深入浅出消息队列----【Broker 集群】

2024-08-20 18:36

本文主要是介绍深入浅出消息队列----【Broker 集群】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

深入浅出消息队列----【Broker 集群】

  • 单 master
  • 多 master
  • 多 master 多 slave 异步复制
  • 多 master 多 slave 同步复制
  • Dledger

本文仅是文章笔记,整理了原文章中重要的知识点、记录了个人的看法
文章来源:编程导航-鱼皮【yes哥深入浅出消息队列专栏】

请添加图片描述

Broker cluster 可以分为五类:

  1. 单 master
  2. 多 master
  3. 多 master 多 slave 异步复制
  4. 多 master 多 slave 同步复制
  5. Dledger

单 master

如果我们仅部署了一个 Broker 实例,那么就是单 master 模式。

假设这个 master 宕机了,那么生产者发送消息会失败、消费者拉取消息也会失败。

请添加图片描述

此时整个消息队列就不可用了,影响了线上服务的正常执行。

基本上生产环境不会采取单 master 模式,这种一般只会在测试时候使用。

多 master

如果仅部署一个实例风险太大,那么部署两个就能避免 Broker 单点的风险。

此时两个 Broker 会互相瓜分对应的 Topic 下的队列,比如 TopicA 一共分了 8 哥队列,那么 Broker-1 承担其中的 4 哥,Broker-2 承担另外四个。

请添加图片描述

这样一来,生产者给不同队列发送消息,写入消息的压力已经均匀的分配到两个 Broker 身上了,提升了写消息的性能。

如果此时 Broker-1 宕机了,咋办呢?

生产者发送给 Broker-1 的消息会失败,但是还记得之前说过的同步、异步发送消息,如果发送失败,生产者会默认重试的机制吗?

没错,生产者会重试发送消息,而且此时会自动避让上次发送失败的 Broker,因此发给 Broker-1 失败后,会避让 Broker-1,会选择投递到 Broker-2,所以 Broker-1 宕机不会影响消息的发送。

但对于消费者而言,如果想消费队列-1到队列-4的消息,只能从 Broker-1 拉取,此时拉取肯定是失败的,因此**会影响宕机钱已经发送存储至 Broker-1 但还未被消费的消息,**这些消息的实时性无法保证,只能等 Broker-1 恢复。

不会影响新消息的消费,因为新的消息只会被发往 Broker-2。

这时候,只要 Broker-1 重启,那么消费者就能顺利地拉取之前在 Broker-1 的消息了(如果消息已经被刷盘了的话)。

什么叫刷盘呢?消息发送成功了,不代表一定已经被 Broker 持久化了

一般为了性能,消息写入到 Broker 后,还在页缓存中,不会同步刷到磁盘内,也就是消息写到页缓存就返回消息写入成功,此时如果断电了,那么在页缓存内的数据就没了,消息也就丢了。

请添加图片描述

如果想消息一定不丢,只能是同步刷盘,也就是每次消息写入都直接刷盘,这样消息是不会丢的,但是这样性能不好,这就要根据实际场景进行取舍了。

请添加图片描述

这里需要提一下,上述对生产者发送消息没有影响指的是普通消息,如果是顺序消息则会有影响。

因为顺序消息的实现是选择 Topic 下的某一队列进行发送,如果 Broker-1 宕机,本来都需要发送给队列-1 的消息,此时发送到队列-6,那么队列-1 的消息会宕机了还未被消费,队列-6 后来到的消息反而被消费了,此时消息的顺序性就无法保证了。

多 master 多 slave 异步复制

上述多 master 的模式,如果发生一个实例宕机会影响部分消息的实时性,因此就弄了哥 slave 来作为 master 的 backup。

请添加图片描述

每个 master 对应有一个 slave,正常情况下 slave 只会默默同步 master 的消息,不支持消息的直接写入,正常也不会对外提供消费。

只有当 master 繁忙(例如当拉取的消息太久远了或因为消息堆积严重,消息不在 master 内存中,就会返回繁忙,此时消费者就会去 slave 拉取消息,前提是 slaveReadEnable 参数要设置为 true),或者 master 挂了才会被消费者消费。

总而言之,当 master 不太行的时候,消费者可以选择对应的 slave 拉取消息,这样就避免了 master 不行后消息的实时性问题。

所以 slave 就是个备胎,当 master 不好了,消费者才会来找 slave。

那何为异步复制呢?

生产者将消息写到 master 后就返回成功了,然后 slave 回去 master 同步消息,也因此 slave 上的消息相对于 master 会有一定的滞后性,所以当 master 宕机,消费者从 slave 拉取消息的时候,可能会存在个别消息丢失的情况。

看到这可能有同学会有疑惑:为啥 slave 不能被生产者主动写入消息呐?

理论上是可以的,master 和 slave 都支持写入,但这需要实现 master 和 slave 之间数据的双向同步,互相同步消息保证消息的一致性,但这样会比较麻烦,会牵扯一些冲突,比如消息的顺序冲突等等。

多 master 多 slave 同步复制

如果想要保证 slave 的消息不丢失,那么可以采取同步复制的情况。

所谓同步复制其指的是生产者只有在消息存储到 master 以及对应的 slave 中后,才会得到消息写入成功的结果,这样就保证 slave 不会落后于 master。

也因此,在同步复制的情况下,当 master 挂了,消费者从 slave 拉取到的事完整的消息。

请添加图片描述

当然,这样消息是可靠了,但是对性能会有一定的损耗,因为本来生产者仅需等消息写到 master 就直接返回了,现在还得多等一下,等 slave 也写完了才能返回。

不过这种模式还是无法解决消息写入的问题,即 master 宕机后,消息写入的压力无法被 slave 分担到。

Dledger

Dledger 集群算是 RocketMQ 集群的终极版本了。

Dledger 集群指的是一组具有相同名称的 Broker,至少有 3 哥节点,它们组成 RocketMQ-on-Dledger Group,这个集群基于 raft 协议(一致性协议),实现自动的主从切换。

当主节点挂了,那么集群内会自动选举出新的主节点。

按照 raft 协议的术语,主节点就是 leader,想要组成这个集群,至少需要三台机子,也就是至少还得有 2 哥 follower,这样根据投票的规则,当 leader 挂了,才能自动从 follower 中选出新的 leader,此时就自动完成了主从切换,使得消息能正常的写入。

之前的集群模式,当 master 挂了之后,slave 还是 slave,无法自动被提升为 master,而 Dledger 则可以自动完成主从切换,非常顺滑。

请添加图片描述

之所以可以自动从 follower 中投票选取出 leader 是因为 Dledger 会接管 commitlog 的存储,通过 raft 协议,follower 会同步 leader 的 commitlog,保证消息的一致性。

可以简单理解集群中的消息存储都是一致性的,不会出现消息顺序不一致等数据冲突等问题,因此当 leader 没了,可以从 follower 中选一个提升为 leader,反正消息都是对的。

这个模式的缺点就是需要多点机器才能实现 Dledger 集群,等于以前是一个 master 配备一共 slave,现在是一个 leader 至少配备两个 follower。

这篇关于深入浅出消息队列----【Broker 集群】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1090856

相关文章

Java中常见队列举例详解(非线程安全)

《Java中常见队列举例详解(非线程安全)》队列用于模拟队列这种数据结构,队列通常是指先进先出的容器,:本文主要介绍Java中常见队列(非线程安全)的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录一.队列定义 二.常见接口 三.常见实现类3.1 ArrayDeque3.1.1 实现原理3.1.2

C++ RabbitMq消息队列组件详解

《C++RabbitMq消息队列组件详解》:本文主要介绍C++RabbitMq消息队列组件的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1. RabbitMq介绍2. 安装RabbitMQ3. 安装 RabbitMQ 的 C++客户端库4. A

golang实现延迟队列(delay queue)的两种实现

《golang实现延迟队列(delayqueue)的两种实现》本文主要介绍了golang实现延迟队列(delayqueue)的两种实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的... 目录1 延迟队列:邮件提醒、订单自动取消2 实现2.1 simplChina编程e简单版:go自带的time

SpringCloud整合MQ实现消息总线服务方式

《SpringCloud整合MQ实现消息总线服务方式》:本文主要介绍SpringCloud整合MQ实现消息总线服务方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录一、背景介绍二、方案实践三、升级版总结一、背景介绍每当修改配置文件内容,如果需要客户端也同步更新,

Nginx使用Keepalived部署web集群(高可用高性能负载均衡)实战案例

《Nginx使用Keepalived部署web集群(高可用高性能负载均衡)实战案例》本文介绍Nginx+Keepalived实现Web集群高可用负载均衡的部署与测试,涵盖架构设计、环境配置、健康检查、... 目录前言一、架构设计二、环境准备三、案例部署配置 前端 Keepalived配置 前端 Nginx

Redis高可用-主从复制、哨兵模式与集群模式详解

《Redis高可用-主从复制、哨兵模式与集群模式详解》:本文主要介绍Redis高可用-主从复制、哨兵模式与集群模式的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝... 目录Redis高可用-主从复制、哨兵模式与集群模式概要一、主从复制(Master-Slave Repli

一文带你搞懂Redis Stream的6种消息处理模式

《一文带你搞懂RedisStream的6种消息处理模式》Redis5.0版本引入的Stream数据类型,为Redis生态带来了强大而灵活的消息队列功能,本文将为大家详细介绍RedisStream的6... 目录1. 简单消费模式(Simple Consumption)基本概念核心命令实现示例使用场景优缺点2

Java的栈与队列实现代码解析

《Java的栈与队列实现代码解析》栈是常见的线性数据结构,栈的特点是以先进后出的形式,后进先出,先进后出,分为栈底和栈顶,栈应用于内存的分配,表达式求值,存储临时的数据和方法的调用等,本文给大家介绍J... 目录栈的概念(Stack)栈的实现代码队列(Queue)模拟实现队列(双链表实现)循环队列(循环数组

Redis消息队列实现异步秒杀功能

《Redis消息队列实现异步秒杀功能》在高并发场景下,为了提高秒杀业务的性能,可将部分工作交给Redis处理,并通过异步方式执行,Redis提供了多种数据结构来实现消息队列,总结三种,本文详细介绍Re... 目录1 Redis消息队列1.1 List 结构1.2 Pub/Sub 模式1.3 Stream 结

SpringKafka错误处理(重试机制与死信队列)

《SpringKafka错误处理(重试机制与死信队列)》SpringKafka提供了全面的错误处理机制,通过灵活的重试策略和死信队列处理,下面就来介绍一下,具有一定的参考价值,感兴趣的可以了解一下... 目录引言一、Spring Kafka错误处理基础二、配置重试机制三、死信队列实现四、特定异常的处理策略五