1)三种对比、2)rocketMq高性能原因、3)kafka比RocketMQ更高原因、4)RocketMQ场景、5)zk和NameServer对比
一、三种对比
Kafka:1)基于Pull模式来处理,2)高吞吐量,3)大量数据、日志采集业务。
RocketMQ:1)金融领域而生,可靠性高,尤其订单扣款,2)业务削峰,大量交易涌入,后端无法及时
RabbitMQ:数据量没那么大,小公司优先选择
1.Kafka
优点:单机写入TPS百万条/秒、时效ms级、日志领域比较成熟
可用性高,多个副本,少数宕机,不丢数据,不会不可用
Pull方式获取消息, 有序, 控制仅被消费一次;
缺点: Kafka单机超过64个队列/分区,队列越多,load越高,发送消息响应时间变长
使用短轮询方式,实时性取决于轮询间隔时间;
不支持重试;支持消息顺序,但一台代理宕机后,就乱序
2.RocketMQ
设计时参考 Kafka做改进。阿里集团被广泛应用在订单,交易,充值,流计算,消息推送,日志流式处理,binglog分发等场景。
优点:1)吞吐量十万级、可用性高、消息可0丢失2)10亿级消息堆积,不会因堆积性能下降
3.RabbitMQ
优点:1)erlang语言的特性,mq 性能较好,高并发;吞吐量万级,MQ功能比较完备
2)健壮、稳定、易用、跨平台、支持多种语言、文档齐全;
缺点:实现机制重,吞吐量低一些
二、rocketMq高性能原因
1、生产者顺序写入
消息存储是由ConsumeQueue和CommitLog配合完成。一个Topic里面有多个MessageQueue,每个MessageQueue对应一个ConsumeQueue
ConsumeQueue:记消息物理存储地址。
CommitLog:存储文件具体字节信息(文件大小默认1g,名称20位数,左边补0右边为偏移量)。消息顺序写,文件满写下一个
2、消费者随机读
先读逻辑队列consumQue中元数据,再从commitlog找消息体。但入口处rocketmq用package,可以批量地从磁盘读取,作为cache存到内存中,加速后续的读取速度。
随机读具体流程
1)Consumer20s一次负载均衡(默认分页)更新,根据Broker存的ConsumerGroup和Topic信息,把MessageQueue分给不同Consumer,负载策略
2)每个MessageQueue对应一个pullRequest,全部存储到该Consumer的pullRequestQueue队列里面
3)Consumer启动独立后台PullMessageService线程,不停的尝试从pullRequestQueue.take()获取PullRequest
4)捞取到PullRequest会先做缓存校验(默认一个Queue里面缓存待处理消息个数不超过1000个,消息大小不超过100M,否则会延迟50ms再重试),从而保证客户端的缓存负载不会过高
5)PullRequest发送给Broker,如果Broker发现该Queue有待处理的消息,就会直接返回给Consumer,Consumer接收响应以后,重新把该PullRequest丢到自己的pullRequestQueue队列里面,从而重复执行捞取消息的动作,保证消息的及时性
6)PullRequest发送给Broker,如果Broker发现该Queue没有待处理的消息,则会Hold住这个请求,暂不响应给Consumer,默认长轮询是5s重试获取一次待处理消息,如果有新的待处理消息则立刻Response给Consumer,当客户端检测到消息挂起超时(客户端有默认参数 响应超时时间 20s),会重新发起PullRequest给Broker
3、消费模型
(1)push:producer发消息后,broker马上投给consumer。实时性高,但增加broker负载;如push过快,消费端出现问题
(2)pull:producer发消息后,broker等consumer来读取。主动权在消费者;但间隔不好设置,太短浪费,太长消费不及时
(3)长轮询:consumer请求时,broker保持连接一段时间(默认15s),期间内有消息到达,返回给consumer;没返回空,重请求。缺点:服务端保存consumer状态,客户端过多占资源。
默认pushConsumer,本质是pull+长轮询。通过长轮询达到push实时性,又有pull可控性。系统收消息后,自动处理消息和offset(消息偏移量),期间有新consumer加入,自动做负载均衡(集群模式下offset存在broker中; 广播模式下offset存在consumer里)。
ps:也可设pullConsumer,更灵活,代码复杂,手动维护offset、消息存储和状态。
4、zero copy
零拷贝技术有mmap(小文件)及sendfile(大文件),MMQ发送消息通常都很小,rocketmq就以mmap+write实现
三、为什么kafka吞吐量更高,但RocketMQ延时低
kafka的Producer:小消息缓存合并(异步),到一定数量批量发Broker
减少网络io,提高发送性能,但发送者宕机,消息丢失,提高io性能降低可靠性
RocketMQ无法用同样方式
1)Producer调send(),及时处理(延时低),直接发出去,但未发送到Broker,返回成功,宕机,消息丢
2)因为用的Java语言,缓存过多会GC
3)Producer每台机器多线程发送,单Producer每秒数据有限,不可能上万。缓存完全可由上层业务完成。
四、为什么选择RocketMQ
broker里topic的partition数过多,kafka性能 < rocketMq,都用文件存储
1、kafka: 一个分区一个文件,topic多,分区总量也多,对消息刷盘时,文件竞争磁盘,出现性能的下降。顺序读写,一分区最多只被一线程消费
2、rocketMq:所有队列都存一个文件中,每个队列消息量小,topic的增加对rocketMq性能影响小
五、为什么kafka 用zk,rocket mq用自研的NameServer?
与nameServer相比,zookeeper:
1.复杂性:zk:基于CAP,宕机选举,选举耗时;
nameServer:代码量少,节点间互不通信,无法复制。
2.可用性:zk :CP,牺牲可用性
nameServer:部署多台broker实现高可用:没宕机时,轮询队列,发消息;宕机:接下来5分钟跳过BrokerA,选其他broker中队列,发消息,不选举
3、路由注册信息:
zk:数据只写主节点,就复制到从
NameServer:broker启动时,轮询nameServer列表,与每个nameServer长连接,发起注册请求。
1、维护Broker列表,用来动态存储Broker信息。
2、Broker和NameServer心跳检测,30s发给NameServer Broker信息。NameServer会更新时间,最新与当前超过120s,则进行路由剔除
3、Topic路由注册中读写锁:对broker表允许并发读,串行写
https://zhuanlan.zhihu.com/p/163246737?utm_source=wechat_session
https://zhuanlan.zhihu.com/p/161224418