Redis常见问题
00 分钟
2022-9-16

持久化机制:AOF和RDB快照

AOF机制对每条写入命令作为日志,以append-only的模式写入一个日志文件中,在redis重启的时候,可以通过回放AOF日志中的写入指令来重新构建整个数据集;redis-》os cache -》磁盘日志文件;当AOF越来越大的时候,会基于当前redis生成新的AOF文件,删除旧AOF文件
RDB则是每隔多长时间对当前数据进行快照,适合做冷备
AOF和RDB同时开启时,则会使用AOF来重新构建数据,因为AOF中的数据更加完整

redis数据结构:

string、sorted list、hash、set、sorted zset
热key
大Value
缓存穿透、失效和LRU被清理
设置为空值,直接返回null,防止缓存穿透
缓存重建、雪崩
 

写少读多,双写不一致

异步最终一致性写缓存;数据库+缓存,同步双写;
 
如图所示:此时db和缓存是不一致的
notion image

解决方案:读写串行化。分布式锁

加两把锁
查询数据的时候需要添加double check
读和写是一把锁,只能有一个进行操作。情况一:当写先拿到锁的时候,读在等待,写更新完,读进去更新数据之前进行检查redis的数据是否为空,不为空则返回。情况二:读先拿到锁的时候,写等待,读从MySQL写入到redis,写更新数据到DB然后写入redis更新数据
notion image

缓存+数据库双写分布式锁高并发优化

场景:

因为央视有播出他的感人事迹,大家都去微博查看他的个人信息给他关注,但是他的用户数据早就过期了,一瞬间,涌入大量的人来查询他,高并发的读-》已过期缓存-》大量的线程都没读到redis key -》大量的线程都涌入了load db→ write redis,会出现非常严重的锁竞争的问题,短时间有严重的串行化发生

解决方案:

只要有一个人把数据写入到redis,则其他人(锁)直接去读redis。redis延期过期expire time
使用tryLock,指定时间内如果拿不到锁就去读redis,串行转并发,redis读不到就抛异常

缓存惊群与穿透问题的解决方案

惊群:技术里典型的术语,突然在某个时间点,出现了一个故障,一大片范围线程/进程/机器都同时被惊动了,惊群效应
设置一个固定时间+随机时间,比如2天4小时。所有的缓存不在同一时间,分开缓存到期时间, 不要几种在一个时间点同时过期
缓存生成时间添加随机数:TWO_DAYS_SECONDS + RandomUtil.genRandomInt(0,10) * 60 * 60;
缓存穿透:数据库中没有这条数据,很多读请求直接从redis打到DB
解决方案:添加分布式锁,第一条去DB查询的时候先在redis上把value设置为EmptyData,然后从数据库中查询更新至redis

惰性分页缓存构建方案如何节约内存

每页数据就是一个key value,对每一页精准过期时间,使用list数据结构进行存储
用户更新数据,所有缓存失效,使用mq进行异步更新分页数据;这个时候会出现用户读redis和db数据不一致。在新增更新数据和mq中使用阻塞式分布式加锁,使用try{}finally{}进行释放
notion image

写多读多双写,购物车、库存场景

数据存储转为redis主存储,异步落库到MySQL
使用hash结构存储商品数量

异步落库的消息丢失与不一致

redis-》mq-》MySQL
数据刚写入redis,还没写入mq,redis崩了,导致数据没有同步过去。
 
库存
缓存分片和渐进式同步方案
缓存分片场景:
库存数据写到了缓存以后,商品-》缓存里的库存数据,如果是大促活动、秒杀,瞬时高并发的操作一个商品的库存,必然会导致对缓存能集群里某个redis节点,造成过大的压力,瞬时流量倾斜。瞬时单节点压力很大
方案:
商品库存一共100,拆分为10个库存分片,每个分片10个库存,redis里,每个节点有2个库存分片,库存瞬时超高并发的操作,库存扣减的请求达到多个redis节点上去
 

缓存雪崩、热key、大Value

热key

场景:比如明星官宣结婚大量请求走一个key一个机器
方案:热key探测系统(京东hotkey),请求的时候过滤一遍,当检测到一个key请求次数异常的时候,则判断为热key,然后将热key写入到分布式的service中,至此在有请求直接走service

大Value

场景:value值很大,几mb或者几十mb
方案:对redis里的大value进行监控,发现超过大于1mb的大value的值,报警,把这个值转为一个字符串,拆分字符串,比如拆分为10个串,每个穿100kb
redis监控内存不足,强制回收方案

缓存雪崩

场景:缓存雪崩是指在我们设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重雪崩。
方案:我们可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。redis集群自动探测,当发现redis挂了以后MySQL进行限流
 
 

评论