Skip to content

Commit 29a711a

Browse files
docs: supplement RocketMQ's message consumption failure scenarios and common solutions (doocs#280)
1 parent 7a10570 commit 29a711a

File tree

1 file changed

+41
-0
lines changed

1 file changed

+41
-0
lines changed

docs/high-concurrency/how-to-ensure-the-reliable-transmission-of-messages.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,44 @@ RabbitMQ 如果丢失了数据,主要是因为你消费的时候,**刚消费
165165
#### 生产者会不会弄丢数据?
166166

167167
如果按照上述的思路设置了 `acks=all` ,一定不会丢,要求是,你的 leader 接收到消息,所有的 follower 都同步到了消息之后,才认为本次写成功了。如果没满足这个条件,生产者会自动不断的重试,重试无限次。
168+
169+
### RocketMQ
170+
171+
#### 消息丢失的场景
172+
173+
1. 生产者发送消息到 MQ 有可能丢失消息
174+
2. MQ 收到消息后写入硬盘可能丢失消息
175+
3. 消息写入硬盘后,硬盘坏了丢失消息
176+
4. 消费者消费 MQ 也可能丢失消息
177+
5. 整个 MQ 节点挂了丢失消息
178+
179+
#### 生产者发送消息时如何保证不丢失?
180+
181+
解决发送时消息丢失的问题可以采用 RocketMQ 自带的**事物消息**机制
182+
183+
事物消息原理:首先生产者会发送一个**half 消息**(对原始消息的封装),该消息对消费者不可见,MQ 通过 ACK 机制返回消息接受状态, 生产者执行本地事务并且返回给 MQ 一个状态(Commit、RollBack 等),如果是 Commit 的话 MQ 就会把消息给到下游, RollBack 的话就会丢弃该消息,状态如果为 UnKnow 的话会过一段时间回查本地事务状态,默认回查 15 次,一直是 UnKnow 状态的话就会丢弃此消息。
184+
185+
为什么先发一个 half 消息,作用就是先判断下 MQ 有没有问题,服务正不正常。
186+
187+
#### MQ 收到消息后写入硬盘如何保证不丢失?
188+
189+
数据存盘绕过缓存,改为同步刷盘,这一步需要修改 Broker 的配置文件,将 flushDiskType 改为 SYNC_FLUSH 同步刷盘策略,默认的是 ASYNC_FLUSH 异步刷盘,一旦同步刷盘返回成功,那么就一定保证消息已经持久化到磁盘中了。
190+
191+
#### 消息写入硬盘后,硬盘坏了如何保证不丢失?
192+
193+
为了保证磁盘损坏导致丢失数据,RocketMQ 采用主从机构,集群部署,Leader 中的数据在多个 Follower 中都存有备份,防止单点故障导致数据丢失。
194+
195+
Master 节点挂了怎么办?Master 节点挂了之后 DLedger 登场
196+
197+
- 接管 MQ 的 commitLog
198+
- 选举从节点
199+
- 文件复制 uncommited 状态 多半从节点收到之后改为 commited
200+
201+
#### 消费者消费 MQ 如何保证不丢失?
202+
203+
1. 如果是网络问题导致的消费失败可以进行重试机制,默认每条消息重试 16 次
204+
2. 多线程异步消费失败,MQ 认为已经消费成功但是实际上对于业务逻辑来说消息是没有落地的,解决方案就是按照 mq 官方推荐的先执行本地事务再返回成功状态。
205+
206+
#### 整个 MQ 节点挂了如何保证不丢失?
207+
208+
这种极端情况可以消息发送失败之后先存入本地,例如放到缓存中,另外启动一个线程扫描缓存的消息去重试发送。

0 commit comments

Comments
 (0)