1. 为什么使用 Redis
- 性能:对于频繁的数据库操作,可以用 Redis 缓存,提升响应速率
- 并发:在大并发的情况下,大量请求访问数据库会导致异常,所以 Redis 可以作为缓冲操作
2. 使用 Redis 有什么缺点
- 缓存和数据库双写一致性问题
- 缓存雪崩问题
- 缓存击穿问题
- 缓存并发竞争问题
3. 单线程的 Redis 为什么这么快
- 纯内存操作
- 单线程操作,避免频繁的上下文切换
- 采用了非阻塞 I/O 多路复用机制
单线程监听 I/O,使用文件事件分派器统一处理命令分派
4. Reids 的数据类型,以及每种数据类型的使用场景
- 数据类型:所有 key 都是字符串对象
1)String
2)Hash:相当于 map,键值对
3)List:有序,可重复的集合
4)Set:无序,不重复的集合
5)Sorted Set:带有权重 Score 的有序,不重复集合
5. Redis 的过期策略以及内存淘汰机制
- 定期策略:定期监视 key,过期则自动删除,可以很多利用内存,但浪费 CPU 资源
- 惰性策略:在 Redis 执行命令之前,调用函数去检查输入键是否过期,过期则删除,对 CPU 友好,但对内存不友好
- 一般采用定期 + 惰性策略:定期删除一部分的过期键
- 内存淘汰机制:如果定时和惰性策略没有删除 key ,则会浪费内存,一般使用的内存淘汰策略为 Volatile-lru:删除过期键中,最近最少使用的键
6. Redis 和数据库双写一致性问题
只能保持最终一致性
- 先更新数据库,再更新缓存
- 对于失败操作,可以用消息队列提供补偿
7. 如何应对缓存穿透和缓存雪崩问题
- 缓存穿透:数据在缓存中不存在,每次请求都直接访问数据库
解决方法:
1)利用互斥锁:缓存失效时,需要先获取锁,再请求数据库
2)采用异步更新策略:请求则直接返回,再异步更新缓存
3)提供判断请求是否有效的拦截机制:如布隆过滤器 - 缓存雪崩:缓存大面积实效,同时请求数据库
解决方法:
1)给缓存的实效时间:添加一个随机值
2)使用互斥锁:吞吐量下降
3)双缓存:一个有实效时间,一个无实效时间,如果范围有实效时间的缓存没数据,则直接返回无实效时间的缓存,然后一步更新双缓存
8. 如何解决 Redis 的并发竞争 Key 问题
- Redis 事务机制:吞吐量低
- 分布式锁:
1)对 key 的操作无序:则直接抢占锁来进行操作
2)对 key 的操作有序:则在 key 对应的 value 中设置一个时间,抢占锁的时候,发现时间早于 key 的时间,就不进行操作
9. Redis 事务
- multi 命令:multi 开启事务,每个命令语法正确则会入队,调用 EXEC 时,执行命令,错误没有回滚,可以使用 DISCARD 放弃事务
- WATCH:乐观锁实现,监视 key,直到操作成功
- Redis 脚本:lua 脚本事务执行
10. Redis3.0 集群
- 槽指有 16384 个,每个 redis master 负责一定连续的区域
- 每个 master 可以有多个 slave 从结点
- 然后通过哨兵监控所有的主从结点,当一个 master 宕机后,选举一个 从结点作为 master
11. Redis 哨兵
- 作用:
- 监控 Master 和 Slave 是否正常
- 提醒:提醒出问题的结点
- 自动故障转移,master 结点故障后,选举 slave 结点为 master 结点
- 多哨兵选取领头羊
在某个结点出现疑似下线时,哨兵开始选举领头羊,每个结点要求所有结点选举自己,通过配置纪元来判别是否是同一次选举,当获得票数超过一半时,才称为领头羊 - master 故障转移
选举出领头羊后,哨兵领头羊移除下线的结点,然后根据从结点的优先级高,偏移量大,id小进行一次判断,来选举从结点 - 缺点:存在访问中断,还是单机性能
12. Redis 事件
- 分为文件事件和时间事件
- Redis 轮流执行文件事件和时间事件,不会抢占,所以定时任务会比实际的事件慢