缓存设计必须基于具体业务场景来思考,例如根据业务系统的具体吞吐量、数据量来设计。本文脱离业务场景讨论缓存设计,仅作学习参考。

一、临时缓存
最简单的缓存,直接给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的数据。
减缓对主缓存服务的压力。