diff --git a/notes/pics/bloom-filter.png b/notes/pics/bloom-filter.png new file mode 100644 index 00000000..6937dad6 Binary files /dev/null and b/notes/pics/bloom-filter.png differ diff --git a/notes/pics/lru.png b/notes/pics/lru.png new file mode 100644 index 00000000..38da77b8 Binary files /dev/null and b/notes/pics/lru.png differ diff --git a/notes/缓存.md b/notes/缓存.md index 1a6cffa1..08831347 100644 --- a/notes/缓存.md +++ b/notes/缓存.md @@ -97,6 +97,10 @@ CDN 主要有以下优点: - 对这些不存在的数据缓存一个空数据,并设置较短的过期时间; - 使用布隆过滤器保存所有存在的 Key,对不存在的 Key 的请求直接拒绝。 +布隆过滤器用多个哈希函数把 Key 映射到位数组的多个位置并置为 1。查询时只要有一个位置为 0,Key 就一定不存在;全部为 1 时 Key 可能存在,存在一定的误判率。 + +

+ ### 缓存击穿 指的是某个热点数据的缓存过期时,大量对它的请求同时到达数据库。 @@ -200,6 +204,8 @@ Redis Cluster 使用的不是一致性哈希,而是把 Key 映射到固定的 - 访问某个节点时,将其从原来的位置删除,并重新插入到链表头部。这样就能保证链表尾部存储的就是最近最久未使用的节点,当节点数量大于缓存最大空间时就淘汰链表尾部的节点。 - 为了使删除操作时间复杂度为 O(1),就不能采用遍历的方式找到某个节点。HashMap 存储着 Key 到节点的映射,通过 Key 就能以 O(1) 的时间得到节点,然后再以 O(1) 的时间将其从双向队列中删除。 +

+ Java 的 LinkedHashMap 内部就是这种结构,把 accessOrder 设为 true 并重写 removeEldestEntry 方法,就可以直接得到一个 LRU 缓存。 ```java diff --git a/tools/diagram/src/bloom-filter.svg b/tools/diagram/src/bloom-filter.svg new file mode 100644 index 00000000..8d3a077d --- /dev/null +++ b/tools/diagram/src/bloom-filter.svg @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + 布隆过滤器 + + 0 + 0 + + 1 + 1 + + 0 + 2 + + 0 + 3 + + 1 + 4 + + 0 + 5 + + 1 + 6 + + 0 + 7 + + 0 + 8 + + 0 + 9 + + 1 + 10 + + 0 + 11 + + 0 + 12 + + 1 + 13 + + 0 + 14 + + 0 + 15 + + + key1 + + + key2 + + + + + + + 插入 + + + key3 + + + key4 + + + + + + + 查询 + 位 3 为 0 + 一定不存在 + 全为 1:可能存在 + 实际未插入过,属于误判 + diff --git a/tools/diagram/src/lru.svg b/tools/diagram/src/lru.svg new file mode 100644 index 00000000..cd1643d6 --- /dev/null +++ b/tools/diagram/src/lru.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + LRU:HashMap + 双向链表 + + + head + + + k2 + + + k3 + + + k1 + + + tail + + + + + + + + + + HashMap + + k2 + + + k3 + + + k1 + + 哨兵 + 哨兵 + 最近访问 + 最久未访问,最先淘汰 + 访问或插入时把节点移到 head 之后,超出容量时删除 tail 之前的节点 +