熟练掌握RabbitMQ和Kafka的使用及相关应用场景。异步通知与解耦,流量削峰,配合本地消息表实现事务的最终一致性并解决消息可靠、顺序消费和错误重试等问题

发布于:2025-07-04 ⋅ 阅读:(23) ⋅ 点赞:(0)

RabbitMQ
在这里插入图片描述
stock.#.nyse ,#匹配多个字符,*匹配一个字符。
Confirm Callback 到达exchange的回调。
Return Callback 到达queue失败的回调。
Kafka
Kafka生产端
在这里插入图片描述
分区器:
1.直接指定partition 指定0,1。
2.设置hashkey,计算key的hash值进行取模分区。
3.不设置分区键,采用粘性发送,即往某个分区发送至batchSize16K大小后切换分区。

RecordAccumulator(阿q米leite)生产内存池
DQuene每个partition对应一个。
batch.size,默认16k。配合linger.ms 10ms ,就是16k一批次发送,最多延迟10ms。
配合linger.ms默认0ms,不进行延迟,即来一条发一条。
sender 线程默认往每个broker发送5条缓存消息,即没有接受到broker的应答,也能发5条。
broker 采用0 1 -1 的应答策略,
默认-1 等待所有的主从节点全部落盘,才去应答。
0 不需要任何落盘应答,直接确认。
1 主节点落盘就直接确认应答。
若应答失败,则会无限重试。

副本分区策略。
创建一个T topic 三分区。
三节点 A B C
0 0’ 0’
1’ 1 1’
2’ 2’ 2
0为主分区lead 0’为副本

消费端
在这里插入图片描述
enable.auto.commit 默认true ,设置为false ,开启手动ack模式。
fetch.min.bytes 默认1B 设置为 128KB
fetch.max.wait.ms 默认500ms
Max.poll.records 最大拉取批次条数,默认500条,设置为1000条。

每个消费者都会和coordinator保持心跳(默认3s),一旦超时
(session.timeout.ms=45s),该消费者会被移除,并触发再平衡;
或者消费者处理消息的时间过长(max.poll.interval.ms 5分钟),也
会触发再平衡

默认采用Range消费者分区策略
10 P 3 C
先平均分配,多的给第一个
123 10 456 789

earliest与latest的区别
earliest:
新消费者会读取分区中从起始位置到当前最开始偏倚位置的所有消息。
latest:
新消费者会读取分区中从起始位置到当前所有消费者最后位置。

消息幂等
1.首先是生产端发生至kafka broker
PID 每次重启kafka则更换,Partition分区号,SeqNumber 区内顺序号。
<PID, Partition, SeqNumber>
幂等性只能保证的是在单分区单会话内不重复
enable.idempotence 默认为 true
kafka Brocker不接受已经接受的顺序号
2.kafka Brocker发送至 消费者端
kafka在同一消费者组,只会把同一分区的消息发送至一个消费者实例,但是由于消费者组一个实例宕机,触发再平衡机制,可能会重新发送消息至消费者端,故消费者端也需要根据主键幂等判断。
消息顺序
只能保证单分区顺序性。
broker接受到乱序的消息之后,会等待顺序的消息,并且进行重新排序。比如Brocker 接受到1 2 4,会等到接受到3之后排好序后落盘。
max.in.flight.requests.per.connection 需要设置小于等于5 默认配置就是5
enable.idempotence 默认为 true
文件存储机制
在这里插入图片描述
每个Segment 1 G 大小,每4KB存储一条索引,指定offset查询时,先查找索引的两端范围,再去查询log文件位置。
默认7天过期、以每个Segment 最大的消息时间判断是否过期,5分钟检查一次。
改为30天,30分钟检查一次,甚至对于重要消息,可以设置永不过期,在根据消费到的offset,进行手动消费。

Kafka为什么快
1.
零拷贝
减少了两次内核态和用户态的文件传输。
在这里插入图片描述
2.顺序磁盘写,减少磁头寻址时间。
3.采用LZ4,Gzip等压缩算法,减少包大小。
4.分区并行。

本地消息表
msgid(全消息唯一id)
topic(stock.relase)
status(状态 1.未消费2.已消费3.异常重试4.错误5.已存在)
erromsg错误消息内容
e_count(异常重试次数)
e_threshold(错误消息阈值)
group_flag(是否是顺序消息)
groupid(顺序消息组号)
grouporder(顺序消息组内顺序号)
发送时间
消费时间
无论如何都进行,确认的ack,不然像kafka这种,uack跳过某一条消息,之后有确认了后续的消息,offset直接就移动到了ack的位置,相当于错误的那条消息丢了,很严重的。
接受消息时都去判断,msgid是否存在,若存在,则不消费逻辑,直接已存在。若不存在,正常消费,处理完成之后标记为已消费。
若出现了异常(db超市,远程调用异常等),标记为异常重试。
后台定时任务,每隔5分钟,走索引扫描异常重试的消息,二次发送至mq。
当异常重试次数达到设定的错误阈值2次时,直接标记改消息错误,记录异常。(此时大概率是代码逻辑的健壮性不够导致的,比如非法的参数长度,sql进不去,或者是数组越界,或者入参没校验空值,出了空指针)重试再多次都不行。有个错误消息的前端页面,可以直接观测到。
顺序消息,通过是否是顺序消息、消息组号和组内顺序号去确认,当前的消息是否应该被消费,若是第二条,则查询库中第一条的消费状态,若不存在或者异常为消费,则直接入库,等待第一条消息消费完,查询后一条的是否存在进行消费。
当然,本地消费表只针对业务型mq。像rocketmq或者kafka有自己的策略。而且数据的并发肯定更不上mq的上限。


网站公告

今日签到

点亮在社区的每一天
去签到