如何利用全量缓存打造毫秒级的读服务?
上一讲我们介绍了一个简单易实现,且成本较低的高性能读服务方案及其升级方案,但其中仍有两个问题暂未完全解决:
第一个问题是为了保证缓存更新实时性而带来的分布式事务的问题;
第二个问题是懒加载导致的毛刺问题。
在本讲里,我将针对上述两个问题,和你一起利用全量缓存打造一个无毛刺、平均性能在 100ms 以内的读服务。
全量缓存的基本架构
全量缓存是指将数据库中的所有数据都存储在缓存中,同时在缓存中不设置过期时间的一种实现方式,此实现的架构如下图 1 所示:
图 1:全量缓存的架构图
因为所有数据都存储在缓存里,读服务在查询时不会再降级到数据库里,所有的请求都完全依赖缓存。此时,因降级到数据库导致的毛刺问题就解决了。
但全量缓存并没有解决更新时的分布式事务问题,反而把问题放大了。因为全量缓存对数据更新要求更加严格,要求所有数据库已有数据和实时更新的数据必须完全同步至缓存,不能有遗漏。
对于此问题,一种有效的方案是采用订阅数据库的 Binlog 实现数据同步。
基于 Binlog 的全量缓存架构
在实施基于 Binlog 的架构方案前,我先简单介绍下 Binlog,更加详细的介绍我将在“05 讲”里和你讨论。首先看下 Binlog 的原理,如下图 2 所示:
图 2:Binlog 原理图
Binlog 是 MySQL 及大部分主流数据库的主从数据同步方案。主数据库会将所有的变更按一定格式写入它本机的 Binlog 文件中。在主从同步时,从数据库会和主数据库建立连接,通过特定的协议串行地读取主数据库的 Binlog 文件,并在从库进行 Binlog 的回放,进而完成主从复制。
现在很多开源工具(如阿里的 Canal、MySQL_Streamer、Maxwell、Linkedin 的 Databus 等)可以模拟主从复制的协议。通过模拟协议读取主数据库的 Binlog 文件,从而获取主库的所有变更。对于这些变更,它们开放了各种接口供业务服务获取数据。
基于 Binlog 的全量缓存架构正是依赖此类中间件完来成数据同步的,架构如下图 3 所示:
图 3:基于 Binlog 的缓存同步架构图