消息存储
分布式队列因为高可靠性 所以要进行持久化的存贮
存贮介质
mysql 在达到千万级别 IO进入瓶颈 文件系统直接 效率较高
消息的存储和发送
存储 使用了顺序写 发送利用了零拷贝技术 MappedByteBuffer
三个文件夹
cmmitLog 存贮消息元数据
ConsumerQueue 消息的逻辑队列 存贮的是消息的物理的地址 每个Topic下的每个MessageQueue 都有一个ConsumerQueue文件
在consumerQueue 下的每个Topic下 有几个队列就有几个文件 会加载到内存来读取
index 提供了通过时间范围 和 key来查询消息
刷盘机制
同步刷盘 写到文件里 再去响应成功 异步刷盘 写入内存 响应成功
高可用机制
消息消费高可用
消息发送高可用
在Consumer的配置文件中 不需要配置是从master或者slave消费 首先回去从master去读 如果繁忙 就去slave
切换时自动的
消息主从复制
同步复制 master到slave 复制成功 再去响应
异步复制 到master就响应
从节点 直接slave 主节点 上面两个选项
推荐 异步刷盘 保证吞吐量 同步复制 保证不丢失
负载均衡
轮训的当时去发送 生产者的负载均衡
集群模式 启动多个消费者
AllocateMessageQueueAverageByCircle 环状轮询
消息重试
顺序重试
对于顺序消息 当消费者 消费消息失败后 消息队列会不断进行消息重试 后面的消费无法进行 会造成消息阻塞
无序重试
无序消息 当消费者消费失败 可以通过设置返回状态来达到消息重试的效果 无序消息只对集群消费有效 广播的话 只能消费一次
不重试的写法
死信队列
消息幂等
消费者接受到消息 同一条消息消费多少次 得到的结果相同
三种产生重复消息
- 发送时消息重复 MQ回复时网络问题或者客户端宕机导致 消息重复发送
- 消费者消费完毕消息 没有给MQ做响应 MQ回再次投递重复消息
- 负载均衡模式下 :消费者策略是负载均衡(不同的消费者去消费不同的消息,当Broker重启或者消费者重启,会出发Relance,此时消费者会出现消费相同的消息
解决方案
- 由于MQ不保证MessageID的唯一性 所以不可以使用这个
- 最好使用业务ID,将消费的消息存起来,然后去查询,如果消费过,丢弃即可