Skip to content

Commit

Permalink
Site updated: 2024-01-25 20:39:30
Browse files Browse the repository at this point in the history
  • Loading branch information
yulewei committed Jan 25, 2024
1 parent b5ee4e9 commit 05d6cb5
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 116 deletions.
44 changes: 26 additions & 18 deletions 2024/01/rocketmq-kafka-sharding-replication/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
<meta property="og:image" content="https://static.nullwy.me/kafka-architecture.png">
<meta property="og:image" content="https://static.nullwy.me/kafka-kraft-mode.png">
<meta property="article:published_time" content="2024-01-18T12:36:00.000Z">
<meta property="article:modified_time" content="2024-01-24T15:54:08.124Z">
<meta property="article:modified_time" content="2024-01-25T12:38:25.506Z">
<meta property="article:author" content="nullwy">
<meta property="article:tag" content="架构">
<meta property="article:tag" content="可扩展性">
Expand Down Expand Up @@ -386,21 +386,25 @@ <h1 id="RocketMQ">RocketMQ</h1>
<li>Borker 节点分为主从(Master/Slave)两种角色,支持异步复制(默认)和同步复制两种复制模式。配置项 <code>brokerRole</code> 用于配置节点的主从角色和复制模式,默认值为 <code>ASYNC_MASTER</code>,可配置为 <code>SYNC_MASTER</code>/<code>ASYNC_MASTER</code>/<code>SLAVE</code></li>
</ul>
</li>
<li><strong>主从读写分离</strong><sup class="footnote-ref"><a href="#fn6" id="fnref6">[6]</a></sup>:Master Borker 可写可读,Slave Borker 只允许读。配置项 <code>slaveReadEnable</code> 用于配置是否允许消息从从节点读取,默认 <code>false</code>。如果 <code>slaveReadEnable=true</code>,并且当前消息堆积量超过物理内存 40%(由配置项 <code>accessMessageInMemoryMaxRatio</code> 控制),则建议从 Slave Borker 拉取消息,否则还是从 Master Borker 拉取消息。
<ul>
<li>相关源码:PullMessageProcessor#<a target="_blank" rel="noopener" href="https://github.com/apache/rocketmq/blob/rocketmq-all-4.9.0/broker/src/main/java/org/apache/rocketmq/broker/processor/PullMessageProcessor.java#L266">processRequest</a></li>
</ul>
</li>
<li><strong>消息可靠性</strong><sup class="footnote-ref"><a href="#fn7" id="fnref7">[7]</a></sup><sup class="footnote-ref"><a href="#fn8" id="fnref8">[8]</a></sup>:主要影响的配置项是主从节点的副本复制方式和磁盘刷盘方式。
<li><strong>消息可靠性</strong><sup class="footnote-ref"><a href="#fn6" id="fnref6">[6]</a></sup><sup class="footnote-ref"><a href="#fn7" id="fnref7">[7]</a></sup>:主要影响的配置项是主从节点的副本复制方式和磁盘刷盘方式。
<ul>
<li>对于 <code>Borker</code> 单点故障情况,若采用主从异步复制,可保证 99% 的消息不丢,但是仍然会有极少量的消息可能丢失。若采用主从同步复制可以完全避免单点,但相对损失影响性能,适合对消息可靠性要求极高的场合。</li>
<li>配置项 <code>FlushDiskType</code> 用于控制磁盘刷盘方式,可配置为异步刷盘 <code>ASYNC_FLUSH</code>(默认)和同步刷盘 <code>SYNC_FLUSH</code>。同步刷盘会损失很多性能,但是也更可靠。</li>
<li>生产环境下的<strong>推荐配置</strong><sup class="footnote-ref"><a href="#fn9" id="fnref9">[9]</a></sup>,把主从节点的磁盘刷盘方式都配置为<strong>异步刷盘</strong>,主从节点之间复制方式配置为<strong>同步复制</strong>,这种配置方式是相对兼顾了性能和可靠性。如果对消息丢失零容忍,则建议配置为同步复制、同步刷盘方式。</li>
<li>生产环境下的<strong>推荐配置</strong><sup class="footnote-ref"><a href="#fn8" id="fnref8">[8]</a></sup>,把主从节点的磁盘刷盘方式都配置为<strong>异步刷盘</strong>,主从节点之间复制方式配置为<strong>同步复制</strong>,这种配置方式是相对兼顾了性能和可靠性。如果对消息丢失零容忍,则建议配置为同步复制、同步刷盘方式。</li>
<li>对于副本系统来说,在系统设计或配置时,必须要在副本一致性和延迟(性能)之间做<strong>权衡</strong>,参见 <a target="_blank" rel="noopener" href="https://en.wikipedia.org/wiki/PACELC_theorem">PACELC</a> 理论(CAP 理论的扩展版)。</li>
</ul>
</li>
</ul>
</li>
<li><strong>数据路由寻址</strong>
<ul>
<li><strong>主从读写分离</strong><sup class="footnote-ref"><a href="#fn9" id="fnref9">[9]</a></sup>:Master Borker 可写可读,Slave Borker 只允许读。配置项 <code>slaveReadEnable</code> 用于配置是否允许消息从从节点读取,默认 <code>false</code>。如果 <code>slaveReadEnable=true</code>,并且当前消息堆积量超过物理内存 40%(由配置项 <code>accessMessageInMemoryMaxRatio</code> 控制),则建议从 Slave Borker 拉取消息,否则还是从 Master Borker 拉取消息。
<ul>
<li>相关源码:PullMessageProcessor#<a target="_blank" rel="noopener" href="https://github.com/apache/rocketmq/blob/rocketmq-all-4.9.0/broker/src/main/java/org/apache/rocketmq/broker/processor/PullMessageProcessor.java#L266">processRequest</a></li>
</ul>
</li>
</ul>
</li>
<li><strong>集群配置和协调</strong>:由 NameServer 集群和 DLedger 模块负责
<ul>
<li>NameServer 集群负责存储消息队列路由信息、Borker 集群注册信息等元数据,是 ZooKeeper 的轻量级替代。</li>
Expand Down Expand Up @@ -486,12 +490,6 @@ <h1 id="Kafka">Kafka</h1>
</li>
</ul>
</li>
<li><strong>主从读写分离</strong>
<ul>
<li>Kafka 2.4 之前,leader 副本可写可读,follower 副本不可读,仅用于备份。消息消费者只允许读取 leader 副本,follower 副本不处理来自消费者的请求。当 leader 所在的节点发生崩溃,其中一个 follower 就会被 Controller 选举为新 leader。</li>
<li>Kafka 2.4 开始(2019.12 发布)支持读取 follower 副本来消费消息,参见 <a target="_blank" rel="noopener" href="https://issues.apache.org/jira/browse/KAFKA-8443">KIP-392</a></li>
</ul>
</li>
<li><strong>消息可靠性</strong>
<ul>
<li>优先考虑消息可靠性(无消息丢失)又同时兼顾性能的常用的配置是,复制系数的配置值为 <code>3</code>,ISR 集合大小的配置值为 <code>min.insync.replicas=2</code>,消息发送确认的配置值为 <code>acks=all</code><sup class="footnote-ref"><a href="#fn14" id="fnref14">[14]</a></sup><sup class="footnote-ref"><a href="#fn15" id="fnref15">[15]</a></sup></li>
Expand All @@ -500,6 +498,16 @@ <h1 id="Kafka">Kafka</h1>
</li>
</ul>
</li>
<li><strong>数据路由寻址</strong>
<ul>
<li><strong>主从读写分离</strong>
<ul>
<li>Kafka 2.4 之前,leader 副本可写可读,follower 副本不可读,仅用于备份。消息消费者只允许读取 leader 副本,follower 副本不处理来自消费者的请求。当 leader 所在的节点发生崩溃,其中一个 follower 就会被 Controller 选举为新 leader。</li>
<li>Kafka 2.4 开始(2019.12 发布)支持读取 follower 副本来消费消息,参见 <a target="_blank" rel="noopener" href="https://issues.apache.org/jira/browse/KAFKA-8443">KIP-392</a></li>
</ul>
</li>
</ul>
</li>
<li><strong>集群配置和协调</strong>:由 <strong>Controller 控制器</strong>负责
<ul>
<li><strong>ZooKeeper 模式</strong><sup class="footnote-ref"><a href="#fn17" id="fnref17">[17]</a></sup>:ZooKeeper 负责存储元数据,包括 Broker、Topic、分区、副本、路由等信息,以及负责选举 Controller 角色的 Broker,整个集群只有一个 Controller 角色的 Broker。Controller 角色的 Broker 节点的主要职责是 Broker 集群成员管理、Topic 管理(创建、删除、增加分区)、分区重分配、选举新的分区 leader 副本等,这些职责的实现重度依赖 ZooKeeper。</li>
Expand All @@ -525,13 +533,13 @@ <h1 id="参考资料">参考资料</h1>
</li>
<li id="fn5" class="footnote-item"><p>2019-03 张乘辉:深度解析RocketMQ Topic的创建机制 <a target="_blank" rel="noopener" href="https://objcoding.com/2019/03/31/rocketmq-topic/">https://objcoding.com/2019/03/31/rocketmq-topic/</a> <a href="#fnref5" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn6" class="footnote-item"><p>2019-09 张乘辉:RocketMQ主从读写分离机制 <a target="_blank" rel="noopener" href="https://objcoding.com/2019/09/22/rocketmq-read-write-separation/">https://objcoding.com/2019/09/22/rocketmq-read-write-separation/</a> <a href="#fnref6" class="footnote-backref">↩︎</a></p>
<li id="fn6" class="footnote-item"><p>Apache RocketMQ 4.9.x开发者指南:特性:4 消息可靠性 <a target="_blank" rel="noopener" href="https://github.com/apache/rocketmq/blob/4.9.x/docs/cn/features.md">https://github.com/apache/rocketmq/blob/4.9.x/docs/cn/features.md</a> <a href="#fnref6" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn7" class="footnote-item"><p>Apache RocketMQ 4.9.x开发者指南:特性:4 消息可靠性 <a target="_blank" rel="noopener" href="https://github.com/apache/rocketmq/blob/4.9.x/docs/cn/features.md">https://github.com/apache/rocketmq/blob/4.9.x/docs/cn/features.md</a> <a href="#fnref7" class="footnote-backref">↩︎</a></p>
<li id="fn7" class="footnote-item"><p>2016-04 Kafka vs RocketMQ——单机系统可靠性 <a target="_blank" rel="noopener" href="https://web.archive.org/web/0/http://jm.taobao.org/2016/04/28/kafka-vs-rocktemq-4">https://web.archive.org/web/0/http://jm.taobao.org/2016/04/28/kafka-vs-rocktemq-4</a> <a href="#fnref7" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn8" class="footnote-item"><p>2016-04 Kafka vs RocketMQ——单机系统可靠性 <a target="_blank" rel="noopener" href="https://web.archive.org/web/0/http://jm.taobao.org/2016/04/28/kafka-vs-rocktemq-4">https://web.archive.org/web/0/http://jm.taobao.org/2016/04/28/kafka-vs-rocktemq-4</a> <a href="#fnref8" class="footnote-backref">↩︎</a></p>
<li id="fn8" class="footnote-item"><p>2018-12 How much memory should we use for broker and namesrv when using cluster mode? #614 <a target="_blank" rel="noopener" href="https://github.com/apache/rocketmq/issues/614">https://github.com/apache/rocketmq/issues/614</a> <a href="#fnref8" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn9" class="footnote-item"><p>2018-12 How much memory should we use for broker and namesrv when using cluster mode? #614 <a target="_blank" rel="noopener" href="https://github.com/apache/rocketmq/issues/614">https://github.com/apache/rocketmq/issues/614</a> <a href="#fnref9" class="footnote-backref">↩︎</a></p>
<li id="fn9" class="footnote-item"><p>2019-09 张乘辉:RocketMQ主从读写分离机制 <a target="_blank" rel="noopener" href="https://objcoding.com/2019/09/22/rocketmq-read-write-separation/">https://objcoding.com/2019/09/22/rocketmq-read-write-separation/</a> <a href="#fnref9" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn10" class="footnote-item"><p>2019-08 金融通、武文良:RocketMQ 实现高可用多副本架构的关键:DLedger—基于raft协议的commitlog存储库 <a target="_blank" rel="noopener" href="https://mp.weixin.qq.com/s/0nmWq29FN17vNzt0njRE-Q">https://mp.weixin.qq.com/s/0nmWq29FN17vNzt0njRE-Q</a> <a target="_blank" rel="noopener" href="https://www.infoq.cn/article/7xeJrpDZBa9v*GDZOFS6">https://www.infoq.cn/article/7xeJrpDZBa9v*GDZOFS6</a> <a href="#fnref10" class="footnote-backref">↩︎</a></p>
</li>
Expand Down
6 changes: 3 additions & 3 deletions atom.xml

Large diffs are not rendered by default.

Binary file added posts/media/redis-cluster-ha-architecture.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 13 additions & 11 deletions posts/rocketmq-kafka-sharding-replication.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,14 @@ RocketMQ 和 Kafka 的历史演进时间线:
- **复制系数**:由消息队列所属的 Broker Group 的下 Borker 总数量决定(每个 Broker Group 下有一个 Master Borker 和零到若干个 Slave Borker)
- **副本更新传播策略**
- Borker 节点分为主从(Master/Slave)两种角色,支持异步复制(默认)和同步复制两种复制模式。配置项 `brokerRole` 用于配置节点的主从角色和复制模式,默认值为 `ASYNC_MASTER`,可配置为 `SYNC_MASTER`/`ASYNC_MASTER`/`SLAVE`
- **主从读写分离**[^6]:Master Borker 可写可读,Slave Borker 只允许读。配置项 `slaveReadEnable` 用于配置是否允许消息从从节点读取,默认 `false`。如果 `slaveReadEnable=true`,并且当前消息堆积量超过物理内存 40%(由配置项 `accessMessageInMemoryMaxRatio` 控制),则建议从 Slave Borker 拉取消息,否则还是从 Master Borker 拉取消息。
- 相关源码:PullMessageProcessor#[processRequest](https://github.com/apache/rocketmq/blob/rocketmq-all-4.9.0/broker/src/main/java/org/apache/rocketmq/broker/processor/PullMessageProcessor.java#L266)
- **消息可靠性**[^7][^8]:主要影响的配置项是主从节点的副本复制方式和磁盘刷盘方式。
- **消息可靠性**[^6][^7]:主要影响的配置项是主从节点的副本复制方式和磁盘刷盘方式。
- 对于 `Borker` 单点故障情况,若采用主从异步复制,可保证 99% 的消息不丢,但是仍然会有极少量的消息可能丢失。若采用主从同步复制可以完全避免单点,但相对损失影响性能,适合对消息可靠性要求极高的场合。
- 配置项 `FlushDiskType` 用于控制磁盘刷盘方式,可配置为异步刷盘 `ASYNC_FLUSH`(默认)和同步刷盘 `SYNC_FLUSH`。同步刷盘会损失很多性能,但是也更可靠。
- 生产环境下的**推荐配置**[^9],把主从节点的磁盘刷盘方式都配置为**异步刷盘**,主从节点之间复制方式配置为**同步复制**,这种配置方式是相对兼顾了性能和可靠性。如果对消息丢失零容忍,则建议配置为同步复制、同步刷盘方式。
- 生产环境下的**推荐配置**[^8],把主从节点的磁盘刷盘方式都配置为**异步刷盘**,主从节点之间复制方式配置为**同步复制**,这种配置方式是相对兼顾了性能和可靠性。如果对消息丢失零容忍,则建议配置为同步复制、同步刷盘方式。
- 对于副本系统来说,在系统设计或配置时,必须要在副本一致性和延迟(性能)之间做**权衡**,参见 [PACELC](https://en.wikipedia.org/wiki/PACELC_theorem) 理论(CAP 理论的扩展版)。
- **数据路由寻址**
- **主从读写分离**[^9]:Master Borker 可写可读,Slave Borker 只允许读。配置项 `slaveReadEnable` 用于配置是否允许消息从从节点读取,默认 `false`。如果 `slaveReadEnable=true`,并且当前消息堆积量超过物理内存 40%(由配置项 `accessMessageInMemoryMaxRatio` 控制),则建议从 Slave Borker 拉取消息,否则还是从 Master Borker 拉取消息。
- 相关源码:PullMessageProcessor#[processRequest](https://github.com/apache/rocketmq/blob/rocketmq-all-4.9.0/broker/src/main/java/org/apache/rocketmq/broker/processor/PullMessageProcessor.java#L266)
- **集群配置和协调**:由 NameServer 集群和 DLedger 模块负责
- NameServer 集群负责存储消息队列路由信息、Borker 集群注册信息等元数据,是 ZooKeeper 的轻量级替代。
- **自动选举主节点**[^10][^11]
Expand Down Expand Up @@ -112,12 +113,13 @@ RocketMQ 架构,以及各个 Borker 下的分区和副本分布示例,如下
-`acks=0``acks=1` 时,相当于**异步复制**
-`acks=all` 并且 `min.insync.replicas` 值大于 `1` 并小于 Broker 节点总数时,相当于**半同步复制**
-`acks=all` 并且 `min.insync.replicas` 值等于 Broker 节点总数时,相当于**全同步复制**
- **主从读写分离**
- Kafka 2.4 之前,leader 副本可写可读,follower 副本不可读,仅用于备份。消息消费者只允许读取 leader 副本,follower 副本不处理来自消费者的请求。当 leader 所在的节点发生崩溃,其中一个 follower 就会被 Controller 选举为新 leader。
- Kafka 2.4 开始(2019.12 发布)支持读取 follower 副本来消费消息,参见 [KIP-392](https://issues.apache.org/jira/browse/KAFKA-8443)
- **消息可靠性**
- 优先考虑消息可靠性(无消息丢失)又同时兼顾性能的常用的配置是,复制系数的配置值为 `3`,ISR 集合大小的配置值为 `min.insync.replicas=2`,消息发送确认的配置值为 `acks=all`[^14][^15]
- Kafka 默认异步刷盘,没有直接的同步刷盘相关配置项。Kafka 会在重启之前和关闭日志片段(默认 1 GB 大小时关闭)时将消息冲刷到磁盘上,或者等到 Linux 系统页面缓存被填满时冲刷。虽然 Kafka 提供刷盘的时间间隔和刷盘的消息条数的配置项,但是官方文档不建议设置,推荐将刷盘的工作交给操作系统完成[^16]。相对于刷盘,复制提供了更强的可靠性保障。
- **数据路由寻址**
- **主从读写分离**
- Kafka 2.4 之前,leader 副本可写可读,follower 副本不可读,仅用于备份。消息消费者只允许读取 leader 副本,follower 副本不处理来自消费者的请求。当 leader 所在的节点发生崩溃,其中一个 follower 就会被 Controller 选举为新 leader。
- Kafka 2.4 开始(2019.12 发布)支持读取 follower 副本来消费消息,参见 [KIP-392](https://issues.apache.org/jira/browse/KAFKA-8443)
- **集群配置和协调**:由 **Controller 控制器**负责
- **ZooKeeper 模式**[^17]:ZooKeeper 负责存储元数据,包括 Broker、Topic、分区、副本、路由等信息,以及负责选举 Controller 角色的 Broker,整个集群只有一个 Controller 角色的 Broker。Controller 角色的 Broker 节点的主要职责是 Broker 集群成员管理、Topic 管理(创建、删除、增加分区)、分区重分配、选举新的分区 leader 副本等,这些职责的实现重度依赖 ZooKeeper。
- **KRaft 模式**[^18]:Kafka 2.8 开始,Kafka 开始用基于 Raft 的控制器替换基于 ZooKeeper 的控制器,新控制器叫作 KRaft。KRaft 模块被集成在 Borker 节点的进程中,去掉了对 ZooKeeper 的依赖,简化了整体架构。
Expand All @@ -137,10 +139,10 @@ Kafka 在 KRaft 模式下的架构图,如下图所示[^18]:
[^3]: 2017-03 阿里冯嘉鼬神:Apache RocketMQ背后的设计思路与最佳实践 <https://developer.aliyun.com/article/71889>
[^4]: Apache RocketMQ 4.9.x开发者指南 <https://github.com/apache/rocketmq/blob/4.9.x/docs/cn>
[^5]: 2019-03 张乘辉:深度解析RocketMQ Topic的创建机制 <https://objcoding.com/2019/03/31/rocketmq-topic/>
[^6]: 2019-09 张乘辉:RocketMQ主从读写分离机制 <https://objcoding.com/2019/09/22/rocketmq-read-write-separation/>
[^7]: Apache RocketMQ 4.9.x开发者指南:特性:4 消息可靠性 <https://github.com/apache/rocketmq/blob/4.9.x/docs/cn/features.md>
[^8]: 2016-04 Kafka vs RocketMQ——单机系统可靠性 <https://web.archive.org/web/0/http://jm.taobao.org/2016/04/28/kafka-vs-rocktemq-4>
[^9]: 2018-12 How much memory should we use for broker and namesrv when using cluster mode? #614 <https://github.com/apache/rocketmq/issues/614>
[^6]: Apache RocketMQ 4.9.x开发者指南:特性:4 消息可靠性 <https://github.com/apache/rocketmq/blob/4.9.x/docs/cn/features.md>
[^7]: 2016-04 Kafka vs RocketMQ——单机系统可靠性 <https://web.archive.org/web/0/http://jm.taobao.org/2016/04/28/kafka-vs-rocktemq-4>
[^8]: 2018-12 How much memory should we use for broker and namesrv when using cluster mode? #614 <https://github.com/apache/rocketmq/issues/614>
[^9]: 2019-09 张乘辉:RocketMQ主从读写分离机制 <https://objcoding.com/2019/09/22/rocketmq-read-write-separation/>
[^10]: 2019-08 金融通、武文良:RocketMQ 实现高可用多副本架构的关键:DLedger—基于raft协议的commitlog存储库 <https://mp.weixin.qq.com/s/0nmWq29FN17vNzt0njRE-Q> <https://www.infoq.cn/article/7xeJrpDZBa9v*GDZOFS6>
[^11]: 2022-09 金融通:RocketMQ 5.0:面向消息与流的云原生高可用架构 <https://mp.weixin.qq.com/s/bb6cGUxpsAoU-IqBgmSJHw>

Expand Down
Loading

0 comments on commit 05d6cb5

Please sign in to comment.