挖掘数据库日志(Binlog)的方式,将数据库变更实时、可靠的从数据库拉取出来,业务可以通过定制化client实时获取变更。分享个基于关系型数据库日志增量订阅的组件,调研图
Binlog
mysql有多种日志,常见的有:
- 错误日志(ErrorLog)
- 更新日志(UpdateLog)
- 二进制日志(Binlog)
- 查询日志(QueryLog)
- 慢查询日志(SlowQueryLog)
Binlog记录了所有的DDL和DML(除了数据查询语句)语句,以事件形式记录,还包含语句所执行的消耗的时间,此外Binlog是事务安全型的。
Binlog一般作用是可以用于实时备份,与master/slave主从复制结合。
MySQL 主从复制原理的是啥?
- 主库db的更新事件(update、insert、delete)被写到binlog(二进制文件)
- 从库发起连接,连接到主库
- 此时主库创建一个binlog dump thread,把binlog的内容发送到从库
- 从库启动之后,创建一个I/O线程,读取主库传过来的binlog内容并写入到relay log
- 从库还会创建一个SQL线程,从relay log里面读取内容,从Exec_Master_Log_Pos位置开始执行读取到的更新事件,将更新内容写入到slave的db
可以知道,对于每一个主从复制的连接,都有三个线程。拥有多个从库的主库为每一个连接到主库的从库创建一个binlog输出线程,每一个从库都有它自己的I/O线程和SQL线程。
数据丢失问题
如果主库突然宕机,恰好数据还没同步到从库,那么有些数据可能在从库上是没有的?
MySQL 实际上在这一块有两个机制,一个是半同步复制,用来解决主库数据丢失问题;一个是并行复制,用来解决主从同步延时问题。
半同步复制
也叫 semi-sync
复制,指的就是主库写入 binlog 日志之后,就会将强制此时立即将数据同步到从库,从库将日志写入自己本地的 relay log 之后,接着会返回一个 ack 给主库,主库接收到至少一个从库的 ack 之后才会认为写操作完成了。
并行复制
从库开启多个线程,并行读取 relay log 中不同库的日志,然后并行重放不同库的日志,这是库级别的并行,MySQL 5.6版本之前是这样的。
主从同步延时问题
MySQL的复制延迟是一直被诟病的问题之一。MySQL 5.6版本前仅仅支持到库级别的并行确实会导致复制延迟问题。大家也可能遇到这样的尴尬情况:先插入一条数据,再把它查出来,然后更新这条数据。在生产环境高峰期,写并发达到了 2000/s,这个时候,主从复制延时大概是在小几十毫秒。线上会发现,每天总有那么一些数据,我们期望更新一些重要的数据状态,但在高峰期时候却没更新。
show status
//查看结果 Seconds_Behind_Master,可以看到从库复制主库的数据落后了几 ms
一般来说,如果主从延迟较为严重,有以下解决方案:
- 分库,将一个主库拆分为多个主库,每个主库的写并发就减少了几倍,此时主从延迟可以忽略不计
- 打开 MySQL 支持的并行复制,多个库并行复制。如果说某个库的写入并发就是特别高,单库写并发达到了 2000/s,并行复制还是没意义
- 适用场景有问题,如果确实是存在必须先插入,立马要求就查询到,然后立马就要反过来执行一些操作,对这个查询设置直连主库。不推荐这种方法,你要是这么搞,读写分离的意义就丧失了。
当然升级到MySQL 5.7是非常棒的!MySQL 5.7基于组提交的并行复制,可称为真正的并行复制,并行复制的思想简单易懂,一言以蔽之: 一个组提交的事务都是可以并行回放 ,因为这些事务都已进入到事务的prepare阶段,则说明事务之间没有任何冲突(否则就不可能提交)。这其中最为主要的原因就是slave服务器的回放与主机是一致的(master服务器上是怎么并行执行的slave上就怎样进行并行回放)。不再有库的并行复制限制,对于二进制日志格式也无特殊的要求(基于库的并行复制也没有要求)。从MySQL官方来看,其并行复制的原本计划是支持表级的并行复制和行级的并行复制,行级的并行复制通过解析ROW格式的二进制日志的方式来完成, WL#4648 。但是最终出现给小伙伴的确是在开发计划中称为:MTS: Prepared transactions slave parallel applier,可见: WL#6314 。该并行复制的思想最早是由MariaDB的Kristain提出,并已在MariaDB 10中出现,相信很多选择MariaDB的小伙伴最为看重的功能之一就是并行复制。
查看主从复制状态
当主从复制正在进行中时,如果想查看从库两个线程运行状态,可以通过执行在从库里执行”show slave status\G”语句,以下的字段可以给你想要的信息:
Master_Log_File 上一个从主库拷贝过来的binlog文件
Read_Master_Log_Pos 主库的binlog文件被拷贝到从库的relay log中的位置
Relay_Master_Log_File SQL线程当前处理中的relay log文件
Exec_Master_Log_Pos 当前binlog文件正在被执行的语句的位置
总结,读写分离分散数据库读写操作压力,分库分表分散存储压力。
参考资料