Binlog 日志应用场景

​https://cloud.tencent.com/developer/article/1444390​

什么是binlog?

Mysql 5.0以后,支持通过binary log(二进制日志)以支持主从复制。复制允许将来自一个MySQL数据库服务器(master) 的数据复制到一个或多个其他MySQL数据库服务器(slave),以实现灾难恢复、水平扩展、统计分析、远程数据分发等功能。

二进制日志中存储的内容称之为事件,每一个数据库更新操作(Insert、Update、Delete,不包括Select)等都对应一个事件。

Binlog 日志应用场景_数据

主要分为3个步骤:

  • 第一步:master在每次准备提交事务完成数据更新前,将改变记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log event,简称event)
  • **第二步:**slave启动一个I/O线程来读取主库上binary log中的事件,并记录到slave自己的中继日志(relay log)中。
  • **第三步:**slave还会起动一个SQL线程,该线程从relay log中读取事件并在备库执行,从而实现备库数据的更新。
  1. 客户端向master的mysql sever写入数据
  2. 当数据发生变化时,master将变更的数据记录写入到二进制文件中,即binlog。
  3. slave订阅了master的binlog,所以会通过一个I/O THREAD与master的DUMP THREAD进行通信,同步binlog
  4. I/O THREAD读取到binlog后会吸入到relay log中,准备重放。
  5. slave会通过SQL THREAD读取relay log,重放数据的改动并执行相应的改动。

这里有几点需要注意:

  1. 主从复制不是强一致性,只能保证最终一致
  2. master配合binlog复制会影响性能,所以尽量不要在master上挂太多的slave,如果对时间要求不高,可以在slave上挂slave

binlog的业务应用

上面介绍了mysql中应用binlog的场景,而我们的业务可以伪装成master的slave节点,感知数据的变化,这就给了我们很多的业务运用空间。

Binlog 日志应用场景_缓存_02

1. 数据异构

经常有这样一个场景:

原来业务是一个很单一的系统,所以表也在一起。随着业务的发展,系统开始拆分,总有一些表是各个业务都关注的表,但是对相关的字段的运用场景不同,所以这样一份元数据怎样更好的为各个系统服务就成了问题。当然,多写或者读写分离可以从物理节点上减少对数据服务器的压力,但是对业务并没有做到足够的支持,因为这些表都是一样的。因此我们可以通过binlog进行数据异构。

Binlog 日志应用场景_缓存_03

如图所示,订单系统生成订单后,通过binlog可以解析生成用户维度的订单信息供用户中心查询、商户维度订单表供运营管理,以及搜索系统的搜索数据,提供全文搜索功能。

这样,我们就通过原始的订单数据异构到三个系统中,提供了丰富的数据访问功能。不仅从节点上降低了数据服务器的压力,数据表现形式也更贴近自己的服务,减少不必要的字段冗余。

2.基于数据的任务分发

有这样一个场景:

很多系统依赖同一块重要数据,当这些数据发生变化的时候,需要调用其他相关系统的通知接口同步数据变化,或者mq消息告知变化并等待其主动同步。这两种情况都对原始系统造成了侵入,原始系统改一块数据,并不想做这么多其他的事情。所以这时候可以通过binlog进行任务分发。

Binlog 日志应用场景_异构_04

当原始业务系统修改数据后,不需要进行其他的业务关联。由调度系统读取binlog进行相应的任务分发、消息发送以及同步其他业务状态。这样可以将其他业务与原始业务系统解耦,并从数据的角度将所有管理功能放在了同一个调度系统中,责任清晰.

3. 缓存数据的补充

对于高并发的系统,数据库往往是系统性能的瓶颈,毕竟IO响应速度是远远小于电子的运算速度的。因此,很多查询类服务都会在CPU与数据库之间加上一层缓存。即现从缓存获取,命中后直接返回,否则从DB中获取并存入缓存后返回。而如果原始数据变化了但缓存尚未超时,则缓存中的数据就是过时的数据了。当数据有变更的时候主动修改缓存数据。

Binlog 日志应用场景_binlog_05

当客户端更改了数据之后,中间件系统通过binlog获得数据变更,并同步到缓存中。这样就保证了缓存中数据有效性,减少了对数据库的调用,从而提高整体性能。

4.读写分离

最典型的场景就是通过Mysql主从之间通过binlog复制来实现横向扩展,来实现读写分离。如下图所示:

Binlog 日志应用场景_binlog_06

在这种场景下:

  • 有一个主库Master,所有的更新操作都在master上进行
  • 同时会有多个Slave,每个Slave都连接到Master上,获取binlog在本地回放,实现数据复制。
  • 在应用层面,需要对执行的sql进行判断。所有的更新操作都通过Master(Insert、Update、Delete等),而查询操作(Select等)都在Slave上进行。由于存在多个slave,所以我们可以在slave之间做​​负载均衡​​。通常业务都会借助一些数据库中间件,如tddl、sharding-jdbc等来完成读写分离功能。

binlog 监听订阅平台

在实际开发中,你可以每个应用场景都模拟一个slave,各自连接到Mysql上去拉取binlog,master会给每个连接上来的slave一份完整的binlog拷贝,业务拿到各自的binlog之后进行消费,彼此之间互不影响。但是这样,有一些弊端,多个slave会给master带来一些额外管理上的开销,网卡流量也将翻倍的增长。

我们可以进行一些优化,之所以不同场景模拟多个slave来连接master获取同一份binlog,本质上要满足的是:一份binlog数据,同时提供给多个不同业务场景使用,彼此之间互不影响。

显然,消息中间件是一个很好的解决方案。现在很多主流的消息中间件,都支持consumer group的概念,如kafka、rocketmq等。同一个topic中的数据,可以由多个不同consumer group来消费,且不同的consumer group之间是相互隔离的,例如:当前消费到的位置(offset)。

kafka, rocketmq 消费者组

因此,我们完全可以将binlog,统一都发送到MQ中,不同的应用场景使用不同的consumer group来消费,彼此之间互不影响。此时架构如下图所示:

Binlog 日志应用场景_异构_07

binlog 长啥样?

参考: https://cloud.tencent.com/developer/article/1444390

总结

binlog是mysql提供的数据同步机制,很好的解决了主从分离、读写库分离等业务。而我们可以构建一个中间件系统,“伪造”成master的一个slave。当读取了binlog中的数据变化后,根据相应的业务场景做各种业务处理。而目前我接触到的最常见的就是第一个场景——数据异构,可以异构到其他表中,也可以异构到其他数据引擎中,比如Elastic Search。