一、背景

master broker.log中出现如下日志:

2019-12-03 17:42:06 INFO BrokerControllerScheduledThread1 - Slave fall behind master: -6868909625984868736 bytes

slave同步master的数据落后的是负数,难以理解!

二、分析

1 上面的日志对应DefaultMessageStore如下代码:

public long slaveFallBehindMuch() {return this.commitLog.getMaxOffset() - this.haService.getPush2SlaveMaxOffset().get();
}

其中this.commitLog.getMaxOffset()这个是master的commit log的最大offset,这个不太可能出错,如果出错,那消息存储麻烦就大了,commit log设计可以参考。

那么就是this.haService.getPush2SlaveMaxOffset().get()这个有问题了。

2 push2SlaveMaxOffset来自于HAService中的属性,顾名思义:推送给slave的最大偏移量,初始值为0。

那么它是什么时候更新的,参考如下代码:

public void notifyTransferSome(final long offset) {for (long value = this.push2SlaveMaxOffset.get(); offset > value; ) {boolean ok = this.push2SlaveMaxOffset.compareAndSet(value, offset);if (ok) {this.groupTransferService.notifyTransferSome();break;} else {value = this.push2SlaveMaxOffset.get();}}
}

push2SlaveMaxOffset来自于offset的值,offset是什么?

  1. 如果slave未同步过master的数据,offset将使用master的commit文件组中最新的一个文件的最小offset,即:同步最新的一个commit文件给slave。
  2. 如果slave已经同步过master数据,那么offset将使用slave commit文件组的最大的offset,其通过心跳包的方式上报给master。

很明显,对于第一种情况(slave未同步过master的数据),offset值不可能大于master的最大offset。

对于第二种情况,是有可能的。

3 实验

模拟slave上报给master的offset过大,很容易联想到如下步骤:

  1. 启动一个新的master。
  2. 增加一个新的slave。
  3. 发送一些消息。
  4. 关闭master,并重新部署一个新的同样brokerName的master。

此时,slave自动变成新master的slave了,但是其commit log的offset是之前master的,肯定大于新master的。

结论:如果重部master,一定要部署新的slave,老的slave重启没用。

另外,如果已经发生这样的情况,移除旧的slave,再部署新的slave并不起作用,因为master已经持有旧的slave上报上来的offset,notifyTransferSome(final long offset)中的for (… offset > value; )会阻止push2SlaveMaxOffset更新。

4 影响

  1. 上面的情况影响的是同步双写模式的master,因为此模式的master会通过push2SlaveMaxOffset检测是否写入到slave了。
  2. 其次,发送错误偏移量的slave将无法正确同步数据。
  3. storeerror.log出现大量错误日志,broker.log和store.log出现诡异的日志,影响主从数据同步情况的判断。

三、解决方案

  1. broker迁移
    由于存储文件巨大,一般broker迁移时,采取的方案是下掉旧的broker,部署新的broker的方案。那么slave一定也要部署新的,即使slave的机器不用迁移,也不能用旧的slave。
  2. 已经存在的broker
    1. 执行停写。
    2. 下掉slave。
    3. 停止master。
    4. 启动master。
    5. 部署新的slave。
      注意以上顺序,master必须重启,否则此问题依然存在。

四、其余情况

导致这样的情况的还有一种可能,就是非rocketmq slave程序和master的slave端口进行了通信,进行如下测试(假设master在127.0.0.1的10916监听slave请求,在127.0.0.2进行测试):

  1. telnet 127.0.0.1 10916
  2. 发送999999999
  3. 观察master日志:
       2019-12-04 11:35:12 INFO AcceptSocketService - HAService receive new connection, /127.0.0.2:388242019-12-04 11:35:12 INFO ReadSocketService - ReadSocketService service started2019-12-04 11:35:12 INFO WriteSocketService - WriteSocketService service started2019-12-04 11:35:16 INFO ReadSocketService - slave[/127.0.0.2:38824] request offset 41233898517703703612019-12-04 11:35:16 INFO WriteSocketService - master transfer data from 4123389851770370361 to slave[/127.0.0.2:38824], and slave request 41233898517703703612019-12-04 11:35:36 WARN ReadSocketService - ha housekeeping, found this connection[/127.0.0.2:38824] expired, 200202019-12-04 11:35:36 INFO ReadSocketService - makestop thread ReadSocketService2019-12-04 11:35:36 INFO ReadSocketService - makestop thread WriteSocketService2019-12-04 11:35:36 INFO ReadSocketService - ReadSocketService service end2019-12-04 11:35:36 INFO WriteSocketService - makestop thread WriteSocketService2019-12-04 11:35:36 INFO WriteSocketService - makestop thread ReadSocketService2019-12-04 11:35:36 INFO WriteSocketService - WriteSocketService service end2019-12-04 11:35:53 INFO BrokerControllerScheduledThread1 - slave fall behind master: 27539373 - 4123389851770370361 = -4123389851742830988 bytes

由于rocketmq的同步机制并未进行安全校验,所以任何程序都有可能链接此端口进行通信,导致问题发生。

另附rocketmq解析通信数据的代码:

if ((this.byteBufferRead.position() - this.processPostion) >= 8) {int pos = this.byteBufferRead.position() - (this.byteBufferRead.position() % 8);long readOffset = this.byteBufferRead.getLong(pos - 8);this.processPostion = pos;HAConnection.this.slaveAckOffset = readOffset;if (HAConnection.this.slaveRequestOffset < 0) {HAConnection.this.slaveRequestOffset = readOffset;log.info("slave[" + HAConnection.this.clientAddr + "] request offset " + readOffset);}HAConnection.this.haService.notifyTransferSome(HAConnection.this.slaveAckOffset);
}

即,只要连接master监听的slave通信端口,发送数据大于8个字节,就可能导致该问题的产生。

slave同步master数据偏移量错误相关推荐

  1. mysql主辅同步报错_mysql数据库主辅同步Slave_IO_Running,Slave_SQL_Running错误

    Slave_IO_Running:连接到主库,并读取主库的日志到本地,生成本地日志文件 Slave_SQL_Running:读取本地日志文件,并执行日志里的SQL命令. 这个错误是出现在我重启电脑之后 ...

  2. mysql的master slave_Mysql 数据库的同步(master slave) 详解

    ####原理######## mysql 的数据同步,在 mysql 官方网站文档上,叫 replication 字面是重作的意思,意译就是同步了. mysql 为了实现 replication 必须 ...

  3. TiDB 作为 MySQL Slave 实现实时数据同步

    由于 TiDB 本身兼容绝大多数的 MySQL 语法,所以对于绝大多数业务来说,最安全的切换数据库方式就是将 TiDB 作为现有数据库的从库接在主 MySQL 库的后方,这样对业务方实现完全没有侵入性 ...

  4. mysql slave同步_Slave_SQL_Running: No mysql同步故障解决方法

    Slave_SQL_Running: No mysql同步故障解决 今天检查数据库发现一台MySQL Slave未和主机同步,查看Slave状态: mysql> show slave statu ...

  5. Elasticsearch7.9集群部署,head插件,canal同步mysql数据到es,亲自测试,无坑

    Elasticsearch集群部署 1.服务器规划 10.4.7.11 node1 10.4.7.12 node2 10.4.7.13 node3 1. 集群相关    一个运行中的 Elastics ...

  6. mysql 同步失败_mysql 同步失败解决方法 (错误:1236)

    在重启了外国B的服务器后,发现国内A数据库同步突然停止了,导致国内A服务器复制失败,如下: 国内A就报下面的错误: 090910 22:47:18 [ERROR] Error reading pack ...

  7. 【Redis】Redis主从同步中数据同步原理

    [Redis]Redis主从同步中数据同步原理 文章目录 [Redis]Redis主从同步中数据同步原理 1. 全量同步 1.1 判断是否第一次数据同步 2. 增量同步 3. 优化Redis主从集群 ...

  8. 使用canal实时同步MySQL数据到Elasticsearch

    使用canal实时同步MySQL数据到Elasticsearch 搭建环境 安装 elasticsearch 安装 kibana 下载和安装canal 1.下载canal 2.配置MySQL 3.配置 ...

  9. 备份恢复与同步(数据搬运专家)

    NewLife.XCode是一个有20年历史的开源数据中间件,支持net6/net5/net45/net40,由新生命团队(2002~2020)开发完成并维护至今,以下简称XCode. 整个系列教程会 ...

最新文章

  1. float最大值_float.h库
  2. 据说程序员等电梯的时候都想过调度算法
  3. 进程间通信各方法优劣
  4. 利用mybatis-generator自动生成代码
  5. PWA(Progressive Web App)入门系列:Push
  6. 服务器系统server 2008,windows server 2008 R2 操作系统
  7. compact php,php内置函数使用 compact()
  8. MongoDB 教程八(结语): 一网打尽当下NoSQL类型、适用场景及使用公司
  9. Vue首屏性能优化组件
  10. CollectionBase的使用
  11. mysql5.1查询分析语句_MySQL 查询数据_mysql 查询语句_SELECT语句
  12. GAN变种介绍 - DCGAN、InfoGAN、CycleGAN、WGAN、Self-Attention GAN、BigGAN
  13. SpringBoot系列之集成EasyExcel导入合并行数据
  14. Nginx常用的模块
  15. Linux提高CPU使用率并设置固定占比
  16. 计算机二级Python错题
  17. (每日更新)《虚拟现实VR资讯》(Yanlz+Unity+SteamVR+云技术+5G+AI=VR云游戏=云渲染+人机交互+立钻哥哥+==)
  18. H5网页元素和全局属性
  19. CMWAP 和 CMNET 的主要区别与适用范围
  20. 使用new bing来阅读文献

热门文章

  1. 163邮箱手机版怎么登录?163vip邮箱可以微信收发邮件吗?
  2. 23种设计模式——结构型设计模式(7种)
  3. 清明短信延迟一个月,导致兄弟翻脸
  4. 水经微图下载与安装教程
  5. 元宇宙游戏开发公司 区块链传奇游戏开发
  6. Android 使用AudioRecord录制声音
  7. 《3+1团队》第三次作业:团队项目的原型设计
  8. 初五接财神,新的一年“不差钱”
  9. 准确率(precision)、召回率(recall)和F值
  10. php日历怎么存价格数据库,日历价格表?