我们的缓存协议提供了 GetOrSet 和 Delete 两个命令,是的, 我们把 Get 和 Set 合并了。
缓存一致性的实现是靠在数据库中的 Key 更新完成的瞬间,以下事件确保发生:
没有任何连接正在读取 Key
所有在此之前读到 Key 且未完成 Set 的连接都已被关闭
Umem-cache 中不存在该 Key
下面我将详细说明:
缓存命中
缓存命中时,Umem-cache 直接返回数据。
但是如果 key 因为正在 set 而被锁住了,该 get 操作会给该锁设置上过期时间,并排队等待 value 。另外,如果锁到期了,持有锁的连接会被关闭,并把锁转交给排队中的下一个连接。
::
客户端 Umem-cache 数据库 get key|------------------------->| | 1. 等待锁释放 返回 value ||<-------------------------|缓存未命中
当缓存未命中时,我们会锁住 key ,然后尝试 set ,其他 get 请求会排队等待,这种机制是为了防止缓存击穿。
你可能发现了,Umem-cache 不响应 Set ,这让我们省掉了一次网络传输。因为它大概率会成功,就算失败也不是什么大事。
::
客户端 Umem-cache 数据库 get key|------------------------->| | 1. 锁住 key 返回 miss ||<-------------------------| get key|--------------------------------------------------->| | 2. 等待读锁 返回 value ||<---------------------------------------------------||------------------------->| 3. set value 4. 释放 key 的锁更新或删除