文章目录
这是读advance-java的pdf所得到的,其中有些总结值得记录,并新增了某些说明。
消息队列丢失消息
RabbitMQ
MQ 丢失消息的补充说明
Rabbit MQ丢失消息的时候,可以开启
1、创建队列时创建持久化队列
2、发送消息发送持久化队列
这样producer的消息必须被MQ持久化后才能返回ACK,但是重试的机制需要程序员自己补充。
选取confirm模式实现以及异步confirm设计实现
这篇文章写的很好:
https://blog.csdn.net/weixin_44399827/article/details/126108161
KafkaMQ
消费端丢失
唯一可能导致消费者弄丢数据的情况,就是说,你消费到了这个消息,然后消费者那边自动提交了offset,让 Kafka 以为你已经消费好了这个消息,但其实你才刚准备处理这个消息,你还没处理,你自己就挂了,此时这条消息就丢咯。
解决方案:设置手动提交,消费完成后再提交offset。
Kafka本身丢失以及producer丢失
先说Kafka本身丢失,其实通过设置防止kafka本身丢失后Producer也不会再丢失了。
常见的一个场景:某个broker挂了,重新选举分区leader。此时某个follower还没有同步leader的数据,刚好这个follower被选举成为leader。未同步的消息就被丢失了。
解决方案:四个设置项,共同保证kafka本身不丢失消息。
因为也涉及到producer,所以producer也不会丢失消息。
- 给 topic 设置 replication.factor 参数:这个值必须大于 1,要求每个 partition 必须有 至少 2
个副本。 - 在 Kafka 服务端设置 min.insync.replicas:这个值必须大于 1,这个是要求一个 leader
至少感知到有至少一个 follower 还跟自己保持联系,没掉队,这样才能确保 leader挂了还有一个 follower 吧。 - producer 端设置 acks=all :这个是要求每条数据,必须是写入所有 replica 之后,才 能认为是写成功了。
- producer 端设置 retries=MAX(MAX代表很大很大的一个值,无限次重试的意思):这个是要求一旦写入失败,就无限重试,卡在这里了。
消息乱序
消息乱序,主要发生在消费端消费的时候,也即到消息队列时,消息是顺序的,因为生产者会为每个消息分配offset,只要offset有序,到达消息队列后就可以保证在消息队列是有序的。
解决方案一句话来讲,使用不同的队列来对应消费者,因为一个队列里的消息是有序的。
RabbitMQ
发生场景
三个消费者依次消费三条消息,但是消费者消费完成的时间是不一定的,可能先拿到消息的后消费完毕,也可能反过来。
解决方案
1、拆分多个 queue,每个 queue 一个 consumer,就是多一些 queue 而已,确实是麻烦点;
2、只有一个 queue,对应一个 consumer,然后这个 consumer 内部用内存队列做排队,然后分发
给底层不同的 worker 来处理。
补充说明
利用consumer 内部用内存队列做排队,然后分发给底层不同的 worker 来处理,其实和kafka的同一个key分配到同一个queue原理一致,只是在这里这一步变成了在消费者内存中路由不同消息到不同内存队列。这样数据库的同步消息顺序就会被分到同一个内存队列中,由线程池中的worker来消费,一个线程消费一个queue不会出现乱序。
Kafka
发生场景
Kafka概念中有partition分区的概念,在一个分区中消息是顺序的,但是可能出现一个消费者组并发处理消息的情况,一条消息会被一个消费者组的一个消费者消费。而一条消息被处理完成的时间是不一样的,因此可能出现乱序。
解决方案
1、一个 topic,一个 partition,一个 consumer,内部单线程消费,单线程吞吐量太低,一般不
会用这个。
2、写 N 个内存 queue,具有相同 key 的数据都到同一个内存 queue;然后对于 N 个线程,每
个线程分别消费一个内存 queue 即可,这样就能保证顺序性。
补充说明
解决方案2中的N个内存队列,是指的是消费端的内存队列,并不是消息队列的内存队列。他的意思是有多少个需要保证顺序的队列,就用多少的个内存队列。这些消息是不是属于一个业务的消息,需要用key保证,一组需要保存顺序的业务消息,需要分配一个key。
kafka一个demo实例
这个实例应该包括一个kafka中,多个topic、多个消费者组,测试在并发前提下,如何落实解决方案2,期望:同一个topic和同一个消费者组下顺序消费,并且关注重复消费和消息丢失问题。
链接:https://gitee.com/egoist_shy/kafka-demo
提高生产者的吞吐量
以下是提高生产者的吞吐量的建议。
- 修改batch.size的大小。batch.size默认大小为16k,提高批次大小可以一定程度提高吞吐量。这就好比用小卡车拉货物和用大卡车拉货物,小卡车单位时间内不能一次拉完货物,那么来回就需要消耗额外时间,而大卡车一次性把货物拉走,那么就节省了来回的时间。
- 修改linger.ms的时间,默认为0,即直接发送数据,一般设置为5-100ms,通过设置延迟时间一次性可以发送更多的数据。
- 修改compression.type的数据压缩类型,默认snappy。根据不同的业务场景选择不同的数据压缩方法,提高数据压缩率。kafka提供的压缩类型有:gzip,snappy,lz4,zstd。
- 修改RecordAccumulator缓冲区的大小。默认32m,增加缓冲区大小可以那么每个batch.size的值就更大,每次发送的数据更多。
消费者的建议
指定offset消费
当消费者第一次消费或者offset信息丢失,这是消费者该如何进行消费呢?Kafka提供了三种方式:earliest(默认值),latest和none
earliest:自动将offset设置为最开始的位置。
latest:自动将offset设置为最新的offset位置。
none:若没有找到之前的offset信息,则会抛出异常。
PS:注意多个消费者组可以同时订阅同一个topic,但是消息不会被同时发送给多个消费者组。!!!!楼主未确认!!!!!
关于自平衡
自平衡是指,消费者组出现gg的情况,分区分配的情况,将会在开启配置后自动重新分配。
如果想要扩容,由于分区限制,只能添加Kafka的实例节点,增加broke需要手动制作迁移计划,或者自动生成建议计划后修改,最后执行迁移脚本。
同理临时扩容后,kafka需要缩容,也和上面一样执行的本质都是分区重分配。
其他建议
参考 https://blog.csdn.net/ykko2009/article/details/123016482