redis面试题(1)
1.实际项目中遇到的困难
缓存和数据库一致性问题:分布式环境下非常容易出现缓存和数据库间数据一致性问题,针对这一点,如果项目对缓存的要求是强一致性的,那么就不要使用缓存了。
我们只能采取合适的策略来降低缓存和数据间数据不一致的概率,而无法保证两者间的强一致性。合适的策略包括合适的缓存更新策略,更新数据库后及时更新缓存,缓存失败时增加重试机制
2.什么是缓存雪崩?
在某一个时间点大量的redis-key全部失效同时访问量很大,造成全部压力都去到了数据库中(场景,首页或者热点数据,某个大促时间中,缓存失效了,造成服务器崩了)
处理方式:每个key的失效时间都加一个随机值,保证不要同时大批量redis-key失效
3.什么是缓存穿透
缓存和数据库中都没有的数据,而用户不断发出请求,解决方案 增加接口参数验证,鉴权等,同时redis中也有一种方式可以做,**布隆过滤器,利用高效的数据结构和算法快速判断出你这个Key是否在数据库中存在,不存在你return就好了,存在你就去查DB刷新KV再return
4.什么是缓存击穿
跟雪崩有点相似,是针对某一个热点的key,一直请求量很高,在某个时刻过期了,高并发的请求压力都落到数据库上了。解决方法:设置热点数据永不过期,或者加上互斥锁。
public static String getData(String key) throws InterruptedException { //从Redis查询数据 String result = getDataByKV(key); //参数校验 if (StringUtils.isBlank(result)) { try { //获得锁 if (reenLock.tryLock()) { //去数据库查询 result = getDataByDB(key); //校验 if (StringUtils.isNotBlank(result)) { //插进缓存 setDataToKV(key, result); } } else { //睡一会再拿 Thread.sleep(100L); result = getData(key); } } finally { //释放锁 reenLock.unlock(); } } return result; }
6.redis这么快,它的“多线程模型”你了解吗?
意思说的其实redis这么快,为什么还是单线程?
1.因为redis完全基于内存的操作,cpu不是redis的瓶颈,redis的瓶颈只能是内存大小或者带宽的问题。
2.采用单线程,避免不必要的上下文切换和竞争条件,不存在多线程导致的cup切换,也不用考虑各种锁的问题
3.数据结构简单,存在内存中,类似于hashmap,hashmap的优势就是查找和操作的时间复杂度是o(1).
4.采用多路复用io,非阻塞io。
7.redis的淘汰策略
一共8种 :
- volatile-lru :从已设置过期时间的KV集中优先对最近最少使用(less recently userd)的数据淘汰
- volatile-ttl : 从已设置过期时间的KV集中优先对剩余时间短的(time to live)数据淘汰
- volatile-random :从已设置过期时间的KV集中随机选择数据淘汰
- volatile-lfu:从已设置过期时间的KV集中优先对访问频率最少的数据淘汰
- allkeys-lru :对所有KV集中优先对最近最少使用的数据淘汰
- allkeys-random:从所有KV集中随机选择数据淘汰
- allkeys-lfu:对所有KV集中优先对访问频率最少的数据淘汰
- noeviction:不淘汰策略,若超过最大内存,返回错误信息
8.redis持久化方式
redis为了保证效率,数据缓存在内存中,定期会保存到磁盘中以保持持久化
RDB:快照形式直接把内存中数据保存到一个dump文件中,定时保存,保存策略(默认策略)
AOF:把所有对redis服务器进行修改的命令都会存到一个文件里,命令的集合(数据更完整,但会消耗性能)
如果你非常关心你的数据,但仍然可以承受数分钟内的数据丢失,那么可以额只使用RDB持久。AOF将Redis执行的每一条命令追加到磁盘中,处理巨大的写入会降低Redis的性能,不知道你是否可以接受。数据库备份和灾难恢复:定时生成RDB快照非常便于进行数据库备份,并且RDB恢复数据集的速度也要比AOF恢复的速度快。当然了,redis支持同时开启RDB和AOF,系统重启后,redis会优先使用AOF来恢复数据,这样丢失的数据会最少
https://zhuanlan.zhihu.com/p/118561398