什么是快取 (Cache)?快取 (Cache) 的机制为何?
2023年2月5日
什么是快取 (Cache)?
目的为了弥补 Database 在复杂业务下的不足,基本原理是将可重使用的资料存放到记忆体中,这样可以避免每一次都去 Database 读取,进而将地效能。而以 Memcache 为例,查询可达到 TPS 50,000 以上。虽然说增加 Cache 可以减轻 Database 的压力,但会让系统变得复杂,因此若 Cache 没有设计好,则有可能造成系统崩溃。
快取 (Cache) 的应用场景
- 需要经过复杂计算才能得到值:每一次从 MySQL 去 Count(*) 大量数据,则不管怎么优化 MySQL 都无法解决这个问题。
- 读多写少的资料:在 Social media 上,写的人少(insert)但读的人多(select),即使 Database 有下 index,但每一个人都去 select 也会大幅降低效能。
快取 (Cache) 设计模式
Cache Aside
Read:优先从 Cache 读,Cache miss 则从 Database 读资料,并写入 Cache,适合读多的情境。
Write:把资料直接写入 Database,成功后将 Cache 对应的 key 值设为失效。 (不直接写入 Cache 是为了避免并发问题。)
注意:还是会有并发问题,一个要读、另一个要写时,Cache 很有可能因此存在脏资料。
Read/Write Through
Cache 作为 Application 与 Database 之间的桥梁,适合写少读多的情境,机制如下:
Read through: 若 Cache hit 在 Cache 里则直接回传,否则从 Database 读取并同时更新 Cache。
Write Through: 直接将资料写入 Cache 以及 Database。
Write behind Cache
写操作会直接写入 Cache,而可依据不同策略决定写回 Database 的时机,相比于 Write Through 的同步机制,这里采取非同步的机制,适合写入多的情境。但要注意若机器当机或 Thread 挂掉,则很有可能丢失资料。
快取 (Cache) 可能的问题
Cache penetration
Cache 并无作用,因此系统依旧还是要去找 Database ,具体可分为以下两种情境
Database 本来就没有这笔资料:照理来说这样发生的请求量应该不大,但如果被恶意攻击,有可能拖慢整个系统,解法可以是:
当搜寻的 Key 重复率较高时:把相对应个 Key 值给一个 default,这样下次再被存取时就回传空值。
当搜寻的 Key 重复率较低时:利用 Bloom filter(类似 hbase 判断 key 否存在),若存在则去 Cache 或 Database 拿,反之则 return null。
缓存资料需耗费大量资源与时间:没办法把所有商品全部存到 Cache 里,因此会需要分页存,因此有可能在访问时 Cache 会失效,进而 Cache 无法起到作用。
Cache avalanche
若 Key 全部都设同一个 Expire time,则当时间到会同时全部失效,此时会全部像 Database 索取资料,Database 会瞬间压力过大,解决方法是利用一定区间的随机值当来当作 Expire time。
Cache breakdown
Cache 失效后引起系统效能急遽下降的情况。例如当 key 值过期后,需要重新和 Database 拿资料,但是在拿资料的过程需要时间,若此时同时有大量访问需求进来,全部都去 Database 拿资料就会造成问题,因此解法有两种:
更新锁:保证只有一个线程可以去更新缓存,其他线程则等待,不过当采分布式集群系统时,多个机器间也会产生缓存雪崩的问题,因此需要用到分布式锁:Zookeeper
后台更新:由后台线程来更新缓存而非业务线程,具体会将 key 的期限设为永久,并且由后台线程定期清扫。但是当 cache 满了时就会遇到问题,可能解法为:业务 thread 发现 cache 失效后,通过 message queue 发送一条消息通知后台 thread 更新 cache;或者后台 thread 依据对业务的了解,对于 Key 做定期清洗。
Hotspot cache
虽然 Cache 系统本身的性能比较高,但对于一些特别热点的数据,如果大部分甚至所有的业务请求都命中同一份 Cache 数据,则这份数据所在的 Cache server 的压力也很大,解决方法是,复制多份 Cache 副本到多个 Cache server ,减轻 Hotspot cache 导致的单台 Cache server 压力。
注意:不同的 Cache 副本不要设置统一的过期时间,不然同时失效后可能引发 Cache avalanche。