缓存与会话
把你数据库最讨厌的那部分负载接走
会话、限流、功能开关,还有每个请求都要读的那一行热点行。在大多数应用里,它们都住在 Postgres 里,也正是被敲得最狠的那些行——不是因为数据库做不好,而是因为它们从来就不是提问。key 你早就知道了。
为什么合适
这些东西的形状是同一个:一个你手里已经有的 key、一个很小的 value、一段寿命。kevy 用 O(1) 查到它,不靠定时任务就让它自己过期,并且在一台机器上每秒做几百万次。
被低估的那一部分是过期。建在数据库上的缓存需要一个清理任务,而 bug 就住在清理任务里。在这里,时间一到引擎就把 key 丢掉,不管有没有人来问它。
怎么做
# a session that cleans itself up
SET session:7f3a '{"user":"ada","role":"admin"}' EX 3600
GET session:7f3a
TTL session:7f3a -> 3599
# a rate limit: one counter per client, expiring on a window
INCR rate:203.0.113.7 -> 1
EXPIRE rate:203.0.113.7 60
INCR rate:203.0.113.7 -> 2 (the window survives)
# feature flags: read constantly, written rarely, joined never
HSET flags new-checkout on dark-mode on beta-search off
HGET flags new-checkout -> "on"
HGETALL flags
# a cached row, invalidated by the writer rather than by a timer
SET user:881 "$json" EX 300
DEL user:881 # after you write to Postgres
代价是什么
缓存是事实的第二份拷贝,它可能是错的。kevy 解决不了这件事——没有任何东西能解决。要在写的时候让它失效,而不是靠一个定时器,TTL 是兜底,不是方案本身。另外注意,多 key 的 MSET 或 DEL 只在单个 shard 内是原子的:如果两个 key 必须一起变,用 {hashtag} 把它们放到同一个 shard 上。