高并发系统内的缓存设计理解
缓存设计必须基于具体业务场景来思考,例如根据业务系统的具体吞吐量、数据量来设计。本文脱离业务场景讨论缓存设计,仅作学习参考。
一、临时缓存
最简单的缓存,直接给key设置一个很短的TTL,1分钟或者几分钟,过期直接查DB,不考虑缓存穿透问题。
适合单表数据量少,读取很多的数据。
二、长期缓存
适合热点数据,给key设置一个较长的TTL。 数据更新时,通过异步的方式去写入缓存。
异步的方式很多:
1) 业务系统直接更新
2) 利用消息中间件,例如kafka
3) 利用mysql binlog,结合canal等工具,自行编写规则和脚本触发缓存更新。
除了热点数据,一些复合查询结果也适合使用该方式。 例如复合查询的统计结果,不能直接查db,直接把结果进行缓存。
三、热点数据+临时缓存mix
成本低+最快速的热点数据缓存方式,适合短期内需要大量缓存的业务。
通过统计的方式, 计算出热点数据key,放到一个set里。
对于热点数据,使用另外的方式进行定期更新缓存,例如开一个定时任务。
如果bisKey查不到数据,且在热点数据中,则认为数据删除了,返回空
如果不是热点数据,则实时查db。
bisKey := "key_1"
query,exists := Redis.Get(bisKey)
if exists {
return query
}
hotSetKey := "hot"
inSet := Redis.Ismember(hotSetKey, bisKey)
if inSet {
return ""
}
// TODO 不是热点数据,查db,然后写一个短TTL的缓存
PS: 对于热点数据key,也可以用bloom filter,更加简单,但是需要高版本redis
四、超高热点数据
对于数据量少,热点非常高的数据,可以考虑在各个服务器本地建一个小redis。 用另外的脚本去维护这些小redis的数据。
减缓对主缓存服务的压力。
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。