【原创】基于 Keepalived 做主备的 MySQL 在切换时遇到的问题

原创
2014/04/18 14:54
阅读数 6.5K

问题描述
MySQL 基于 keepalived 实现主备切换,业务 A 和业务 B (其实 A 和 B 上跑的业务是相同的 )同时使用 MySQL 做数据库查询。通过重启 keepalived 服务来测试 MySQL 主备切换后,能够为业务提供正常的服务。

问题现象
测试人员发现 MySQL 主从切换之后,与业务 A 相关的 TCP 连接信息已经变更为新 TCP 连接,而与业务 B 相关的 TCP 连接信息仍旧未变化。

具体环境如下
业务A:172.16.177.158
业务B:172.16.177.159

VIP:172.16.177.147
MySQL master:172.16.177.148
MySQL slave:172.16.177.149




在业务正常运行状态下,业务A 通过 VIP 与 MySQL master(148)建立 6 条 TCP 连接(业务开发人员告知的),分别对应端口
43666、 43668、 43669、 43670、 43673、 43674。

当通过重启 148 机器上的 keepalived 服务来完成 VIP 切换,从而达成 MySQL 主备切换时,可以看到如下抓包信息:

如下为 158 上的 TCP 链接信息。




可以看到,上面出现了 10 个 RST ……,呃,先不管为什么多出来 4 个吧。

下面看一下 148 (原 MySQL master)上来自 158 的连接信息。



      从上面两个截图中,只能看到有两条 TCP 链路上出现了新的请求,并且因为重启了 keepalived 的原因,出现了 TCP 的重发。这两条 TCP 链路对应的端口分别为: 43673、43669。
这里重发请求的端口与 158 上的抓包中显示的一致。

再看一下 149 (原 MySQL slave)上来自 158 的连接信息。




可以看到这里也出现了 10 条 TCP 链路被 RST 。与上面的 10 条 TCP 链接是对应的。

综上,整个过程可以描述为:
  • 最开始 158 与 148 建立了6条 OCS 业务的 TCP 连接;
  • 在重启 keepalived 的时候,恰好使用端口 43673 和 43669 的 TCP 连接正在信令交互,而此时正处于 VIP 147 从 148 向 149 漂移的过程之中,此时这两条 TCP 链路上的请求会因为得不到任何回应而触发重传;
  • 当 VIP 成功绑定到 149 上后,上述两条 TCP 链路上的重传请求会被 RST,而当其他 TCP 链路上有新的请求时,才会被 RST。被 RST 后,OSC 会重新建立 TCP 连接。
下面单独看下每条 TCP 链路的状况:

端口 43673 的 TCP 链路。

端口为 43669 的 TCP 链路。

端口为 43666 的 TCP 链路。

端口为 43674 的 TCP 链路。

端口为 43670 的 TCP 链路。

端口为 43668 的 TCP 链路。

端口为 43671 的 TCP 链路。

端口为 43665 的 TCP 链路。

端口为 43672 的 TCP 链路。

端口为 43667 的 TCP 链路。



上述现象在对于 159 上的业务来说也是这样,不再重复说明。

总结:
      上述问题的出现值得思考的地方有,通过重启 keepalived 来促使 MySQL 主备切换这种方式对于实际应用场景是否有意义?!如果实际情况中真的出现类似于 keepalived 重启导致的 MySQL 主从切换,那么由此导致的主从不一致将如何解决 ?!业务程序通过某种保活机制触发对当前 TCP 链路是否处于“半打开”状态的检测时间间隔多少比较合适?MySQL 上的 wait_timeout 设置多少比较合适!?
      真正让人感到不安的是,仅通过重启 keepalived 来进行主备切换,无论是 MySQL 侧还是业务侧,居然都不会收到 TCP 的 FIN 或 RST ,而只会在业务层面有“动作”时才能发现 TCP 链路的问题,这种现象对类似 MySQL 这种服务来说必然会造成一些问题。











展开阅读全文
打赏
6
122 收藏
分享
加载中
摩云飞博主

引用来自“xiaorui521”的评论

我有个疑问,这样的架构,不适合自动切换吧? A主,B从 10个app往A读写,这时候A挂了,Keepalived的vip偏移到B上面,那么我程序可以往B写入。 那这时候,怎么再创建B主,A从的关系? 需要暂停业务,然后记录pos file值,然后再跑到从手动change to master ?
哦,我之前少说了一个东东,其实这里使用的MySQL主从结构,实际上配置的是互为主从,即一个MySQL实例既作为主,又作为从。
2015/12/17 16:00
回复
举报
我有个疑问,这样的架构,不适合自动切换吧? A主,B从 10个app往A读写,这时候A挂了,Keepalived的vip偏移到B上面,那么我程序可以往B写入。 那这时候,怎么再创建B主,A从的关系? 需要暂停业务,然后记录pos file值,然后再跑到从手动change to master ?
2015/12/16 11:44
回复
举报
明天仔细瞅瞅
2014/05/13 20:07
回复
举报
摩云飞博主

引用来自“kongfei”的评论

问下楼主,keepalive是哪个版本?
用的是 keepalived-1.2.7 ,兄台有何高见
2014/04/22 18:38
回复
举报

引用来自“摩云飞”的评论

引用来自“kinglynn”的评论

楼主你的网段是/24么,可能是mac地址缓存上了么keepalived在切换脚本中检查同步延迟呗,跟上再切。不是还有半同步么

兄台认为这个问题和MAC地址缓存有关系?请明示~~ 另外,上面的实验中,是通过 service keepalived restart 来重启的,所以“在keepalived切换脚本中检查同步延迟“应该无法实施了吧; 再者,即使在 keepalived 脚本中实现了检查同步延迟的功能,当作为主的机器挂掉了,仍然是要做切换动作的吧……”跟上再切“的情况,当切换到从后,作为 slave 的机器作为只读提供服务,然后等主启动后才能”跟上“。而实际应用中,其实我们使用的是互为主从的方式,所以似乎没办法避免上面的问题。

在二层网络上通讯记得是到mac地址的 并不经过路由,我并不太清楚你说的重发的情况,检查延迟的目的是最大程度上保证数据的一致性,在半同步的情况下主库只是保证事务日志传送到同步库,并不保证同步库也事务完成吧。
2014/04/21 11:03
回复
举报
摩云飞博主

引用来自“kinglynn”的评论

楼主你的网段是/24么,可能是mac地址缓存上了么keepalived在切换脚本中检查同步延迟呗,跟上再切。不是还有半同步么

兄台认为这个问题和MAC地址缓存有关系?请明示~~ 另外,上面的实验中,是通过 service keepalived restart 来重启的,所以“在keepalived切换脚本中检查同步延迟“应该无法实施了吧; 再者,即使在 keepalived 脚本中实现了检查同步延迟的功能,当作为主的机器挂掉了,仍然是要做切换动作的吧……”跟上再切“的情况,当切换到从后,作为 slave 的机器作为只读提供服务,然后等主启动后才能”跟上“。而实际应用中,其实我们使用的是互为主从的方式,所以似乎没办法避免上面的问题。

2014/04/21 09:30
回复
举报
摩云飞博主

引用来自“宝仔love”的评论

引用来自“摩云飞”的评论

引用来自“宝仔love”的评论

你可以配合MHA来使用keepalive

我觉得只要用了 keepalived 就 一定会遇到类似的问题吧

MHA有binlog补偿的 数据保持一致的

没用过 MHA~~

2014/04/21 09:19
回复
举报
问下楼主,keepalive是哪个版本?
2014/04/21 09:05
回复
举报
楼主你的网段是/24么,可能是mac地址缓存上了么keepalived在切换脚本中检查同步延迟呗,跟上再切。不是还有半同步么
2014/04/20 22:03
回复
举报

引用来自“摩云飞”的评论

引用来自“宝仔love”的评论

你可以配合MHA来使用keepalive

我觉得只要用了 keepalived 就 一定会遇到类似的问题吧

MHA有binlog补偿的 数据保持一致的
2014/04/20 14:56
回复
举报
更多评论
打赏
16 评论
122 收藏
6
分享
返回顶部
顶部