Redis高频面试

数据类型

String、List、Set、Zset(有序集合)、Hash

一、缓存

1.1 缓存穿透

缓存穿透:查询一个不存在的数据,mysql查询不到数据也不会直接写入缓存,就会导致每次请求都查询数据库。
解决:
(1)缓存空数据

缺点:消耗内存,有可能发生数据不一致问题

(2)布隆过滤器

缺点:存在误判,redisson一般设置无判断在5%以下也是可以接受

布隆过滤器

1.2 缓存击穿

缓存击穿:给某一个热点的key设置了过期时间,当key过期时,恰好这个时间点对这个key有大量的并发请求过来,这个并发的请求可能会瞬间把DB压垮。
(1)互斥锁

强一致,性能差

互斥锁

(2)逻辑过期

高可用,性能好,不能保证数据绝对一致

逻辑过期

1.3 缓存雪崩

缓存雪崩:在同一时间段大量的key同时失效或者redis服务宕机,导致大量的请求到达数据库,带来巨大压力。
(1)针对同时过期,给不同的key过期时间添加随机值
(2)利用redis集群提高服务可用性(哨兵或者集群模式)
(3)给缓存业务添加降级限流策略
(4)给业务添加多级缓存

1.4 双写一致问题

双写一致性:当修改了数据库的数据也要同时更新缓存的数据,缓存和数据库的数据要保证一致。

采用延时双删:
首先我们明确一点,当数据库中值修改后,先删除缓存还是先写数据,其实真正情况下,二者都肯能会产生问题。

解决方案:一般情况下进入缓存的数据都是读多写少型,
(1)分布式锁可以解决

读数据:采用共享锁(readLock),加锁之后其他线程可用共享读操作
写数据:采用独占锁(writeLock),加锁之后阻塞其他线程读写操作
读写锁也是Redisson就可以完成。

(2)异步通知保证最终一致性

①数据库写完后,发送MQ利用MQ保证最终一致
②数据库写完后,基于Canal异步通知,Canel监控Binlog实现

二、Redis持久化

2.1 RDB

RDB是一个快照文件,它是把redis内存存储的数据写到磁盘上,当redis实例宕机恢复数据的时候,方便从RDB的快照文件中恢复数据。

2.2 AOF

AOF的含义是追加文件,当redis操作写命令的时候,都会存储这个文件中,当redis实例宕机恢复数据的时候,会从这个文件中再次执行一遍命令来恢复数据。

总结

RDB因为是二进制文件,在保存的时候体积也是比较小的,它恢复的比较快,但是它有可能会丢数据,我们通常在项目中也会使用AOF来恢复数据,虽然AOF恢复的速度慢一些,但是它丢数据的风险要小很多,在AOF文件中可以设置刷盘策略,我们当时设置的就是每秒批量写入一次命令。

三、Redis数据过期策略

3.1 惰性删除

惰性删除:访问key的时候判断是否过期,如果过期,则删除

3.2 定期删除

定期删除:定期删除一定量的key是否过期(SLOW模式+FAST模式)

总结

一般使用中,采用惰性删除+定期删除两者配合使用

四、Redis数据淘汰策略

数据的淘汰策略:当Redis中的内存不够用时,此时在向Redis中添加新的key,那么Redis就会按照某一种规则将内存中的数据删除掉,这种数据的删除规则被称之为内存的淘汰策略。
以下8中淘汰策略:

  • noeviction:不淘汰任何key,但是内存满时不允许写入新数据,默认就是这种策略。
  • volatile-ttl: 对设置了TTL的key,比较key的剩余TTL值,TTL越小越先被淘汰。
  • allkeys-random:对全体key,随机进行淘汰。
  • volatile-random:对设置了TTL的key,随机进行淘汰。
  • allkeys-lru:对全体key,基于LRU算法进行淘汰。
  • volatile-lru:对设置了TTL的key,基于LRU算法进行淘汰。
  • allkeys-lfu:对全体key,基于LFU算法进行淘汰。
  • volatile-lfu: 对设置了TTL的key,基于LFU算法进行淘汰

LRU(Least Recently Used)最近最少使用。用当前时间减去最后一次访问时间,这个值越大则淘汰优先级越高。
LFU(Least Frequently Used)最少频率使用。会统计每个key的访问频率,值越小淘汰优先级越高。

使用建议:
1、优先使用 alkeys-lru 策略。充分利用 LRU 算法的优势,把最近最常访问的数据留在缓存中。如果业务有明显的冷热数据区分,建议使用。
2、如果业务中数据访问频率差别不大,没有明显冷热数据区分,建议使用alkeys-random,随机选择淘汰
3、如果业务中有置顶的需求,可以使用 volatile-lru 策略,同时置顶数据不设置过期时间,这些数据就一直不被删除,会淘汰其他设置过期时间的数据。
4、如果业务中有短时高频访问的数据,可以使用 allkeys-lfu 或 volatile-lfu 策略。

五、Redis分布式锁

1、可以直接采用redis的setNx来完成,当redis中没有数据返回ture表示拿锁成功,否则拿锁失败。接下来进行业务处理,最后删除redis数据。
可能会带来以下问题:
(1)拿到锁后,接下来执行的操作不具有原子性,如果抛出异常后锁无法释放,导致其他线程永远无法执行
(2)为了解决上面问题,设置redis超时时间,但是又引来了新的问题,超时时间没法明确到底需要多久,因为下面具体的业务执行时间需要多久无法确定。
(3)为了解决上面问题,当然也有解决方案,开启另外线程,监控业务情况,如果业务未完成给锁续命,带来的问题是代码非常复杂
2、Redisson实现分布式锁
redisson实现分布式锁

注意:Redisson实现的分布式锁可以重入(利用线程hash结构记录线程id和重入次数,同一个线程如果进来可重入,降低死锁出现的情况)
总结:Redisson底层也是setnx和lua脚本(保证原子性)

  • 18
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值