天天看点

近期对semisync的一些优化

最近对同机房semisync性能优化告一段落,性能基本能达到预期;目前优化的版本基于mysql5.6.14,基本优化思路是让备库尽快的发送ack。主要的优化点简单总结下:

a).备库在接受到需要ack的事件时,先ack,再去写relay log。对于不需要ack的事件只写io cache

原始行为为每接受到一个事件就写一次relay log,在同机房场景下,可能存在网络io已经完成,备库还没写完数据到磁盘

b).备库在需要ack时才去刷master info文件

原始行为是每接受一个事件写一次master_info文件

a)和b)以牺牲备库日志的持久化来提升semisync场景下的主库性能,当备库挂了时,只需要从一个安全的位点重拉binlog即可;

使用sysbench测试的结果:tps 13000(原生semisync) => 24000 (改进后semisync)

无semisync的tps约为28000

上述测试同时基于以下的改进

c).主库上在事务commit之前等待备库ack(after_sync),在等待期间其他事务无法看到等待线程所做的修改,如果主库挂了,切换到备库后,应用连接只需要检查数据是否更新成功即可 (port  from  mysql5.7.2)

原始行为为在事务commit之后(after_commit),每个应用连接等待备库ack,这种情况下在主备切换后,应用连接将无法判断其事务是否成功提交(数据可能被修改多次)

after_sync比after_commit更能保证数据的一致性,并且有一定的性能提升,因为在after_sync发生在innodb group commit之前,由leader线程来等待,只需要唤醒leader,而after_commit在大thread running下,可能需要唤醒大量应用连接,开销更大

d).mysql_binlog_send函数不再需要持有lock_log锁来读取binlog事件,而是维持一个文件末尾的偏移量;(port from mysql5.7.2, facebook mysql5.6有类似实现)

原始行为中,写binlog和读binlog都需要lock_log这个大锁来保护,这会导致锁竞争,如果有多个备库dump线程,这种竞争会影响到tps

e).在rotate时,需要生成下一个binlog文件,在设定文件名后缀时,避免扫描整个文件夹,改为维护一个递增数字

其他一些小的修改点不一一列出;

semisync接下来潜在的优化点:

a).大量dump线程对主库性能的影响需要纳入考虑(例如bug#70342)

b).如何保证主备库的强一致;例如,主库宕机,事务已写入本地binlog,但还没发送到备库;主备切换后,如果应用链接在备库重试事务,则主备一致;如果应用抛弃该事务,或走其他逻辑,那么挂掉重启后的主库可能比备库多执行了事务(利用adha回滚机制?)

c).在跨机房场景下,网络称为瓶颈时,如何解决(并发网络io?)

d).内建semisync,而不是通过plugin的形式,是否可能带来性能提升?

e).主库semisync 的大锁对性能的影响?