2 minutes
Mq Overall
因为做IM的缘故, 需要使用Queue进行削谷填峰, 这里对比市面上不同的queue, 从不同角度观察Queue.
feature
对比 Kafka/RocketMQ/qmq/pulsar, 不考虑consumer/producer 客户端上的特性, 针对broker实现上对比
Type/feature | kafka | rocketmq | qmq | pulsar |
---|---|---|---|---|
delay message | false | true | true | design |
consume mode | group | 广播/集群 | 广播/group | 广播/group |
ack mode | acc | acc | acc/One | acc/One |
ordered message | partition | queue | queue | sub-topic |
history msg | local | local | backup | offload |
高可用 | partition rebalance | Master/Slave | Master/Slave | bookkeeper + broker leader base zk |
transaction | true | true | false | false |
从定位上来说, kafka是实时流, rocketmq、qmq、pulsar 是MQ, pulsar 比较特殊, 很多feature和常规的MQ不一样, 但是实现了feature的效果, 比如, 在 消息消费模式中, pulsar 本身支持 Shared/Exclusive/Failover, 其中, Shared 和 广播模式一致, 除此之外, pulsar还支持 sub topic 模式, 将topic路由成多个 sub topic, 结合 Exclusive/Failover, 实现 group 模式.
基本思想
- kafka:
- 提供topic、partition视图, 一个topic由多个partition组成
- broker上, 每个partition对应一个存储文件, 每个partition独立分散在不同的broker上, 每个broker上有多个partition存储
- producer通过partition策略, 指定消息分发给topic下具体的某个partition, 然后发送给partition的leader broker.
- consumer消费的时候, 以consumer group的方式进行订阅, broker会先执行join流程, 早期是broker内部分配, v2的版本通过client计算, consumer获取订阅的partition 列表和相应的broker地址, 连接broker地址进行pull方式消息拉取
- Rocketmq
- 提供 topic、queue视图, 一个topic有多个queue组成
- broker上, 所有的topic/queue都写入一个 commit log文件, 通过线程异步的从commit log文件读取构建每个queue的consumer queue文件 + time index 文件.
- producer通过selector策略, 确定发送给topic的一个queue, 然后发送给queue的broker
- consumer以consumer group方式进行订阅, 从name server获取topic的路由信息, 值得注意的是, 订阅关系queue的分配是在consumer端维护的, consumer获取到要消费的queue, consumer会连接到broker上进行消息的拉取
- pulsar
- 提供topic、subTopic视图, 一个topic由多个subTopic组成
- broker上, broker负责处理消息的"存储”(依赖bookkeeper实现)和分发, broker承担着类似代理的角色.
- producer通过 partition router选择指定broker发送
- consumer获取partition的元数据信息 ??????
- qmq
- 类似Rocketmq, 提供 topic、queue视图, 一个topic有多个queue组成,
- 类似Rocketmq, 所有的topic/queue消息存储在一个commit log, 异构构建consumer queue.
- producer ????
- consumer ????
组件设计
- Kafka:
- zookeeper: 存储元数据
- kafka controller: 监听zk的变化, 处理 分区/副本状态, 每个kafka集群使用一个kafka controller.
- group coordinator: 管理 consumer group状态, 比如offset管理和consumer rebalance, 每个consumer group有一个group coordinator.
- broker: 提供文件存储
- Rocketmq:
- namesrv负责元数据的存储, 只有简单的文件/内存实现, 不依赖zk
- filter: 提供消息过滤服务
- broker: 提供文件存储
- pulsar:
- zookeeper: 存储元数据
- bookkeeper: 负责存储消息、offset
- broker: broker和bookkeeper交互, 实现 消息+offset的存储
- 存储的实现上, 依赖bookkeeper, bookkeeper能够高效的实现追加写, broker需要维护bookkeeper的topic和bookkeeper bookie的ledger信息, 映射维护在zk中.
- function: 轻量的计算引擎
- qmq:
- metaserver提供元数据存储, 依赖mysql
- delay-server: 基于时间轮提供了定时任务
扩容
在扩容方式中, 有两种, 希望增加consumer的消费能力需要扩容 和 降低单个broker的负载需要扩容.
consumer扩容
业务执行过程中, 单个consumer的执行能力是有上限的, 除了优化单个consumer的下游耗时, 比如rpc调用、本地计算等, 还有细化consumer的消费粒度, 比如partition级别的consumer, 通过并行partition的消费, 提升consumer的消费能力. 但是, partition consumer的消费能力也是有上限的, 这里分开讨论下.
- 在kafka中, consumer最细的粒度是 partition级别的, 如果需要增加consumer的消费能力, 最终只能够扩容partition, 但是过多的partition, 在consumer发布中, 会导致频繁的rebalance.
- 在Rocketmq, consumer最细的粒度queue, 如果需要增加consumer的消费能力, 只需要 producer用新的queueId向新的broker列表发送消息就可以. consumer端只需要连上新的broker即可, 发布过程无影响.
- 在pulsar中, consumer最细的粒度是宿便 topic, 如果需要增加consumer的消费能力, 只需要添加更多的sub topic, 没有类似kafka的副作用
- qmq中, 模式偏向Rocketmq, 也是异步构建consumer queue, 所以, 增加consumer的消费能力, 也需要添加更多的queue. 没有类似kafkade 副作用
broker扩容
在线上运行时, 会有很多topic/partition, 导致读写文件的OS Cache的红利降低, 这个时候, 需要扩容 broker, 降低单个broker的负载.
-
Kafka: 纯粹的添加broker到Kafka集群并不会引起broker的负载降低, 还需要配合脚本 kafka-reassign-partitions.sh
-
Rocketmq: 官方没有提供很好的方式, 可以参照文章, 需要自己改造
-
pulsar: 因为存储和分发分离的缘故, 所以只需要修改broker和topic的映射关系, 参见文章
-
qmq: qmq 使用range映射逻辑queue到物理queue的映射, 扩容中, 添加broker后, 还需要修改逻辑queue的映射, 之后qmq会完成整个流程. qmq扩容的实现中, 通过版本号区分不同时候的topic/queue -> broker的映射, 并且, 为了保证消息的顺序新, 提出了控制消息的想法, consumer在消费到控制消息之后, 取出里面的版本号, 拉取相应版本的映射关系, 再进行消费.
306 Words
2019-03-24 00:08 +0800