Caching & Async
Cache 模式详解
Cache-aside、Write-through、Write-back 模式
由于 cache 能存的数据有限,你需要选择最适合用例的 cache update strategy。
Cache 模式(Cache-aside / Lazy loading)
应用从 storage 读写。cache 不直接和 storage 交互,应用执行以下步骤:
- 在 cache 中查找记录,如果 miss
- 从 database 加载所需数据
- 将结果写入 cache
- 返回所需内容
def get_user(self, user_id):
user = cache.get("user.{0}", user_id)
if user is None:
user = db.query("SELECT * FROM users WHERE user_id = {0}", user_id)
if user is not None:
key = "user.{0}".format(user_id)
cache.set(key, json.dumps(user))
return user
Memcached 常用这种方式。
优点是读取速度快,且只 cache 被请求的数据,避免冷数据占满 cache。
Cache-aside 的缺点
- cache miss 时需要多一步 database 查询,latency 会明显增加。
- database 更新后 cache 可能过期,需要用 TTL 或 write-through 来缓解。
- 节点故障会触发 cache cold start,短期内 latency 增大。
直写模式(Write-through)
资料来源:scalability、availability、稳定性、patterns
应用把 cache 当作 primary store,写入 cache 时同步写入 database:
- 应用写入或更新 cache
- cache 同步写入 data store
- 返回结果
应用代码:
set_user(12345, {"foo":"bar"})
cache 代码:
def set_user(user_id, values):
user = db.query("UPDATE Users WHERE id = {0}", user_id, values)
cache.set(user_id, user)
Write-through 写入较慢,但刚写入的数据读取很快,且 cache 数据不会 stale。
Write-through 的缺点
- 新节点不会有历史 cache,直到 database 被更新为止(可结合 cache-aside 缓解)。
- 大量写入数据可能从未被读到,使用 TTL 可以减轻浪费。
Read-through vs Write-through 快览
Read-through:读时 miss 才回源并写入 cache,适合 read-heavy。
Write-through:写时同步落库 + cache,保证数据一致但写入更慢。


回写模式(Write-back / Write-behind)
资料来源:scalability、availability、稳定性、patterns
Write-back 中,应用:
- 更新 cache 中的条目
- 异步写入 database,提高 write performance
Write-back 的缺点
- cache 在落库前宕机会丢数据。
- 实现复杂度高于 cache-aside 或 write-through。
刷新(Refresh-ahead)
你可以配置 cache 在到期前自动刷新最近访问的数据。
如果 cache 能准确预测未来会被请求的数据,refresh-ahead 可以降低 latency。
Refresh-ahead 的缺点
- 预测不准会导致额外 work,performance 可能不如不刷新。
Cache 的通用问题
- 需要保持 cache 和 data source 的 consistency,例如配合 cache invalidation 机制。
- 需要改造应用,引入 Redis 或 Memcached。
- cache invalidation 是经典难题:什么时候更新 cache,什么时候失效?