diff --git a/notes/缓存.md b/notes/缓存.md index 66fc4214..76234faa 100644 --- a/notes/缓存.md +++ b/notes/缓存.md @@ -206,7 +206,7 @@ Redis 8 起内置了布隆过滤器(BF.RESERVE、BF.ADD、BF.EXISTS),Redis - 为缓存设置过期时间作为兜底,需要注意过期时间从这次写回缓存时算起,慢读请求很晚才写回旧值时,旧值最长还会保留一个完整的过期时间; - 延迟双删:更新数据库并删除缓存之后,隔一段时间再删除一次,清掉慢读请求写回的旧值; - 删除失败时重试:把要删除的键发到消息队列,由消费者删除,失败就重新投递; -- 订阅 binlog 删除缓存:Canal 这类组件伪装成 MySQL 的从库读取 binlog,发现某一行被修改就删除对应的缓存键,失败时重试,业务代码中不再需要删除缓存,手工执行的 SQL 也能覆盖,代价是多部署一套组件; +- 订阅 binlog 删除缓存:Canal 这类组件伪装成 MySQL 的从库读取 binlog,发现某一行被修改就删除对应的缓存键,失败时重试,业务代码中不再需要删除缓存,手工执行的 SQL 也能覆盖,代价是多部署一套组件,而且和直接删除一样挡不住在删除之后才写回的旧值; - 写回缓存时检查期间是否有过删除:Facebook 的 Memcache 在缓存未命中时发给读请求一个租约(lease)令牌,写回时要带上令牌,如果这期间键被删除,令牌就会失效,旧值写不进缓存。 延迟双删的第二次删除不能让写请求同步等待,通常交给线程池或者延迟消息执行。间隔要大于读请求从查询数据库到写回缓存的耗时:附录 A4 中读请求最多停顿 5 毫秒,间隔取 50 毫秒时没有留下旧值;间隔太短清不掉旧值,太长则旧值在缓存中停留更久。第二次删除也可能失败,同样要重试,最后靠过期时间兜底。 @@ -321,7 +321,7 @@ public class LRUCache extends LinkedHashMap { @Override protected boolean removeEldestEntry(Map.Entry eldest) { - return size() > maxSize; // 每次 put 之后调用,返回 true 时删除最久未访问的元素 + return size() > maxSize; // 插入新键之后调用,返回 true 时删除最久未访问的元素 } } ```