缓存击穿 缓存穿透 缓存雪崩
缓存击穿
热键
在一般的分布式缓存体系中,会存在一个中央缓存的节点。在高并发的场景下,中央缓存节点会面临热点键的冲击,需要使用本地缓存来分担热点键的压力。那么本地缓存如何识别热点键便成为了分布式缓存设计的核心命题。
topk
根据二八定律,一般20%热点键的会占据请求80%的请求。如何从全量的键中识别这20%的热点键。热点键的特征就是单位时间的请求量(请求速率)远远高于普通键。所以对键进行计数,使用 topk 对这些键的计数进行排序,便可以很好的识别热键,然后将热键保存在本地缓存.
heavykeeper 正是一个概率性的topk的数据结构。
heavykeeper
使用场景
- Log Analysis: Find the most frequent IP addresses, user agents, or error messages
- Text Processing: Identify the most common words in large documents
- Network Monitoring: Track heavy hitters in network traffic
- Clickstream Analysis: Find the most popular pages or user actions
- Time Series Data: Monitor frequently occurring events or anomalies
原理 TODO
python中,我们使用 rust + pyo3 库实现的 heavykeeper 来实现分布式缓存的热点键值识别.
注意要点:
- 此库最低要求 python 3.11
- 对于缓存穿透(访问不存在的键)的热键,设置负缓存(在本地缓存不存在的结构)
缓存穿透
缓存穿透就是请求构造了大量不存在的键. 可以全量缓存或者使用bloomfilter来检测请求键是否存在.
全量缓存
bloomfilter
bloom 过滤器是一种概率数据结构,使用多个散列函数将输入键(字符串)得到多个散列值,并将多个散列值的bit位置置为1,这样查询时可以通过同样的散列逻辑得到的多个 bit 位置的数值来判断当前元素是否在bloom过滤器中.
据此原理,只要多个bit位置都是0,说明键不在过滤器中,这样可以高效的判定不存在的元素。
使用 xxhash 和 rbloom 来做可序列化保存的 bloomfilter. 这样可以去异步全量键放置到bloom过滤器中,用来判断黑客故意构造的系统中不存在的键,进而解决缓存穿透问题,提高系统的健壮性。
pip install xxhash==3.6.0
pip install rbloom==1.5.4
from pickle import dumps
from rbloom import Bloom
from xxhash import xxh3_128
def hash_func(obj):
# 要保存bloomfilter的比特位,需要额外的hash function.
h = xxh3_128(dumps(obj)).digest()
# use sys.byteorder instead of "big" for a small speedup when
# reproducibility across machines isn't a concern
return int.from_bytes(h[:16], "big", signed=True)
bf = Bloom(10_000, 0.01, hash_func)
bf.size_in_bits/8+8
(bf.size_in_bits/8+8)/2**10
bf.add("hello")
bf.add("world")
"hello" in bf # True
bf.save("bf.bloom")
loaded_bf = Bloom.load("bf.bloom", hash_func)
assert loaded_bf == bf
"hello" in loaded_bf # True
缓存雪崩
缓存雪崩是指大量的键同时过期,进而导致大量请求到了后端,压垮了后端数据库等服务。 这个主要是给键设置不同的过期时间。