MySQL集群迁移方案

背景

最近业务主库由于磁盘存储不够,需要对MySQL进行扩容;其实扩容的主要工作都在DBA侧,业务侧更多是配合DBA确定业务是否稳定,以及进行服务重启;

这篇笔记,一是学习MySQL的平滑迁移方案,二是,从MySQL的迁移中,学习的对业务开发中的一些小小建议

MySQL迁移中存在的问题

我们业务生产环境是通过域名方式连接MySQL集群,使用“一主三从”的集群架构,读写分离通过业务侧自己使用不同域名区分;整个集群迁移方案,分为以下几步:

  1. 新集群节点创建
  2. 新节点加入集群,作为slave,同步老集群master节点数据(此时新集群服务仍然没有流量)
  3. 切换读操作;将读域名解析到新集群只读节点
  4. 写域名解析切换;切换写操作,将写域名解析到新集群节点
    • 设置新老master节点主键自增长步长
    • 切换写操作到新集群节点
    • 恢复新集master节点主键自增长步长

其中,在第四步写切换时,操作比较复杂,涉及到几个冲突:

  1. 写节点切换期间,存在新老集群双写(老集群的老连接,新集群新连接),双向同步可能导致主键/唯一键冲突报错
  2. 步长生效期间,新连接和老连接感知到的自增长步长不一致,导致插入主键冲突报错
  3. 为了降低1、2的影响,需要主动kill数据库连接,导致业务层数据库连接博报错

以上,问题1其实是要解决的核心问题,因为如果双写阶段,应用层无异常,但MySQL自身数据同步冲突,会导致数据丢失,这是最严重的后果。问题2、3的出现,其实是为了解决问题1(解决的详情后面介绍),且问题2、3应用层可以感知到,在应用层通过重试即可解决。

MySQL从库(读节点)迁移原理

从库迁移只用修改域名(使用域名连接数据库)解析,修改完后会存在两种连接类型,一是旧连接,仍然读旧集群节点二是新连接,读新集群节点,此时可以选择多种处理方式:

  1. 保持不变。等待客户端主动断开旧连接,重新建立连接会读到新节点。这种方式需要一段时间,具体看客户端连接的配置;
  2. DBA强行kill旧节点连接。这种情况下,客户端会有数据库连接报错;需要业务层兼容
  3. 重启服务。通常服务端会使用滚动发布的方式,保证平滑重启,重启服务后,业务层新的连接池的连接都在新节点上;这种方式可以做到平滑迁移

MySQL主库(写节点)迁移原理

主库迁移涉及到写操作迁移,即将当前的主库(写节点)和新集群的从库(读节点)切换,切换过程会出现双写,即旧主库有数据新增,新主库也有数据新增,会导致新旧主节点在双向数据同步时,因主键/唯一键冲突而丢失数据。因此,迁移方案不仅仅是简单的切换域名解析,需要通过设置新旧节点主键的偏移和步长数据同步错误,具体步骤:

  1. 设置新旧主节点的自增参数

    • 新主:
      • set global auto_increment_offset=2 ;
      • set global auto_increment_increment=2;
    • 旧主:
      • set global auto_increment_offset=1 ;
      • set global auto_increment_increment=2;

    这一步是为了修改新旧节点主键的自增偏移量自增步长,其目的就是为了一个奇数增长,一个偶数增长,从而保证在双写时主键不冲突。这里自增偏移量是相对当前auto_increment而言的,如果此时auto_increment = 10,那旧主下一个值为11,新主下一个值仍是10。新连接才会生效,需要DBA kill连接 or 应用服务重启

    这一步会在旧节点上出现主键冲突。因为修改旧主的自增步长之后,仍然有旧连接是步长为1,主键值可能出现2 3 4,而新连接步长为2,自增值1 3 5

  2. 切换DNS到新主节点

    这一步切换后,新连接都请求新集群节点,但部分旧连接仍然请求旧集群连接,此时存在双写。但由于我们第一步修改了新旧节点的增长偏移和步长,这里的双写不会导致彼此主键冲突而导致数据丢失。同样,为了减少双写存在的时间,切换DNS后,需要DBA kill旧节点连接,使得写请求都流向新节点。

    这里还存在一个问题,即唯一键冲突问题,第一步修改主键自增偏移和步长只解决了双写时主键冲突问题,但原则上可能出现双写两端的唯一键冲突。但从业务上看,这一步几乎不可能发生(当然要根据业务的具体情况,在我们迁移的业务场景中,唯一键冲突几乎不存在,所以没有加以考虑和兼容);如果业务确实存在大量的唯一键写入冲突,那可能需要重新考虑下迁移方案了

  3. 恢复新主节点的偏移和步长为1

    同样,这一步的修改可能存在新主上的唯一键冲突(和第一步类似),因此,需要业务层有响应的重试机制兼容

总结

数据库集群迁移很难做到完全平滑,因为涉及主从节点切换时双写必然存在。尤其是在业务写入量比较大时,这种冲突更是很难避免。但是,从DB层做不到平滑,可以在业务层增加必要的重试机制,来保证客户端平滑。

重试机制,我更倾向于做尽可能少的逻辑重试,比如数据库增删改查原地重试,出现错误时最多重试3次,3次仍然错误就给客户端返回error

展望

我们当前数据库大小为1T,主表大小7亿+;日增300w行(且日增量仍在递增),存储周增15G;

数据库集群迁移扩容,并不是最彻底的解决方案,分库分表或者考虑TIDB更加合理。但因为业务紧急,有需求大表某字段长度要增加,因磁盘问题在线DDL无法操作,所以只能临时先集群迁移扩容。同时,我们分库分表的方案也在进行中,后面落地后,会在另一篇笔记中记录。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值