对于那些少更改、小数据的表,以及对一致性要求不高的业务,其实完全可以通过本地缓存将表数据缓存到本地内存中,然后通过定时机制拉取表更新数据
直接从内存中获取数据,将会使得查询性能得到巨大的提升,并且由于更改少,数据量小,同时内存压力也不会很大,除了一致性不高外,完全是利大于弊的策略
那么如果我想设计这样的本地缓存,该如何进行呢?
基本功能满足
既然是同步数据库表,在项目启动时其实就可以拉取数据。用户仅需要提供拉取表,然后缓存组件就可以自动拉取数据
同时还衍生后台线程定期更新数据
内存节约
考虑实际中需要的数据仅是少部分字段,那么也可用户指定需要的字段,仅查询需要的
那么是否需要压缩呢?
从速度角度来说,我以为是不需要的,既然是为了快,压缩就有些背离其初衷了
如果对于业务X需要a、b、c字段,对于业务Y需要a、b、d字段,其中X、Y需要的条件相同,那么是分别拉取X、Y需要的数据吗?
不在乎内存情况下是可以的。最好是取并集,更简单的方式是如果同条件表数据超过1,就查询所有数据
假如利用mysql的主从同步机制,在本地建立从库,这是好主意吗?
该方法虽然能利用mysql的主从同步机制,但是会带来更大的复杂性,尤其是服务部署在容器时
对于数据更新频率极少的情况下,是否还有其他方法呢?
如果数据更新频率非常少,那么甚至可以用配置文件、硬编码的方式直接将数据记录到项目里,尤其配置文件支持热部署时。
问题在于数据较多较复杂,那么配置文件会更为麻烦
定期更新
按照用户指定的更新间隔去更新,那么一旦需要同步表较多情况下,岂不是更新的过于频繁呢?
在设定频率不是特别高,且数据量小的情况下,这并不会有多大的影响。
当然也可以通过增量更新方式尽可能减少影响。
标记变化的数据,然后仅拉取
或者使用数据库的事件通知机制,如 MySQL 的 binlog 或其他类似的触发机制。一旦表发生更改,直接推送更新
是否可提供主动触发接口呢?
主动触发在低频更新数据的情况下是很棒的想法,既大大减少了定期更新带来的消耗,还能够根据触发接口进行精确的增量更新
比如对于教材版本来说,更新频率极低极低,甚至完全可以舍弃掉定期更新机制,而是通过主动触发更新接口进行本地缓存的更新
假如在最初时数据表较为简单,更新频率小,可如果慢慢数据库越来越大,更新频率甚至越来越高该如何办呢?
- 设定阈值监控:比如超过阈值后,进行告警
- 回退到db查询:若不在本地缓存中,那么就再查询数据库
- 采用bloom filter、缓存id等过滤掉根本不存在的数据
- 引入淘汰机制:将不常使用的数据进行淘汰,或者根本不会再用的数据淘汰掉
- 分级缓存:本地缓存常用数据,远程缓存一般数据,数据库储存所有数据
并发
如果存在多个线程同时请求本地缓存数据,那么是否需要加锁?
在低一致性情况下,加锁并非必要的。因为唯一的写仅仅只是将引用指向新数据,那么这样即使出现并发冲突,也仅仅只是访问到旧数据