推荐答案
1. 使用互斥锁(Mutex Lock)
在缓存失效时,使用互斥锁确保只有一个线程去数据库加载数据,其他线程等待锁释放后直接从缓存中获取数据。
// www.javascriptcn.com code example
import redis
import threading
cache = redis.Redis(host='localhost', port=6379, db=0)
lock = threading.Lock()
def get_data(key):
data = cache.get(key)
if data is None:
with lock:
# 再次检查缓存,防止其他线程已经更新了缓存
data = cache.get(key)
if data is None:
# 从数据库加载数据
data = load_data_from_db(key)
cache.set(key, data, ex=60) # 设置缓存过期时间
return data2. 使用永不过期的缓存
对于热点数据,可以设置缓存永不过期,通过后台定时任务定期更新缓存。
// www.javascriptcn.com code example
def get_data(key):
data = cache.get(key)
if data is None:
data = load_data_from_db(key)
cache.set(key, data) # 不设置过期时间
return data
# 后台任务定期更新缓存
def update_cache_periodically():
while True:
data = load_data_from_db('hot_key')
cache.set('hot_key', data)
time.sleep(60) # 每分钟更新一次3. 使用布隆过滤器(Bloom Filter)
在查询缓存之前,先通过布隆过滤器判断数据是否存在,避免对不存在的数据进行查询。
// www.javascriptcn.com code example
from pybloom_live import BloomFilter
bf = BloomFilter(capacity=100000, error_rate=0.001)
def get_data(key):
if key not in bf:
return None
data = cache.get(key)
if data is None:
data = load_data_from_db(key)
cache.set(key, data, ex=60)
return data本题详细解读
1. 缓存击穿的定义
缓存击穿是指一个热点数据在缓存中过期后,大量并发请求同时访问数据库,导致数据库压力骤增的现象。
2. 缓存击穿的危害
- 数据库压力:大量请求直接打到数据库,可能导致数据库崩溃。
- 系统性能下降:数据库响应变慢,影响整体系统性能。
3. 解决方案的优缺点
互斥锁:
- 优点:简单易实现,能有效防止缓存击穿。
- 缺点:锁的粒度较大,可能影响系统吞吐量。
永不过期的缓存:
- 优点:避免缓存失效,减少数据库压力。
- 缺点:需要额外的后台任务维护缓存,增加了系统复杂性。
布隆过滤器:
- 优点:减少对不存在数据的查询,降低数据库压力。
- 缺点:存在一定的误判率,且需要额外的存储空间。
4. 实际应用场景
- 互斥锁:适用于热点数据较少且并发量适中的场景。
- 永不过期的缓存:适用于热点数据较多且数据更新频率较低的场景。
- 布隆过滤器:适用于数据量大且查询频繁的场景。