开发者学堂课程【PolarDB-X 开源系列课程:数据导入与导出(四)】学习笔记与课程紧密联系,让用户快速学习知识
课程地址:https://developer.aliyun.com/learning/course/1032/detail/15143
数据导入与导出(四)
四、Replica
接下来看一下Replica的内容,这个内容会比Binlog相对来说少一些。
首先可以完成什么样的功能?Replica可以实现数据的流入,它可以和MySQL之间实现双向同步,也可以和PolarDB-X之间实现双向同步。它的架构大概是这样的:任务调度、任务运行这两个部分,然后通过一系列的流水线变更,来去消费源端的Binlog数据,把这些数据导入到PolarDB-X内部。有人说DDL操作时DMR会报错,我的意思是说DDL,比如说它之前只有a b两个列,你在加c列这个变更过程中,因为DDL还没变更完,那DMR操作里边真实的业务SQL肯定只有insert a b这两列,但是如果在变更过程中,如果你的DMR插入一个c列,肯定是会报错的,因为整个DDL执行完成之后,它才会返回给客户端这个DDL成功了。其实MySQL也是一样的,如果提交了一个MySQL加列的操作,那这个DDL如果还没变更,还没有执行完,如果你执行一个DMR操作,已经包含了正在加的这一列,那肯定是会报错的。
Replica内部的小知识点就是它的写入模式。首先,可以保证事务完整性的写入,就是源端MySQL的Binlog里面,我们在消费的时候,它的事务是什么样?我们就可以去串行的消费,并且在写入的时候也能保证事务的完整性,但这种模式性能一般会比较差。
还有一种消费就是牺牲事务,我们会按照唯一键进行哈希,哈希完之后并发地往目标端去做协助,这样性能会比较好。
还有一种Merge的方式,除了做哈希我们还会做合并,比如说我们在哈希完之后会组装队列,在这个队列里边,会有一个Merge的操作,比如说有一条id为1的一条数据,在队列里边有连续的十次更新,那我们的算法就会把这十次更新合并成一次,这样在往目标端写入的时候,它就不是十次,只需要写一次,这样可以大大地提升性能。这是Replica内部来保证的写入的几个模式,以及不同模式的性能情况。
会有关于DMR语句的数据记录,比如加的C列它是有默认值的,它加完之后我们业务的SQL虽然说只插入了a b两列,但是这一列如果有默认值,在插入的时候在MySQL Binlog里边已经有c这一列的数据了,所以说是会有新列的数据的,虽然说外物感知不到,但是MySQL在记录Binlog的时候已经有这个列的数据了,所以说才会有整形的需求。
而且这不是一个遍历操作,是一个实时操作,它会有一个缓冲区,而且这个缓冲区在操作的时候不是一个纯遍历,它本身就是一个流逝的操作,只不过会有一个窗口,这个窗口内会有默认值的这样一个操作,速度是非常快的,熟悉Flink的同学应该知道,在流逝消费过程中,会有一个窗口,在这个窗口中就有一个数据的快速遍历,遍历完之后做一个Merge,再去写入就可以了。
还有同学问全局Binlog备份了以后怎么连CN,导入恢复到库里边。这个操作用原生MySQL的MySQL Binlog这个命令就行,通过MySQL Binlog以远程模式的访问来把全局Binlog拉到本地,拉到本地之后,导入恢复到库里边。这个其实也是借助MySQL Binlog,它有player这样的功能,因为playe这个操作其实是在MySQL Binlog工具内部的,它拿到Binlog之后,会构建出DMR语句,然后发送给PolarDB-X,所以说刚才这个问题就是导入和导出都是通过MySQL Binlog这个原生的工具做操作就可以,一个是MySQL Binlog的Dump,一个是通过MySQL Binlog做player操作。
然后看一下这个视频,这也是之前录好的视频,看字幕来感受一下PolarDB-X作为MySQL的slave的这样的能力。
以展示PolarDB-X的Replica这项能力,
接下来在源端MySQL处创建一个数据库,
然后在PolarDB-X里面检查一下这个库是否已经正常同步,
可以看到transfer_test这个库已经正常同步过来,说明我们的主备链路已经搭建完成。接下来启动转账测试脚本。转账测试脚本的基本模型是通过连接源端MySQL创建一张accounts表,并在里面写入100个账户,每个账户的初始余额为10000。
这个脚本已经开始运行,接下来看一下MySQL里面的数据情况。
再来看一下PolarDB-X的情况。
可以看到这些数据和增量已经开始同步,接下来停止转账测试,对MySQL里面的数据做一个MD5校验。
对下PolarDB-X里面的数据做一个同样的校验。
可以看到两个的MD5值一样。
刚才的demo讲的是一个PolarDB-X作为MySQL的slave,进行数据消费,并且验证了一下数据的一致性,可以保证数据的一致。
接下来最后一个demo来演示一下双向同步。因为我们在很多产品下边可能都需要涉及双向同步,比如说在同城双重新这样的场景或者自己的业务需要做双活等等这样的场景特别是需要双向同步这种能力的。
左上角是一个单机的MySQL,版本是8.0的。右边是一个PolarDB-X的实例,版本是5.4.13,目前是开源的版本。双向同步是通过server_id来做的,我们先看一下单机MySQL的server_id是什么,
是比较好记的名字——555。再来看一下PolarDB-X这边的server_id,是一个比较长串的数字,结尾是7011。
提前建好了一个rpl的库,库下边有一个表叫t1,里边没有数据。在PolarDB-X这边也是一样的,也是有一个rpl库,有一张t1表,表里边也没有数据,表结构也是一致的。
接下来看一下单机MySQL的Binlog,
目前是679,最大的编号是000003,再看一下PolarDB-X的Binlog,
看一下两边的Binlog情况。刚才拿到了各自的server_id,看到了两边各有一张t1表,然后还看了一下它们当前Binlog的最新状态。接下来就要开始配置同步。
先配置PolarDB-X到MySQL的同步,脚本已经准备好。
重点看一下IGNORE_SERVER_IDS,这里意思就是说PolarDB-X消费单机MySQL的Binlog的时候,如果从Binlog里边看到了SERVER_ID等于7011这样一个值,Binlog日志就会把它忽略掉。指定位点,然后IGNORE_SERVER_IDS。这个IGNORE_SERVER_IDS就是它自己的,为什么忽略?就是在双向同步的时候为了避免回还, 要把它标识成自己SERVER_ID的数据过滤掉。
把链路创建起来,再看一下状态。
PolarDB-X消费单机MySQL的链路就创建完成了。因为我们是要演示双向同步,接下来就再去配置一下单机MySQL到PolarDB-X的主从同步, 同样的关注一下IGNORE_SERVER_IDS是555,就是刚才单机MySQL的server_id。同理,它要过滤掉它自己的。
操作步骤和MySQL主从同步是一样的。
以单机MySQL为slave,PolarDB-X为主的主从链路也创建好了。这时候看下它的状态。
双向同步已经构建完成。接下来就演示一下双向同步场景下边数据是怎么做双向同步的?
先在MySQL里边插入一条数据,id为1。
数据已经成功插入,查一下这条数据。
数据已经插入。然后在PolarDB-X这边来验证一下,正常情况肯定是已经同步过来了。
这条数据已经过来了。接着从Binlog里面看一下,这里面是一个重点,
就是Binlog里面看server_id是555,因为这条数据是从单机MySQL里面同步过来的,所以这里面记录的server_id就是555。如果不是同步过来的数据,是它自己插入的数据,就是PolarDB-X自己的server_id,这一点和原生MySQL的行为是完全一致的。就是MySQL主从同步的时候,从库在消费主库Binlog的时候,它的Binlog里边的server_id也是这样的形态,如果是从控制台进行的操作,那Binlog里面的server_id是它自己的。如果是从其它master消费的Binlog过来的,它记录的server_id是上游master的那个server_id。可以看到PolarDB-X是一样的行为。
然后看一下MySQL这边已经正常同步完所有的Binlog,并没有报错,说明刚才的IGNORE_SERVER_IDS已经生效了。
因为这边Binlog里面记录的是555。然后左边消费的时候IGNORE_SERVER_IDS就是会把它过滤掉,如果没有生效,那右边可能会报错, 因为它这边id为1的,如果回还回来之后,它把id为1的数据重新插入,肯定会有主线冲突的报错,但是可以看到它并没有报错,正常消费。
然后在PolarDB-X这边也插一条数据,
可以看到2这条数据也已经同步到了单机MySQL,就是这两边的双向同步,我们都进行了验证。
我们也去看一下单机MySQL的Binlog里边的内容。
可以看到这边的server_id,刚刚那个555是刚才插入的那个1,下边的7011是刚刚PolarDB-X这边刚刚插入的2这条数据,我们可以看一下单机MySQL的server_id,保存的是PolarDB-X的,和刚才描述的PolarDB-X这边的形态是一致的。
右边还有一个小特性,这个特性是PolarDB-X内核提供的一个能力,这个命令叫set polardbx server_id=555,这个命令作用就是说如果我执行了这条命令,从控制台插入的数据在PolarDB-X的全局Binlog里边,它的 server_id就会以set的这个server_id为基准,意思就是说它不会用默认值。我们来验证一下,
插入了一条id为3的数据,然后看一下已经插入成功。按照刚才的讲解,如果执行了set polardbx server_id=555这样的指令之后,在源端的Binlog里面,就会记录555,我们预期的行为是555,这个刚刚插入的3这个数据,它不应该同步到单机MySQL,看一下这条数据的确没有同步过来。
我们插入到这条数据,它的server_id是555,所以说是没有同步过去的,跟刚才描述的行为是一致的。这个双向同步的演示大概就是这样。
为什么会封装set这样的命令?这个命令其实是非常有用的。如果大家在用PolarDB-X的时候,有自己的一些需求,比如说我不是通过单机MySQL这种change master命令来做同步,比如大家自己有中间件,有各种各样搭建的自己的同步系统,其实是可以靠这种能力来搭建自己的双向同步的,是一个非常方便的功能,感兴趣的同学可以去深入地研究一下。