如何解决MQTT消息不丢失
为什么消息会丢失?
整个消息从生产到消费,哪些地方可能导致丢消息?
生产阶段:消息在Producer中被创建,网络传输到Broker。
存储阶段:消息在Broker存储,若是集群,消息会被复制到其他副本上。
消费阶段:Consumer从Broker拉取消息,网络传输到Consumer上。
总结下来有以下可靠性问题:
- 网络传输时的可靠性问题
- 存储时的可靠性问题
在主流的消息队列产品中都提供了非常完成的消息可靠性保证机制,确保消息的可靠传递,不丢失消息。
你怎么知道消息丢没丢?
首当其冲的问题其实不是如何保证消息传递的可靠性,而是应该考虑如何知道消息是否丢失。
答案是有序性。
原理很简单:
- 在Producer端,每个发送的消息添加一个连续递增的序号。
- 在Consumer端,若检测到消息序号不连续了,则丢消息了,还可以确定丢的是那一条数据。
分布式提升了消息丢失检查方法的复杂度
在Kafka和RocketMQ中,为了提升并发程度,降低了有序性。从Topic级有序降到了分区级有序。
因此由原来的每个Topic检测消息序号的连续性,降为每个分区单独检测消息序号的连续性。
因此我们要注意:
在Producer端
- 我们要指定发送消息的分区
- 若有多个Producer实例,每个Producer分别生成各自的消息序号,且附加上Producer标识。
在Consumer端
- 按照Producer分表来检测序号的连续性。
- Consumer实例数最好和分区数一致,一一对应可以方便Consumer检测序号的连续性。
怎么确保消息不丢失?
请求确认机制(ACK)解决网络传输时的可靠性问题
请求确认机制原理
- Producer告诉Broker我消息发给你了,你收到了告诉我一声。
- Broker收到消息之后给Producer发送,我收到了。
生产阶段和消费阶段发送ACK的时机不同
生产阶段:
- 若存储阶段为单机,则Broker将消息写入硬盘之后,再返回ACK。
- 若存储阶段为集群,则将消息发送到Broker两个以上节点,再返回ACK。 消费阶段:
Consumer消费掉消息之后,再返回ACK。
总结
链接:https://juejin.cn/post/7001365874024136712