0
点赞
收藏
分享

微信扫一扫

TDSQL强同步复制

一.概述

通过分析,我们发现MySQL原声半同步复制缺陷:

1、MySQL半同步复制支持退化成异步复制,在严格的金融场景不一定合适。

2、MySQL在Slave在收到Master的binlog时,默认情况下无法保证relay log实时落盘,即sync_relay_log=0,如果需要保证relay log实时落盘,即sync_relay_log=1,则每个event会调用一次fsync,数据库性能大幅下降。

3、MySQL在等待Slave返回ACK时工作线程是阻塞状态的,若长时间收不到ACK,用户提交被挂起,

      1>如果要提高并发则要会开启更多的线程,而线程越多,时耗就越不稳定,性能达到某个值之后会下降.

       2>在跨IDC等延时比较大的情况下,MySQL半同步复制性能下降比较厉害。

因此,TDSQL强同步复制主要改造如下:

1、如果Master等待Slave ACK出现超时,则返回给客户端失败,但不可退化模式下强同步复制不退化成异步复制,确保主备数据强一致,主备切换事物0丢失,满足金融场景的需求。

2、增加rpl_slave_ack_thread线程,循环取出io_thread接收到的binlog 和pos等信息,且只处理最后一个,如果对列为空,则等待,可以通过组的机制来实现,性能与异步相当,

      1> 启用该功能后,从库io_thread不是在接收主库的event之后立即写入磁盘(也不是 fsync),而是将 binlog 文件名和偏移量插入一个队列。  

      2> 使用rpl_slave_ack_thread线程从队列中获取binlog位置信息,然后写入binlog_cache,并fsync,然后给强同步主库回ACK消息。

3、强同步复制采用线程池+业务线程易步化,充分利用资源,性能接近异步

      1> 在Master等待Slave ACK的过程中,会将会话保存起来,然后线程切换到其他的的会话处理,不用无谓的等待。

       2> 性能提升的同时响应时间会增加,但在高并发场景下TPS不下降。

二、强同步复制的原理:

TDSQL强同步复制_客户端

首先Master上一笔写请求到达,线程池分配连接处理该请求,当收到commit之后先写binlog,这时继续往下应该回吐客户端信息,但对于开启了强同步的服务来说,此时会先hold住这个操作,在内存保存会话信息。

然后可以继续处理其链接的请求。此时客户端还不能收到应答,啥时候能收到应答呢?Master启动之后,会先启动一个udp服务器,用来接受Slave收到binlogACK请求,同时再启动16个工作线程,当收到ACK请求时,这16个线程其中之一去唤醒刚刚保存的会话,执行下半段(如执行引擎层提交等)并对客户端返回应答信息。

所以,在Master上新开了两组线程,一组为接受ACK应答线程(Dump ACK Thread),另外一组为唤醒hang住的客户端连接线程(User ACK Thread)Slave这里比较简单,就是在io线程刷盘relay log时给Masterudp线程发一个应答包。、

三、核心参数

sqlasyn=ON

● 是否开启强同步模式。Master和Slave需同时开启该参数,强同步才能正常工作。

● 注意:强同步必须和thread pool一起使用;针对使用extra port或者socket连接(没有使用thread pool),强同步模式失效。 sqlasyntimeout=30

● 强同步下Master等待Slave ACK最大时间;如果超时之后会报超时的错误并断开连接 。 tdsql_allow_async=OFF

● 如果Master没有收到Slave ACK,则允许降级为异步复制。 sqlasync_after_sync=OFF

● 如果为ON,则Master的用户线程在收到Slave ACK后进行engine commit,即AFTER_SYNC模式。如果为OFF,则AFTER_COMMIT模式。 sqlasynwarntimeout=3

● Master接收Slave ACK超过配置的时间,将会在error日志里打印信息,便于在网络、备机等异常的时候分析日志既可以发现一些线索。日志格式如下:

[ERROR] [MY-000000] [Server] session waiting for ack of binlog pos (2,5780) cost [6] sec,exceed 3 sec relay_log_sync_threshold=20000

● 在同步中继日志并将ACK发送给Master之前要累积的字节数。 relay_log_sync_timeout=1000

● 如果自从上次从IO线程fsync&ACK中继日志以来已经过去了这么多微秒,则IO线程无论如何都将fsync&ACK中继日志,而与relay_log_sync_threshold无关。此超时应该短于sqlasyntimeout,否则客户端在提交事务时将获得ER_RBTIMEOUT错误,然后断开连接。 relay_log_sync_txn_count=10

● 如果IO线程自上次fsync&ACK中继日志以来已接收到这么多事务的二进制日志,则无论其他限制如何,它将仍然fsync&ACK中继日志。 tdsql_relay_log_opt=OFF

● 如果为ON,始终在事务结束时刷relay log,以使relay log可靠。sqlasync_group_slave_ack=TRUE

● 是否开启slave节点使用group ack(merge fsync),保证数据持久化,减少IO。

举报

相关推荐

0 条评论