目录
缓存穿透:无效请求绕过缓存访问数据库。
缓存击穿:某个热点数据缓存失效,导致并发请求直接访问数据库。
缓存雪崩:大量缓存同时失效,导致请求集中访问数据库,数据库压力骤增
缓存穿透
定义:缓存穿透指的是查询一个根本不存在的数据,这种查询会绕过缓存直接访问数据库,导致大量无效的请求直接打到数据库,降低系统性能。
原因:
-
请求的数据不存在于缓存或数据库中。
-
系统没有做有效的参数校验,导致无效请求未能被拦截。
解决方案:
-
参数校验:对所有输入参数进行有效性检查,避免无效请求。
-
布隆过滤器:可以使用布隆过滤器在缓存之前检查数据是否存在,避免无效请求访问数据库。
Python实现布隆过滤器
import hashlib
import math
class BloomFilter:
def __init__(self, capacity, error_rate):
"""
初始化布隆过滤器
:param capacity: 预计集合的最大容量
:param error_rate: 允许的误判率 (比如 0.01 代表 1% 的误判率)
"""
# 计算位数组的大小
self.size = self._get_optimal_size(capacity, error_rate)
# 计算哈希函数的个数
self.hash_count = self._get_optimal_hash_count(self.size, capacity)
# 初始化位数组,所有位为 0
self.bit_array = [0] * self.size
def _get_optimal_size(self, capacity, error_rate):
"""
计算布隆过滤器的位数组大小
:param capacity: 预计最大元素数量
:param error_rate: 允许的误判率
:return: 位数组的大小
"""
# 计算位数组的大小
return int(-(capacity * math.log(error_rate)) / (math.log(2) ** 2))
def _get_optimal_hash_count(self, size, capacity):
"""
计算哈希函数的个数
:param size: 位数组的大小
:param capacity: 预计最大元素数量
:return: 哈希函数个数
"""
return int((size / capacity) * math.log(2))
def _hash(self, item, i):
"""
根据元素和索引生成哈希值
:param item: 待哈希的元素
:param i: 哈希函数的索引
:return: 哈希值
"""
hash_obj = hashlib.md5((str(i) + item).encode('utf-8'))
return int(hash_obj.hexdigest(), 16) % self.size
def add(self, item):
"""
向布隆过滤器中添加一个元素
:param item: 待添加的元素
"""
for i in range(self.hash_count):
index = self._hash(item, i)
self.bit_array[index] = 1
def contains(self, item):
"""
判断布隆过滤器中是否包含某个元素
:param item: 待查询的元素
:return: 如果包含返回 True, 否则返回 False
"""
for i in range(self.hash_count):
index = self._hash(item, i)
if self.bit_array[index] == 0:
return False
return True
# 使用示例
if __name__ == '__main__':
# 创建一个布隆过滤器,预计最多插入 10000 个元素,误判率为 1%
bloom = BloomFilter(capacity=10000, error_rate=0.01)
# 添加元素
bloom.add("apple")
bloom.add("banana")
bloom.add("cherry")
# 查询元素
print(bloom.contains("apple")) # 输出: True
print(bloom.contains("banana")) # 输出: True
print(bloom.contains("grape")) # 输出: False (可能为 False,若发生误判)
缓存击穿
定义:缓存击穿是指缓存中某个热点数据失效(过期或被清除),而有大量并发请求同时访问该数据,导致缓存失效后,所有请求都直接访问数据库,给数据库带来巨大的压力。
原因:
-
缓存数据失效,且没有及时更新。
-
多个请求同时并发,导致数据库压力大,影响系统性能。
解决方案:
-
锁机制:可以使用互斥锁、分布式锁来保证同一时刻只有一个请求能查询数据库并更新缓存,避免多个请求并发访问数据库。
-
提前预热缓存:设置热点数据永不过期,通过后台异步任务定时刷新数据。
缓存雪崩
定义:缓存雪崩是指缓存中大量数据同时失效,导致大量请求直接访问数据库,短时间内数据库负载急剧增加,可能导致数据库宕机或者性能大幅下降。
原因:
-
缓存中的大量数据过期时间相近,导致在同一时刻大量请求同时访问数据库。
-
由于缓存失效而导致短时间内大量请求集中访问数据库,造成系统崩溃。
解决方案:
-
设置不同的缓存过期时间:通过设置不同的过期时间,避免大量数据同时过期。
-
使用多级缓存:在不同层次(如本地缓存、分布式缓存)之间进行缓存的数据分布,降低单点缓存失效的影响。
布隆过滤器
布隆过滤器(Bloom Filter)是一种空间效率高、时间效率高的概率数据结构,用于测试一个元素是否属于一个集合。它可以在常数时间内进行查询和插入,但有一定的误判率(即可能会误报元素在集合中,但绝不会漏报)。
基本步骤:
-
初始化:设定位数组的大小和哈希函数的个数。
-
插入元素:通过哈希函数将元素映射到位数组的多个位置并设置为 1。
-
查询元素:通过哈希函数检查多个位置是否都是 1,如果有一个位置为 0,则说明元素不在集合中。