干货|携程多活动-MySQL实时双向(多方向)复制实践

电脑杂谈  发布时间:2020-07-18 15:22:32  来源:网络整理

php获取当前时间 毫秒_mysql 获取当前毫秒_php 获取当前时间到毫秒

作者

Roy是携程软件技术专家,负责MySQL双向同步DRC和访问中间件DAL的开发和发展. 他对分布式系统的高可用性设计和数据一致性感兴趣.

携程的内部MySQL部署采用多机房部署. 机房A部署了一个主机和一个从机,机房B部署了一个从机,用作DR(灾难恢复)交换机. 在当前部署下,部署在计算机房B中的应用程序需要跨计算机房编写. 当计算机机房A发生故障时,DBA需要手动切换DR.

为了在不同地方实现真实数据的多种活动,请在附近的同一计算机室中实现MySQL读写. 当计算机机房发生故障时,无需执行DR操作. 只有流量交换需要引入实时双向(多向)数据复制组件.

DRC(数据复制中心)是由携程框架体系结构研发部门推出的用于双向或多向数据复制的中间件. 在公司G2(高质量优质服务,全球化)战略的背景下,它为不同地方的Multi-active项目提供服务,从而为企业提供了全球部署功能.

DRC采用服务器端集中式设计,并与另一个访问中间件DAL(数据访问层)的本地读写功能配合以实现附近的数据访问.

模块介绍

复制器容器实现对复制器实例的管理. Replicator实例代表MySQL群集的复制单元. 实例伪装成MySQL从站,以实现Binlog拉取和本地存储.

Applier容器实现对Applier实例的管理. 将Applier实例连接到Replicator实例,以提取本地存储在Replicator实例中的Binlog,然后解析SQL语句并将其应用于目标MySQL,从而实现数据复制.

Cluster Manager负责群集的高可用性切换,包括由MySQL主从切换引起的Replicator和Appliance实例重启,以及由Replicator和Appliance实例之间的主从切换引起的新实例启动的通知.

控制台提供UI操作,外部系统交互API和监视警报.

DRC的核心指标包括复制延迟和数据一致性.

为了实现低数据复制延迟,Applier可以快速应用SQL,并且每个表至少需要包含一个主键或唯一键以提高执行效率;同时,在确保数据准确性的前提下,应尽可能并行地复制SQL,要求MySQL启用从5.7.22版引入的Writeset函数.

为了确保数据复制的准确性,当主用/备用切换时,Replicator仍可以准确地定位Binlog站点,并且MySQL需要启用GTID. 当数据复制冲突时,为了具有自动解决冲突的能力,该表需要包含一个时间戳列,并且精确到毫秒.

这需要访问DRC的MySQL才能满足:

1)5.7.22及更高版本;

2)在母版上打开Writeset并行副本;

3)MySQL打开GTID;

php获取当前时间 毫秒_php 获取当前时间到毫秒_mysql 获取当前毫秒

4)每个表都包含一个时间戳列,精确到毫秒;

5)每个表至少包含一个主键或一个唯一键.

DRC复制依赖于GTID(全局事务ID),这是GTID概念的简要介绍. MySQL 5.6.5版本增加了新的基于GTID的复制方法,该方法增强了的主和备份一致性,故障恢复和容错能力,取代了传统的基于文件和位置的主从复制,以便在MySQL在主服务器和主服务器之间切换时从站,仍然可以准确定位Binlog站点.

GTID的格式如下: source_id: transaction_id,其中source_id代表MySQL服务器的uuid,transaction_id是提交事务时系统分配的序列号.

单向复制链接包括用于复制Binlog并将其持久化到本地磁盘的Replicator,以及请求Binlog并将其并行应用于目标MySQL的Applier. 整个链接中涉及的I / O操作包括网络传输和磁盘读写.

为了减少复制延迟,要求复制链接中的每个环都尽可能地高效. 网络层通信模型使用异步I / O. 系统层尽可能使用操作系统提供的零拷贝和页面缓存;应用层改善了数据处理的并行性,并减少了系统的不可用时间.

监控显示,生产环境业务的双向复制被延迟了999行

Replicator采用GTID复制方法来实现MySQL复制协议,并假装是源MySQL提取Binlog的从属. 网络层通信组件使用携程的开源组件XPipe()来实现异步网络交互.

接收Binlog时,将从数据流中解析不同类型的事件,并将其直接存储在堆外内存中. 每个事件都需要通过一组过滤器,以确定是否需要将其放置在持久性顺序中. 心跳类型的事件需要过滤并丢弃;对于一些不需要数据同步的库和表,需要丢弃相应的事件以减少存储和传输;对于需要持久性的事件,直接将数据写入堆外内存中. 进入文件页面缓存并定期刷新磁盘,以减少数据复制和IO操作,减少处理时间并提高复制器提取效率.

在发送Binlog时,当Applier进度落后于Replicator并且需要从磁盘读取时,此时仅解析gtid_event事件,而其他需要发送的事件则直接从磁盘读取到磁盘. 堆外内存用于发送,减少了数据复制.

Applier利用基于Writeset的本地MySQL的并行复制,并嵌入一个基于水位的并行算法,以将SQL有效地应用于目标.

除了正常复制之外,为了减少系统的不可用性,还必须使系统在异常情况下尽快恢复正常功能. 例如,从断开连接中恢复时,为了防止一端使用旧的连接,该连接需要空闲;为了应对由于断开而导致的数据累积突然增加,有必要控制流量.

复制器和MySQL,应用程序和复制器通过Netty传输数据. 当网络出现故障时,一端可能仍会使用旧的连接进行通信,这将导致数据复制被中断.

为响应网络故障,Replicator将读取空闲检测添加到MySQL. 启动时,将MySQL设置为在空闲时每10秒发送一次heartbeat_event. 如果30秒钟内未收到MySQL事件,则认为MySQL存在问题并启动了重新连接.

复制器为Applier设置写空闲检测. 如果没有要发送给应用程序的事件,则heartbeat_event每10秒发送一次. 如果发送失败,则认为应用程序有问题,并且连接已断开.

Applier为Replicator设置了读取空闲检测. 如果30秒钟内未从Replicator接收到任何事件,则认为Replicator存在问题,并启动了重新连接.

复制器容器设计为使用将运行多个复制器实例的物理机,而应用器容器使用虚拟机,这将导致发送率和使用率之间不匹配. 尤其是当请求器由于某种原因而失败时,大量未使用的事件会在复制器端累积. 重新启动后,如果所有累积的事件都被发送出去,则Applier可能会被直接销毁. 这要求将Applier限制在Replicator实例上.

复制器的发送端使用Netty提供的WRITE_BUFFER_WATER_MARK的更改来控制流量控制开关,然后动态调整发送速率,调整流量的形状和平滑度.

php 获取当前时间到毫秒_mysql 获取当前毫秒_php获取当前时间 毫秒

4.2.2数据一致性

为了确保数据的一致性,需要满足以下条件:

1)保证提取数据的时间;

2)不能省略数据提取,SQL应用程序不繁重,甚至重复执行,必须保证幂等操作mysql 获取当前毫秒,并且至少要保证一次;

3)当数据冲突时,可以正确处理它以确保数据最终一致.

让我们看看DRC如何保证上述三个要求.

本地磁盘使用本机存储协议保存Binlog,复制器按顺序处理它收到的每个事件事件. 该存储协议与MySQL的本地mysqlbinlog命令兼容. 根据DRC自己的需要,保存了一些自定义辅助事件,例如DDL事件和表结构事件. 在使用期间,Binlog文件中的事件会顺序发送到Applier.

2)至少一次

为了至少实现一次,需要解决3个子问题:

1)Replicator或Applier重新启动时,如何确保所请求的GTID集准确反映当前消耗的偏移量?

2)双向(多向)复制如何解决循环复制?

3)当申请人由于异常而反复退出时,如何确保幂等?

每个子问题的解决方案都一一介绍.

Replicator重新启动时,它将恢复从本地磁盘中拉出的GTID集:

1)找到重新启动之前使用的最后一个Binlog文件;

2)解决previous_gtids_event;

3)遍历文件中的所有gtid_event,并与由previous_gtids_event解析的GTID集进行联合.

在恢复过程中,将验证文件的正确性. 对于不以xid_event结尾的事务,Replicator将截断文件,并且相应的gtid事务将重新请求.

mysql 获取当前毫秒_php 获取当前时间到毫秒_php获取当前时间 毫秒

当Applier重新启动时,群集管理器将从目标中查询当前执行的GTID集并将其发送给Applier,Applier将使用此参数将Binlog提取请求发送到Replicator. 复制器接收请求中设置的GTID,从本地磁盘中找到要发送的第一个事件所在的Binlog文件,依次遍历文件中的每个事件,在gtid_event事件中取出gtid,并确定相应的gtid无论交易是否包含在GTID集中(如果包含),这意味着Applier已经使用了该交易,因此不需要发送,否则该事件通过堆外内存直接发送到Applier.

在单向复制期间,通过DRC复制到另一端的SQL在执行后也将落入MySQL Binlog中. 这样,在双向(多向)复制结构中,相反的Replicator实例将拉动Binlog. 如果以后继续复制,则会出现循环复制的问题.

对于循环复制,行业的可选解决方案是在Binlog事务的开头插入写操作,以标识该事务是由DRC复制的,而不是实际的业务写,以便对等复制器发现事务包含开头的DRC带有特殊标记的交易将不会继续被复制.

分析MySQL本身的主从复制. 当从站接收到由主站同步的Binlog时,它通过设置gtid_next将事务的GTID设置为同步的gtid_event中的GTID,从而实现了主从GTID集的一致性.

如果复制器将Binlog类比拉到Slave I / O线程,磁盘文件类比是Relay日志,Applier类比是Slave SQL线程,则Applier可以使用相同的方法,并使用gtid_next集设置以复制到DRC相对事务的GTID,以便源和目标的GTID集将保持一致,更重要的是,可以识别出该事务是由DRC复制的. 这也是DRC最终用于破解循环副本的解决方案.

双向复制结构如下. Replicator Instance1将仅同步源MySQL集群uuidSet1中的服务器以生成事务,而Replicator Instance2将仅同步目标MySQL集群uuidSet2中的服务器以生成事务. 如果企业在源MySQL集群中写入了一条数据,则复制器Instance1从gtid_event中的GTID解析uuid以发现uuid属于uuidSet1,然后它将被持久化到磁盘并发送到Applier Instance1. 在Applier Instance1接收到事务中包含的所有事件之后,它将执行set gtid_next = GTID,然后通过JDBC将SQL写入目标MySQL,以完成单向复制. 在Replicator Instance2收到gtid_event之后,它还会解析GTID,但是uuid不属于uuidSet2,因此将对事务进行过滤并避免循环复制.

如果申请人重复接收相同的GTID事务,因为MySQL会记录已执行的GTID集,如果GTID已执行,它将自动忽略它,因此即使申请人重复应用相同的事务,它不会引起业务影响.

从上面可以看到,在确保数据一致性时,在复制器和Applier重新启动后,GTID用于定位Binlog站点,标识Binlog的源以避免循环复制,或者在重复应用Applier时实现幂等. 重要角色.

在设计中,我们必须首先避免冲突:

1)将根据交通入口处的uid划分对Set服务的访问权限,同一用户的交通将进入同一计算机房;数据访问层中间件DAL也将使用local-2-local路由策略. 这样,很少在同一时间在两个计算机室中修改同一记录;

2)对于使用自我递增ID的企业,请通过不同的计算机机房设置不同的自我递增ID规则,或者采用分布式全局ID生成方案,以避免双向复制后的数据冲突.

如果数据确实存在冲突,则两个计算机房修改同一条数据,则需要根据冲突处理策略进行处理:

1)申请人根据默认的冲突处理策略处理冲突. 连接到DRC的表具有一个时间戳,该时间戳会自动更新为毫秒精度. 当发生冲突时,将采用稍后的时间戳以实现数据一致性; <


本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/ruanjian/article-284861-1.html

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    • 阿里不哥
      阿里不哥

      期待宋歌手

    • 李体仁
      李体仁

      前提是这些男性必须提升自己的颜值和身材

    • 何炅
      何炅

      几次讲话让人感觉水平差了点

    热点图片
    拼命载入中...