Redis高频面试题

1、redis的几种数据类型?
五大基本数据类型:String、List、Set、ZSet、Hash
2、redis是单线程还是多线程?
无论是什么版本的redis工作线程只有一个,
在6.x高版本中出现了IO多线程(处理磁盘读写的是多线程,进行数据计算和操作的只有一个工作线程。
类似netty的主从Reactor模式
3、redis有线程安全性问题吗?为什么?
redis是线程安全的,redis可以保证内部串行,外界使用时只需要保证业务顺序即可
4、redis的缓存穿透、击穿、雪崩详述一下?
  • 穿透:缓存穿透的概念很简单,用户想要查询一个数据,发现redis内存数据库没有,也就是缓存没有命中,于是向持久层数据库查询。发现也没有,于是本次查询失败。当用户很多的时候,缓存都没有命中,于是都去请求了持久层数据库。这会给持久层数据库造成很大的压力,这时候就相当于出现了缓存穿透(采用布隆过滤器)
  • 击穿:热点key过期(或者从来没有缓存,数据库存在数据)类似穿透,解决方案(请求redis数据不存在是时开始抢锁,没抢到锁的等待或者降级,拿到锁的请求开始请求数据库。获取数据后,更新缓存)
  • 雪崩:多个key同一时间过期(数据库存在数据)解决方案:分散设置key的过期时间(random),
5、redis的缓存如何回收?
  • 后台轮询的时候分段分批删除过期的key
  • 访问redis缓存数据的时候判断是否过期,过期则删除
  • 尽量的把内存无用的空间回收回来。
6、redis的缓存如何淘汰?
  • 内存空间不足的情况下。
  • 淘汰机制里有不允许淘汰
  • LRU算法:最近最少使用。优先淘汰最近未被使用的数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”,LRU底层结构是 hash 表 + 双向链表。hash 表用于保证查询操作的时间复杂度是O(1),双向链表用于保证节点插入、节点删除的时间复杂度是O(1)
  • LFU算法:使用频率最少的(最不经常使用的)优先淘汰最近使用的少的数据,其核心思想是“如果一个数据在最近一段时间很少被访问到,那么将来被访问的可能性也很小”。LFU 使用 Morris counter 概率计数器,仅使用几比特就可以维护 访问频率,Morris算法利用随机算法来增加计数,在 Morris 算法中,计数不是真实的计数,它代表的是实际计数的量级。
  • TTL算法:从设置了过期时间的数据中,挑选越早过期的数据进行删除
7、如何进行缓存预热?
  • 提前将数据缓存至redis,哪些是热数据(刚开始并不知道,从测试切到生产,首先会出现穿透,雪崩。然后就会知道哪些数据需要预热了)
8、数据库和缓存不一致如何解决?
  • 最直接的办法就是通过canal去延迟写数据库
  • 延迟双删
    1)先删除缓存;
    2)再写数据库;
    3)休眠500毫秒(根据具体的业务时间来定);
    4)再次删除缓存
  • 通过binlog
    (1)更新数据库数据
    (2)数据库会将操作信息写入binlog日志当中
    (3)订阅程序提取出所需要的数据以及key
    (4)另起一段非业务代码,获得该信息
    (5)尝试删除缓存操作,发现删除失败
    (6)将这些信息发送至消息队列
    (7)重新从消息队列中获得该数据,重试操作。
  • 如果数据库不采用事务,那么第一的方案是「先删除缓存,再更新数据库」;
  • 如果数据库采用了事务,但是是读的场景为主,那么方案优先次序为:「先更新数据库,再更新缓存」、「先更新数据库,再删除缓存」、「先删除缓存,再更新数据库」
  • 如果数据库采用了事务,但是是写的场景为主,那么方案优先次序为:「先更新数据库,再删除缓存」、「先更新数据库,再更新缓存」、「先删除缓存,再更新数据库」
  • 之所以把「先更新数据库,再更新缓存」放在「先删除缓存,再更新数据库」前面是因为后者既对代码侵入性、和提高复杂,而且效率降低(在维护redis穿透和击穿时需要互斥),而前者只是效率降低)无论哪种情况都不应该采取的方案:「先更新缓存,再更新数据库」
  • 总结
    1、懒加载模式缓存可采取双删+TTL失效来实现;
    双删失败情况下可采取重试措施,重试有业务通过mq重试以及组件消费mysql的binlog再写入mq重试两种方式;
    2、主动加载由于操作本身不具有幂等性,所以需要考虑加载的有序性问题,采取mq的分区机制实现串行化处理,实现缓存和mysql数据的最终一致,此时读和写操作的缓存加载事件是走的同一个mq。
8、描述一下redis持久化原理?
  • redis会fork一个子线程去执行持久化
  • RDB:保存数据快照至一个RDB文件中,用于持久化。RDB操作和Mysql Dump相似。优点:速度快,但是一致性较差,恢复快(大指令集)
  • AOF:采用AOF持久方式时,Redis会把每一个写请求都记录在一个日志文件里(追加写),AOF操作和Mysql Binlog相似。通过AOF重写机制减少AOF文件的体积,从而减少恢复时间。效率慢(如果开启了同步策略,不开启的情况下和RDB一致),一致性强,恢复慢
  • 总结:二者选择的标准,就是看系统是愿意牺牲一些性能,换取更高的缓存一致性(aof),还是愿意写操作频繁的时候,不启用备份来换取更高的性能,待手动运行save的时候,再做备份(rdb)。rdb这个就更有些 eventually consistent的意思了。不过生产环境其实更多都是二者结合使用的。
9、为什么使用setnx?
  • 使用SETNX实现分布式锁
    如果 SETNX 返回1,说明该进程获得锁,SETNX将键 lock.foo 的值设置为锁的超时时间(当前时间 + 锁的有效时间)。
    如果 SETNX 返回0,说明其他进程已经获得了锁,进程不能进入临界区。进程可以在一个循环中不断地尝试 SETNX 操作,以获得锁。
  • 解决死锁
    考虑一种情况,如果进程获得锁后,断开了与 Redis 的连接(可能是进程挂掉,或者网络中断),如果没有有效的释放锁的机制,那么其他进程都会处于一直等待的状态,即出现“死锁”。
    上面在使用 SETNX 获得锁时,我们将键 lock.foo 的值设置为锁的有效时间,进程获得锁后,其他进程还会不断的检测锁是否已超时,如果超时,那么等待的进程也将有机会获得锁。
10、redis的分布式锁原理?
  • 使用setnx、getset、expire、del这4个redis命令实现
  • 底层使用了Lua脚本
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值