Redis常见问题

穿透(Cache Penetration):

穿透指的是恶意请求或查询缓存中不存在的数据,导致请求直接落在后端存储上,消耗了后端资源。这种情况下,缓存无法起到预期的作用,也没有命中率。常见的攻击方式是使用不存在的键进行请求。

解决穿透问题的常见方法是使用布隆过滤器(Bloom Filter)或简单的缓存校验来过滤掉不存在的键。布隆过滤器是一种高效的数据结构,用于判断一个元素是否属于一个集合中,可以快速过滤掉不存在的键,减轻后端存储的压力。

击穿(Cache Miss):

击穿指的是在高并发情况下,当一个请求查询 Redis 中不存在的数据时,导致请求直接落在后端存储上,增加了后端的负载并降低了性能。这是因为查询不存在的数据时,Redis 无法缓存该数据,每次请求都需要访问后端存储。

解决击穿问题的常见方法是使用互斥锁(Mutex Lock)或分布式锁,在第一个查询发现数据不存在时,将锁加上,其他请求在锁未释放之前直接返回,避免了对后端存储的直接访问。同时,可以使用热点数据预加载或设置合理的缓存过期时间,减少对后端存储的访问。

雪崩(Cache Avalanche):

雪崩指的是在缓存过期时间到达时,大量的请求同时查询该数据,导致所有请求都落在后端存储上,造成后端存储压力骤增,甚至导致后端服务不可用。这是因为缓存过期后,所有请求都会直接访问后端存储获取数据。

解决雪崩问题的常见方法是使用分布式缓存的多级缓存架构,如设置热点数据永不过期、使用不同的缓存过期时间、采用异步缓存更新策略等。此外,还可以使用限流、降级和熔断等技术手段,保护后端存储不被大量请求压垮。

缓存穿透解决方案

缓存穿透是查询不存在的数据时会访问数据库

有两种方法:

布隆过滤器:将数据库中的数据哈希映射到bitmap(0、1表示存在、不存在),查询时先访问bitmap,查询不存在的数据就会被bitmap拦截,就不用进入数据库查询
redis1
返回空值给缓存:当查询不存在数据访问数据库返回值为空,仍然将空值进行缓存(Redis中value为空值会被回收,可以设置empty字符串等),当然插入值时要替代掉空值
redis2

缓存击穿解决方案

缓存击穿是数据缓存没有而数据库有,查询时需要进入数据库查询,高并发时会压垮数据库

有两种解决方案:

设置热点key永不过期

加互斥锁(mutex key)

互斥锁:在缓存失效的时候(判断拿出来的值为空),第1个进入的线程,获取锁并从数据库去取数据,没释放锁之前,其他并行进入的线程会等待,再重新去缓存取数据

Redis:使用setnx操作去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。

setnx key value:当key不存在时才设置值,key存在不操作。setnx可以实现互斥锁
redis3
通过互斥锁,高并发也仅查询一次数据库

缓存雪崩解决方案

缓存雪崩是缓存服务器重启或者大量缓存失效,引起数据库压力过大

这里的问题是多个key缓存,有两种方案:

尽量设置缓存失效时间均匀分布,别在短时间内大量缓存过期

考虑用加锁队列的方式来保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量的并发请求数据库(在高并发下线程阻塞,用户体验差)