一.消息的发送流程,包括上图三个阶段,分别为生产阶段,存储阶段,消费阶段。
(1).生产阶段:rocketMq 客户端生产者承担该任务。
(2).存储阶段:rocketMq 服务器本身承担该任务。
(3).消费阶段:rocketmq 客户端消费者承担该任务。
可知要想保证消息不丢失就要保证生产阶段,存储阶段,消费阶段 三个阶段消息不丢失。
二.消息不丢失解决方案
1.生产阶段怎么保存消费不丢失,即消息一定到达了rocketMq服务器并返回了成功信息。
生产阶段包含三种发送方式分别为:
(1) 同步发送
(2) 异步发送
(3) 单向发送
1)我们先聊一聊 同步发送怎么保证消息不丢失.
引用官方状态说明: 消息发送成功或者失败都要打印消息日志(log 或 数据库),务必要打印SendResult 和key 字段。sand消息方法只要不抛出异常,就代表发送成功。发送成功会有多个状态,在sendResult里定义。以下对每个状态进行说明
:
.SEND_OK
消息发送成功.要注意的是消息发送成功也不意味着它是可靠。要确保不虎丢失任何消息,还赢启动同步master服务器器和同步刷盘。
.FLUSH_DISK_TIMEOUT
消息发送成功但是服务器刷盘超时。此时消息已经进入服务器队列(内存),只有服务器宕机,消息才会丢失消息。消息存储配置参数中可以设置刷盘方式和同步刷盘时间长度,如果broker服务器设置刷盘方式为同步刷盘,即FlushDiskType = SYSNC_FLUSH(默认为异步刷盘方式),当Broker服务器未在同步刷盘时间内(默认为5s)完成刷盘,则将返回该状态—刷盘超时
.FlUSH_SLAVE_TIMEOUT
消息发送成功,但是服务器同步到Slave时超时。此时消息已经进入服务器队列,只有服务器宕机,消息才会丢失。如果Broker服务器的角色是同步Master,即SYSNC_MASTER(默认是异步Master即ASYNC_MASTER),并且从Broker服务器未在同步刷盘时间(默认为5秒)内完成与主服务器的同步,则将要返回该状态----数据同步到Slave服务器超时。
.SLAVE_NOT_AVAILABLE
消息发送成功,但是此时Slave不可用。如果Broker服务器的角色是同步Master,即SYSNC_MASTER(默认是异步master服务器即ASYNC_MASTER),但没有配置slave Broker服务器,则将返回该状态----无Slave服务器可用。
解读:
同步发送只要正确返回成功状态即以上四种状态,就代表该消息在生产阶段消息正确的投递到了RocketMq没有丢失。但是只是生产阶段消息没有丢失,并不代表存储阶段消息不丢失,只有生产阶段和存储阶段都满足不丢失,消息才是真正的不丢失。
疑问: 发送端接受到FLUSH_DISK_TIMEOUT 和 FlUSH_SLAVE_TIMEOUT 状态那么务消息丢失了呢 还是消息没有丢失呢。
答案: 上边已经阐述了只有生产阶段 1 和存储阶段 2 都满足不丢失,消息才是真正的不丢失,那么返回了FLUSH_DISK_TIMEOUT 和 FlUSH_SLAVE_TIMEOUT 就代表着存储阶段有可能会丢失该消息。
这里有2个选择:
. 若是业务要求消息一定不能丢失,那么出现FLUSH_DISK_TIMEOUT 和 FlUSH_SLAVE_TIMEOUT 状态就认为消息丢失,需要重新发送该消息(消费端要保存幂等性)。
. 消息无关紧要,要求并不那么的严格,可以任务该消息成功发送,不在重新发送。
这里的日志该怎么记录呢:
.业务要求不太严格
log.info(发送消息mq key 发送中........) //用数据库记录日志: 插入本地消息表:消息:key, 消息状态:发送中
try{
send(msg)
log.info(发送消息mq key 发送sucess........) //用数据库记录日志: 更新本地消息表:消息:key, 消息状态:发送成功
}catch(E e){
log.info(发送消息mq key 发送 fail..