RocketMQ是如何判断flushOK,及4.2版本所出现的疑问

RocketMQ

版本:rocketmq-4.2.0

bug所表现形式:在同步刷盘时,生产消息,返回SendResult的SendStatus为FLUSH_DISK_TIMEOUT,而且是在发送消息总量大概mapedFileSizeCommitLog(默认配置1G)的时候出现,每次达到mapedFileSizeCommitLog大小左右的时候都会出现FLUSH_DISK_TIMEOUT。而其余时间并没有出现状态,总是如此这显然是有问题的。

rocketmq刷盘逻辑:引用:https://blog.csdn.net/prestigeding/article/details/79188383

RocketMQ是如何判断flushOK?

刷盘:CommitLog.this.mappedFileQueue.flush(0)

原理:根据刷盘起始点【CommitLog.this.mappedFileQueue.getFlushedWhere()】和下次刷盘点【req.getNextOffset()】的比较来判断是否成功刷入磁盘。由于可能刷盘需要刷两个MappedFile,故循环次数为2。

代码:

private void doCommit() {

            synchronized (this.requestsRead) {

                if (!this.requestsRead.isEmpty()) {

                    for (GroupCommitRequest req : this.requestsRead) {

                        // There may be a message in the next file, so a maximum of

                        // two times the flush

                        boolean flushOK = false;

                        for (int i = 0; i < 2 && !flushOK; i++) {

                            flushOK = CommitLog.this.mappedFileQueue.getFlushedWhere() >= req.getNextOffset();

                            if (!flushOK) {

                                CommitLog.this.mappedFileQueue.flush(0);

                            }

                        }

                        req.wakeupCustomer(flushOK);

                    }

                    long storeTimestamp = CommitLog.this.mappedFileQueue.getStoreTimestamp();

                    if (storeTimestamp > 0) {

                        CommitLog.this.defaultMessageStore.getStoreCheckpoint().setPhysicMsgTimestamp(storeTimestamp);

                    }

                    this.requestsRead.clear();

                } else {

                    // Because of individual messages is set to not sync flush, it

                    // will come to this process

                    CommitLog.this.mappedFileQueue.flush(0);

                }

            }

        }

 

先讲正常流程:进入for循环,第一次:由于刷盘起始点【CommitLog.this.mappedFileQueue.getFlushedWhere()】小于下次刷盘点【req.getNextOffset()】,故flushOK为false,执行刷盘操作。第二次:由于刷盘成功,刷盘起始点【CommitLog.this.mappedFileQueue.getFlushedWhere()】等于下次刷盘点【req.getNextOffset()】,flushOK为true。结束循环。

bug出现了:若有两个MappedFile来存储,第一次flushOK为false,刷盘之后刷盘起始点【CommitLog.this.mappedFileQueue.getFlushedWhere()】还是小于下次刷盘点【req.getNextOffset()】,故开始第二次刷盘。而第二次刷盘成功,而这时循环却结束了。可flushOK还是为false。

修改代码:在for循环外再加flushOK的判断。

 

 

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值