但核心系统如果对增值业务系统做太多的耦合适配,就会导致业务系统变得十分复杂,如何能既让增值服务拿到核心系统的资源,又能减少系统之间的耦合?
这节课我会重点带你了解一款内网主动缓存支撑的中间件,通过这个中间件,可以很方便地实现高性能实体数据访问及缓存更新。

为了减少业务系统中使用核心系统资源时过多的耦合,所以设计一个缓存支撑中间件。
大概的功能为:

  1. 数据主动缓存
  2. 数据查询直接由缓存中间件进行,查询时缓存不存在,由中间件去访问数据库计算得出结果
  3. 自动识别热点 Key,热点 Key 快速查询

1 实体数据主动缓存

期望效果:

  • 首先,具有类似于 Redis 的缓存功能,能缓存、有 TTL 机制;
  • 其次,当数据库数据发生变更后,能够主动的更新缓存中相关数据;
  • 再次,当查询的数据过期了,能够支持查询服务,生成缓存数据。

主动缓存方式:通过监听 MySQL binlog 日志获得数据变更,变更信息包含表名+主键 ID。回到数据库主库查询出最新数据,加工后推送到缓存中。
缓存查询服务:当查找缓存时如果没找到数据,中间件就会通过 Key 识别出待查数据属于数据库的哪个表和处理脚本,再按配置执行脚本查询数据库做数据加工,然后中间件将获取的数据回填到缓存当中,最后再返回结果。
提高查询效率:建议查询服务使用类似 Redis 的纯文本长链接协议,同时还需要支持批量获取功能,比如 Redis 的 mget 实现。如果我们的数据支撑架构很复杂,并且一次查询的数据量很大,还可以做成批量并发处理来提高系统吞吐性能。
避免缓存穿透:在缓存中加一个特殊标志,这样查询服务查不到数据时,就会直接返回数据不存在。万一真的出现缓存穿透问题时,还需要限制数据库的并发数目,建议使用 SingleFlight 合并并行请求,无需使用全局锁,只要在每个服务范围内实现即可。
排查同步问题:由于是数据库和缓存之间的同步,为了方便排查同步问题,建议在数据库中和缓存中都记录数据最后更新的时间,方便之后对比。

2 L1 缓存及热点缓存延期

500

  1. 若是热点 Key,直接从 L1 缓存读取;不是热点 Key,从集群缓存读取
  2. 异步统计近期内 Key 的访问频率,选择前 1000 个高频 Key 作为热点 Key
  3. 基于热点 Key 生成热点 Key 列表和布隆过滤器,用于查询时热点 Key 的快速判断
  4. 热点数据推送线程从数据库中拉取热点数据,不断更新热点 Key 结果和 TTL

3 关系数据缓存

对于量级更高的数据缓存系统,还可以引入多种数据引擎共同提供不同的数据支撑服务,比如:

  • lua 脚本引擎,是数据推送的“发动机”,能帮我们把数据动态同步到多个数据源;
  • Elasticsearch 负责提供全文检索功能;
  • Pika(RocksDB 的加强版)负责提供大容量 KV 查询功能;
  • ClickHouse 负责提供实时查询数据的汇总统计功能;
  • MySQL 引擎负责支撑新维度的数据查询。

4 多数据引擎平台

500

5 思考题

L1 缓存使用 BloomFilter 来减少 L1 缓存查询,那么 BloomFilter 的 hash 列表如何更新到客户端呢?
被动方式:根据缓存返回状态,客户端更新列表。
主动方式:定期去拉一下列表
作者回复: 你好,如果有更新,如何加强一致性?