RocketMQ和kafka的对比
- 性能:kafka百万级别,rocketmq十万级?
- 单机队列数:rocketmq,单机最高5万个队列,kafka单机超过64个就会load变高,是的响应时间变长。
单机可以创建更多的Topic,Consumer的规模也是和队列数成正比
- 消息实时性:rocketmq使用长轮询,同push方式实时性一致,kafka实时性取决于轮询间隔时间
- 顺序消息:如果broker宕机则,rocketmq会发送失败但不会乱序?,kafka会乱序
- 定时消息:rocketmq支持
- 重试:rocketmq支持
- 消息查询:rocketmq可以通过msgId查询消息
- 消息回溯:rocketmq可以精确到毫秒根据时间来回溯,kafka理论上可以根据offset来回溯消息
- 开发语言的友好性:rocketmq采用JAVA编写
- 消息堆积能力:理论上kafka要比rocketmq强,但rocketmq也有单机亿级别的堆积,基本够用
kafka吞吐量
零拷贝——基于sendfile实现零拷贝
- sendfile系统调用,文件数据被copy至内核缓冲区
- 文件数据从内核缓冲区到用户缓冲区
- 再从用户缓冲区copy至内核中socket相关的缓冲区
- 最后再socket相关的缓冲区copy到协议引擎
在2.1版本减少了第二步,可直接从内核缓冲区到socket缓冲区
在2.4版本之后,文件描述符改变,再次减少了一次copy操作
通过零拷贝技术,就不需要把OS里的数据拷贝到应用缓存,再从应用缓存拷贝到Socket缓存
,这两次拷贝都省略了,所以叫做零拷贝。
对Socket缓存仅仅就是拷贝数据的描述符过去,然后数据直接从OS Cache中发送到网卡上去
磁盘顺序写
页缓存技术
批量压缩
将多个消息一起压缩而不是单个消息压缩
rocketmq核心模块
- broker:接收生产者发来的消息并存储,消费者从这里取得消息
- client:提供发送、接收消息的客户端API
- namesrv:类似于zk,这里保存着TopicName,队列等运行时元信息
- remoting:分布式处理方式,基于Netty4的client/server + fastjson序列化 + 自定义二进制协议。
- store:存储消息,索引引擎。
- filtersrv:消息过滤器Server
- tools:命令行工具
rocketmq核心架构组成
-
NameServer(主要负责对于源数据的处理,包括了对于Topic和路由信息的管理)
-
集群化部署
,是一个功能齐全的服务器,类似于dubbo中的zk,轻量、节点之间相互独立。 -
30秒心跳机制和120秒的故障检查机制
,平时主要在维持心跳和提供Topic-Broker的关系数据 -
每个Broker在启动的时候会到
每一台NameServer注册
,同时每隔30秒会向NameServer发送心跳 -
如果宕机,每个Broker都有Slave节点进行备份,消费者可以继续从Slave上拉去信息。
-
Producer在发送消息前会根据Topic到NameServer获取Brooker的路由信息,
-
Consumer也会定时获取Topic的路由信息。
-
Broker(消息中转角色,负责存储消息,转发消息)
-
每个节点与所有的NameSrv保持长连接及心跳,并定时将Topic注册到NameSrv,底层通信和链接基于Netty实现
-
负责消息的存储,以Topic为维度支持轻量级队列,具有上亿的消息堆积能力,同时保证消息的有序性。
-
Producer(消息生产者,负责生产消息)
-
三种发送方式:同步、异步、单向
-
**同步发送:**发送方发出消息后,收到接收方响应后才发下一个数据包,一般用于通知重要消息。
-
**异步发送:**发送方发出消息后,不等接收方回响应
-
**单向发送:**单向发送是指只负责发送,不等待响应
-
Consumer
-
支持集群消费和广播消费,提供实时的消息订阅机制
mq集群模式
-
多master模式
-
优点:配置简单,单个master宕机或重启维护对应用无影响,性能最高。
-
缺点:单台机器宕机时,这台机器上未被消费的消息在机器恢复之前不可订阅,消息
实时性收到影响
。 -
多master多salve——异步复制(每个master配置一个slave,HA采用异步复制方式,主备毫秒级延迟)
-
优点:即使磁盘损坏,消息丢失非常少,
消息的实时性不受影响
,可用性高,性能高 -
缺点:master宕机,磁盘损坏的情况下回丢失少量消息。
-
多master多salve——同步双写(每个master配置一个slave,HA采用异步同步双写,只有主备都成功才返回成功)
-
优点:数据与服务无单点故障,master宕机,消息无延迟,服务可用性和一致性都非常高
-
缺点:性能比异步复制模式略低(大约10%左右)
-
Dledger 多副本模式
-
3个Broker组成,一个组由一个master,两个slave组成,通过Raft协议来进行选举。
-
优点:master挂后会自动选举新的master。
Raft协议
term选举周期和分裂选举
- Leader
- Follower
- Candidate 候选人
刷盘
先写道commitlog(映射区),再到磁盘
- 同步刷盘
- 异步刷盘
消息重复
mq一般都要保证至少一次,在一些特殊情况难免避免消息重复。
由于网络原因闪断,ACK返回失败等等故障,确认消息没有传送到消息队列,导致消息队列不知道自己已经消费过消息。
- 幂等
- 业务去重
顺序消息
- 生产者顺序发送,不要使用多线程
- 顺序写入broker,使用hash取模队列传同一个hashkey,就可以进去同一个queue队列,由先进先出的特性
- 消费者消费的时候只有一个线程,不然也有可能因为速率不同导致落库有先后
事务消息
- 生产者发送半消息(暂时不能投递消费者的消息),需要等生产者二次确认才可投递。
- MQ服务端给生产者发送ack,告诉生产者半消息成功收到。
- 生产者执行本地数据库事务。
- 执行成功后就告诉broker进行commit。
- 未收到第4步的消息,回查事务状态。
- 发送方收到消息回查后,检查对应消息本地事务的最终结果。
- 发送方根据检查本地事务的最终状态再次二次确认,发送commit或者rollback。
延迟消息
- 可以使用rocketmq的延迟队列来实现,开源版只支持指定精度的延时。
- 对于broker收到延时消息,会进入专门的topic中,有18条专门队列和延迟等级一一对应。
- 定时任务根据上次拉取的偏移量不断从队列中取出消息
消息堆积
-
怎么发现消息堆积
-
消息发送速率,远大于消息消费速率
-
堆积场景
-
消费端阻塞
-
jstack -l pid 去查ConsumeMessageThread的线程状态,如果是blocked那就阻塞了,如果是runnable状态一般来说是正常的
-
消息堆积在内存Buffer
-
扩容或者丢弃部分消息
-
消息堆积在磁盘
-
当不能命中cache时,不可避免的会访问磁盘,会产生大量读IO
-
增加Topic的队列数和消费者数量(一个消费者一个队列)
-
扩大队列容量,提高堆积上限
-
集群故障
-
有brocker挂了
保证消息不丢失
如何知道消息丢失?哪些环节可能丢失?如何确保消息丢失?
消息可能丢失的阶段有:
-
消息产生阶段:
-
从消息生产出来提交给MQ的过程中,只要能正常收到Broker的ack就表示发送成功。
-
消息存储阶段:
-
这个一般交给mq中间件来保证,比如Broker会有主从,有同步复制和异步复制两种
-
如果主挂了,消费者也可以自动从备机中获取消息
-
追求强一致性的话,可以等同步两个节点后再返回ack
-
消息消费阶段:
-
消费端的话等业务逻辑执行完后,再返回成功,失败的话也会有mq重试机制保证消息不丢失
上述方案时从mq架构设计上描述在各阶段都有对应的防丢失措施,
在某些必要情况下可以添加业务消息检测,比如给每个发出的消息里都指定一个全局唯一id或者连续递增的id生成落库,拦截器检测消息版本号更新消费状态。
或者有些业务场景可以添加中间态来检测,比如在完成和奖品发放成功中有一个发放中的中间态,可以通过数据库来检查是否有漏发情况,可以定时任务补发。
存储结构
RocketMQ文件主要包括Commitlog文件,ConsumeQueue文件,Index文件。
Commitlog 消息存储的物理文件
RocketMQ将所有主题的消息存储在同一个文件中,确保消息发送时按顺序写文件,尽最大能力确保消息发送的高可用性和高吞吐量。
ConsumeQueue 消息消费的逻辑队列(异步写入)
消息中间件一般都是基于主题的订阅与发布模式,消息消费时必须按照主题进行筛选消息,显然从commitlog中按照同topic去筛选消息效率很低,为了提高根据主题检索消息的效率,RocketMQ引入了ConsumeQueue文件。这里包含消息在CommitLog中的物理偏移量。(commitLogOffset、msgSize、tagsCode)
indexFile 消息索引文件(异步写入)
提供了对CommitLog进行数据检索,提供了一种通过key或者时间区间来查找CommitLog中的消息的方法
Kafka的分区副本和RocketMQ的队列的区别
rockemq的队列
rocketmq的每个Topic都会有若干个队列,分布于集群中各个broker上,每个队列只能由一个消费者进行订阅消费,但一个向消费者可以订阅多个队列。
Kafka
分区机制使得kafka具备了水平扩展的能力,在分区上,kafka还可以设置分区副本,大大提高了消息的可靠性。
和rocketmq一样,一个分区只能由一个消费者进行订阅消费,一个消费者可以消费多个分区。
可以通过调整主题分区数量来提高消息的吞吐量,还可以设置分区的副本因子。