栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

后端常用消息中间件RocketMq与kafka,11个不同点总结,只看这一篇文章就够了(吐血整理)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

后端常用消息中间件RocketMq与kafka,11个不同点总结,只看这一篇文章就够了(吐血整理)

RocketMq与kafka不同点总结! 1.RocketMQ批量发送做的不好,无提供压缩机制 Kafka:

1.批量发送
buffer.memory
RecordAccumulator 缓冲区总大小,默认 32m。
batch.size 缓冲区每一批数据最大值,默认 16k。适当增加该值,可以提高吞吐量,但是如果该值设置太大,会导致数据 传输延迟增加。
Kafka比如设置延时5ms(默认为0ms)或者满了就发,更灵活
而如果批量里那个出现问题就去在应答区单独重试,而不是整批重试
2.支持压缩机制
生产端压缩,消费者解压缩
消息压缩(默认不压缩)
在对大数据处理上,瓶颈往往体现在网络上而不是CPU(压缩和解压会耗掉部分CPU资源)。
RocketMq没有封装好的方法去压缩消息
3.消费者批量发

RocketMq(kafka快)

没有默认批量机制
可以批量发送大小
默认情况下,一批发送的消息总大小不能超过4MB字节。如果想超出该值,有两种解决方案:拆分成小个4MB,不可以设置4MB大小,没有kafka灵活
问题:若出现了问题,那么本批次所有消息都需要全部重新拉取。
2.RocketMq没有封装好的API去压缩消息

2.nameServer注册中心与zookeeper区别 nameServer(全局无序)

优点: NameServer 集群搭建简单,扩容简单。
缺点:对于 Broker ,必须明确指出所有 NameServer 地址。否则未指出的将不会去注册。也正因为如此, NameServer 并不能随便扩容。因为,若 Broker 不重新配置,新增的 NameServer 对于 Broker 来说是不可见的,其不会向这个 NameServer 进行注册。
Broker 节点为了证明自己是活着的,为了维护与 NameServer 间的长连接,会将最新的信息以 心跳包 的 方式上报给 NameServer ,每 30 秒发送一次心跳。
如何保证nameServer节点同步?
在Broker节点启动时,轮询 NameServer 列表,与每个 NameServer 节点建立长连接,发起注册 请求。在 NameServer 内部维护着⼀个 Broker 列表,用来动态存储 Broker 的信息。
NameServer路由信息有四个Map,
topic信息,brokerIp等信息,集群信息,心跳具体信息

Zookeeper(有序)

注意,这是与其它像 zk 、 Eureka 、 Nacos 等注册中心不同的地方。
这种 NameServer 的无状态方式,有什么优缺点:
无状态:即 NameServer 集群中的各 个节点间是无差异的,各节点间相互不进行信息通讯。
Zookeeper各个节点之前都有监控,宕机就通知所有节点。可以动态增加broker和服务节点数量,有监控,会调整。不想nameServer还得重新改配置文件。
Zookeeper保证数据同步原理
1、leader 接受到消息请求后,将消息赋予给一个全局唯一的64位自增id,叫:zxid,通过zxid的代销比较即可以实现因果有序的这个特征
2、leader 为每个follower 准备了一个FIFO队列(通过TCP协议来实现,以实现了全局有序这个特点)将带有zxid的消息作为一个提案(proposal)分发给所有的follower
3、当follower接受到proposal,先把proposal写到磁盘,写入成功以后再向leader恢复一个ack
4、当leader 接受到合法数量(超过半数节点)的 ack,leader 就会向这些follower发送commit命令,同时会在本地执行该消息
5、当follower接受到消息的commit命令以后,就会提交该消息

3.高级特性(kafka快) 1延时队列 2消息查询

1 按照MessageId查询消息
RocketMQ中的MessageId的长度总共有16字节,其中包含了消息存储主机地址(IP地址和端口),消息Commit Log offset。“按照MessageId查询消息”在RocketMQ中具体做法是:Client端从MessageId中解析出Broker的地址(IP地址和端口)和Commit Log的偏移地址后封装成一个RPC请求后通过Remoting通信层发送(业务请求码:VIEW_MESSAGE_BY_ID)。Broker端走的是QueryMessageProcessor,读取消息的过程用其中的 commitLog offset 和 size 去 commitLog 中找到真正的记录并解析成一个完整的消息返回。

2 按照Message Key查询消息
按照Message Key查询消息,主要是基于RocketMQ的IndexFile索引文件来实现的。RocketMQ的索引文件逻辑结构,类似JDK中HashMap的实现。

3死信队列

消息的 TTL 过期时
消息队列达到最大长度
消息不能入队时。

4.定时消息(特性) 4.日志文件存储(前边一样,后边kafka快) MQ:

即无论当前Broker中存放着多少Topic的消息,这些消息都是被顺序写入到了mappedFile文件中的。也就是说,这些消息在Broker中存放时并没有被按照Topic进行分类存放。
所有队列都放在一个文件上。
写好些,读不好读。

Kafka:

但是kafka是一个分区一个文件,当topic过多,分区的总量也会增加,kafka中存在过多的文件,当对消息刷盘时,topic太多,分区太多,导致文件散落,有序写变成随机写。
读好读,写不好写。

5.事务不同 Kafka事务(保证的是自身消息的事务)

重点总结
保证的全分区幂等性,消息只发一次,并且保证发送多条分区的任务要发送成功都成功,失败都失败。
采取两阶段提交协议,借助broker内部事务协调者
保证精确一次发送
对于一些非常重要的信息,比如和钱相关的数据,要求数据既不能重复也不丢失。

Kafka 0.11版本以后,引入了一项重大特性:幂等性和事务。
幂等性就是指Producer不论向Broker发送多少次重复数据,Broker端都只会持久化一条,保证了不重复。
具有相同主键的消息提交时 保证有序和幂等。Pid保证单区内幂等,SeqNumber保证单区内有序。
事务ID加pid单区幂等id 形成全局唯一id(保证全局幂等)
即使客户端挂掉了,它重启后也能继续处理未完成的事务,因为有全局id

事务应用场景
最简单的需求是producer发的多条消息组成一个事务这些消息需要对consumer同时可见或者同时不可见 。
producer可能会给多个topic,多个partition发消息,这些消息也需要能放在一个事务里面,这就形成了一个典型的分布式事务。
kafka的应用场景经常是应用先消费一个topic,然后做处理再发到另一个topic,这个consume-transform-produce过程需要放到一个事务里面,比如在消息处理或者发送的过程中如果失败了,消费位点也不能提交
Kafka+本地消息表解决分布式事务(实现类似RocketMQ功能)
生产者本地业务逻辑执行完成之后,往数据库插入一条待发送的数据(在一个事务内,要么全部成功,要么全部失败)
然后从数据库去取这条待发送的数据,发送到kafka,状态更新为已发送(一个事务)。
消费者从kafka取出消息之后,将消息数据库数据更新为待消费(在一个事务内,要么全部成功,要么全部失败)
然后从数据库去取这条待消费的数据,进行消费端的业务处理,处理完成之后,状态更新为已消费(一个事务)。
定时任务扫描数据库的待发送数据,如果有,则代表有生产者本地执行成功,
但是发送到kafka失败的情况,那就重新发送。
定时任务扫描数据库的待消费数据,如果有,则代表有消费者消息取到了,
但是执行本地逻辑没有成功,那就重新执行消费逻辑。
三、优缺点
优点:
事务吞吐量大. 因为不需要等待其他数据源响应.
容错性好. A服务在发布事件的时候, B服务甚至可以不在线。
缺点:
1、容易出现较多的中间状态,保证不了实时性。
比如生产者已经发送数据了,但是消费者才执行到第一步
(拉取消息,留证据到本地数据库消息表),这个时候用户登录之后,
可能就看不到消费后的数据。在实时性要求高的业务不太适用。
2、与具体业务场景绑定,偶尔性强,不可以共用。
四、适用场景:
1、实时性要求不高,只要满足最终一致性的情况
2、生产者的逻辑是否成功,不依赖于消费者的逻辑执行是否成功的情况,
比如:
下订单和出库,这就是典型的生产者的逻辑要依赖于消费者的逻辑
是否执行成功。
因为下订单,如果库存不够,那么订单也是不能成功的。

RocketMq事务(外部事务)

真正实现了分布式事务的连接,而不是自身的消息事务。
半事务消息
本地事务状态
消息回查(防止确认ack因网络堵塞而导致系统停止)
1.成功 2.回滚 3.未知

整体流程
Producer执行本地事务;
Step4:本地事务完毕,根据事务的状态,Producer向Broker发送二次确认消息,确认该Half Message的Commit或者Rollback状态。Broker收到二次确认消息后,对于Commit状态,则直接发送到Consumer端执行消费逻辑,而对于Rollback则直接标记为失败,一段时间后清除,并不会发给Consumer。正常情况下,到此分布式事务已经完成,剩下要处理的就是超时问题,即一段时间后Broker仍没有收到Producer的二次确认消息;
Step5:针对超时状态,Broker主动向Producer发起消息回查;
Step6:Producer处理回查消息,返回对应的本地事务的执行结果;
Step7:Broker针对回查消息的结果,执行Commit或Rollback操作,同Step4。

6.主从复制不同(也差不多) MQ:

复制策略
复制策略是Broker的Master与Slave间的数据同步方式。
分为同步复制与异步复制:
同步复制:消息写入master后,master会等待slave同步数据成功后才向producer返回成功ACK
异步复制:消息写入master后,master立即向producer返回成功ACK,无需等待slave同步数据成功
异步复制策略会降低系统的写入延迟,RT变小,提高了系统的吞吐量

Kakfa

副本机制保障高可用和一致性。Ack机制 = -1
所有主副本都同步完ack,可同步可异步。
切换时间短,直接选取最近的副本。
Zookeeper 中ISR活着的,AR第一个。

7.有序性保证不一样 Kafka通过幂等性可保证有序(批量发送的缺点)

具有相同主键的消息提交时 保证有序和幂等。Pid保证单区内幂等,SeqNumber保证单区内有序。
分区策略选择key。保证一个分区。或者同一个指定区号。

MQ:

队列选择器传参
我们可使用Hash取模法,让同一个订单发送到同一个队列中,再使用同步发送,只有同个订单的创建消息发送成功,再发送支付消息。这样,我们保证了发送有序。
RocketMQ的topic内的队列机制,可以保证存储满足FIFO(First Input First Output 简单说就是指先进先出),剩下的只需要消费者顺序消费即可。
RocketMQ仅保证顺序发送,顺序消费由消费者业务保证!!!
这里很好理解,一个订单你发送的时候放到一个队列里面去,你同一个的订单号Hash一下是不是还是一样的结果,那肯定是一个消费者消费,那顺序是不是就保证了?

8.重平衡(差不多) MQ重平衡

生产者broker重平衡,消费者重平衡
Rebalance 限制
由于⼀个队列最多分配给⼀个消费者,因此当某个消费者组下的消费者实例数量大于队列的数量时,多余的消费者实例将分配不到任何队列。

危害
Rebalance的在提升消费能力的同时,也带来一些问题:

消费暂停:在只有一个Consumer时,其负责消费所有队列;在新增了一个Consumer后会触发Rebalance的发生。此时原Consumer就需要暂停部分队列的消费,等到这些队列分配给新的Consumer后,这些暂停消费的队列才能继续被消费。

消费重复:Consumer 在消费新分配给自己的队列时,必须接着之前Consumer 提交的消费进度的offset继续消费。然而默认情况下,offset是异步提交的,这个异步性导致提交到Broker的offset与Consumer实际消费的消息并不一致。这个不一致的差值就是可能会重复消费的消息。

同步提交:consumer提交了其消费完毕的一批消息的offset给broker后,需要等待broker的成功 ACK。当收到ACK后,consumer才会继续获取并消费下一批消息。在等待ACK期间,consumer 是阻塞的。

异步提交:consumer提交了其消费完毕的一批消息的offset给broker后,不需要等待broker的成 功ACK。consumer可以直接获取并消费下一批消息。
对于一次性读取消息的数量,需要根据具体业务场景选择一个相对均衡的是很有必要的。因为 数量过大,系统性能提升了,但产生重复消费的消息数量可能会增加;数量过小,系统性能会 下降,但被重复消费的消息数量可能会减少。
消费突刺:由于Rebalance可能导致重复消费,如果需要重复消费的消息过多,或者因为Rebalance暂停时间过长从而导致积压了部分消息。那么有可能会导致在Rebalance结束之后瞬间需要消费很多消息。

Kafka重平衡

条件
检测broker中主副本区的个数,当新broker宕机恢复后没有主副本区,导致压力过大,重平衡。10%不合理。设置更大。搭配分区策略。和再平衡策略一样,

Round Robin(针对所有topic排序(性能低,但是不容易倾斜)),Range(针对一个分区(性能高,但是容易倾斜前几个))和Sticky(性能中等),默认使用的是Range为性能

9.消息过滤不同 Mq:

1.bysql方法传参

2.tag匹配
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(“CID_EXAMPLE”);
consumer.subscribe(“TOPIC”, “TAGA || TAGB || TAGC”);

3.拦截器

Kafka:

只能拦截器里边配

10.重试机制不同(kafka慢) Kafka:

无限重试,int最大值

Mq:

生产端,
消息去重
同步默认去重试两次,异步只重试一次。也可设置重试次数为0,保证效率

消费端
重试十六次
1,5,10,。。。2小时最后
一般设置成这样的代码这里的代码意思很明显: 主动抛出一个异常,然后如果超过3次,
不行放在死信队列去人工修改,这种有bug。其他无bug

11.刷盘不同(RocketMq慢)

Kafka没有同步刷盘
MQ有同步:默认异步

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/874603.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号