RocketMq-消息不丢失&幂等

by shihang.mai

1. 消息不丢失

首先需要知道

  1. producer发送msg给broker,broker返回ack给producer
  2. consumer向broker拉取消息,处理成功,返回ack给broker

1.1 从producer-broker分析

生产者只要接收到返回的确认响应,就代表消息在生产阶段未丢失。
利用同步发送、异步发送,等待ack状态,ack状态包括

  • SendStatus.SEND_OK
  • SendStatus.FLUSH_DISK_TIMEOUT
  • SendStatus.FLUSH_SLAVE_TIMEOUT
  • SendStatus.SLAVE_NOT_AVAILABLE

无论用哪种形式发送,设置重试一定次数

1.2 broker自身

1.2.1 设置同步刷盘

默认:消息只要到了 Broker 端,将会优先保存到内存中,然后立刻返回ack给producer。随后 Broker 定期批量的将一组消息从内存异步刷入磁盘。

若想保证 Broker 端不丢消息,保证消息的可靠性,我们需要将消息保存机制修改为同步刷盘方式,即消息存储磁盘成功,才会返回ack给producer

## 默认情况为ASYNC_FLUSH,异步刷盘 
flushDiskType = SYNC_FLUSH 

若 Broker 未在同步刷盘时间内(默认为 5s)完成刷盘,将会返回 SendStatus.FLUSH_DISK_TIMEOUT 状态给生产者。

1.2.2 设置salve同步复制

默认:消息写入 master 成功,就可以返回ack给producer,接着消息将会异步复制到 slave 节点

master 节点将会同步等待 slave 节点复制完成,才会返回ack给producer

## master节点配置
## 默认为 ASYNC_MASTER 
brokerRole=SYNC_MASTER

1.2.3 小结

严格保证息不丢失,可采取如下措施
master端

#设置同步刷盘才返回ack给producer
flushDiskType = SYNC_FLUSH
#设置同步消息给salve
brokerRole=SYNC_MASTER

salve端

#角色为salve
brokerRole=slave
#设置同步刷盘才返回ack给master
flushDiskType = SYNC_FLUSH

生产者判断ack返回状态是否是SendStatus.SEND_OK,如果是其他状态,重试发送

1.3 从broker-consumer分析

只有当业务逻辑真正执行成功,我们才返回 ConsumeConcurrentlyStatus.CONSUME_SUCCESS。否则我们需要返回 ConsumeConcurrentlyStatus.RECONSUME_LATER,稍后再重试即可

2. 幂等

利用幂等令牌.幂等令牌时指生产者和消费者两者中的既定协议.在业务中通常是具备唯一业务标识的字符串,如:订单号、流水号等。且一般由生产者端生成并传递给消费者端

  • 在消费端操作业务之前,先判断缓存中是否有幂等令牌,如果有直接返回消费成功,否则进行业务操作

  • 在插入库的时候,通过唯一键做最后一道幂等防线

参考博客:

https://www.cnblogs.com/goodAndyxublog/p/12563813.html

你可能感兴趣的:(RocketMq-消息不丢失&幂等)