RocketMQ 刷盘机制BUG踩坑——可能引起消息丢失

上文说到dledger模式有bug,于是还是踏实考察master-slave或HA的架构。最近看源码发现一个严重的bug,可能导致消息丢失。

具体分析过程有机会再详写,直接看MappedFile.java的flush方法代码

 public int flush(final int flushLeastPages) {
        if (this.isAbleToFlush(flushLeastPages)) {
            if (this.hold()) {
                int value = getReadPosition();

                try {
                    //We only append data to fileChannel or mappedByteBuffer, never both.
                    if (writeBuffer != null || this.fileChannel.position() != 0) {
                        this.fileChannel.force(false);
                    } else {
                        this.mappedByteBuffer.force();
                    }
                } catch (Throwable e) {
                    log.error("Error occurred when force data to disk.", e);
                }

                this.flushedPosition.set(value);
                this.release();
            } else {
                log.warn("in flush, hold failed, flush offset = " + this.flushedPosition.get());
                this.flushedPosition.set(getReadPosition());
            }
        }
        return this.getFlushedPosition();
    }

能看到try catch了错误之后,有log.error("Error occurred when force data to disk.", e);这行代码报错输出。

然后,就没有然后了。。。

反馈给上一级的还是正确,所以就算刷盘报了错,客户端最后依然收到的是SEND_OK。

然后问题来了,磁盘或存储故障(比如很常见的文件系统read only),然后客户端依然认为发送正常了。直到我们发现磁盘故障要重启机器,因为消息没写成功,然后消息就丢了。

修改起来也简单,加个返回码就行,已提交了PR。问题修改之前,HA架构也别想了。

另外大家源码分析的时候注意,网上说的实现刷盘的入口类是handleflushdisk,4.8.0实际应该是submitFlushRequest了。

还有就是RocketMQ的异常处理机制还有几个bug,后续有时间接着分析。

4.9.1 测试问题还是存在。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值