目录
1.Redis在项目中的主要作用是是什么?怎么用的?(应用场景)
10.Redis集群中某个master节点挂了,后面流程怎么判断?
11.Redis的缓存优化方向有哪些?你们怎么理解的?对热点键的注意事项设计什么?
12.高并发情况下,对于Redis的更新操作有哪些注意事项?
备注:针对基本问题做一些基本的总结,不是详细解答!
1.Redis在项目中的主要作用是是什么?怎么用的?(应用场景)
Redis作为一款性能优异的内存数据库,在互联网公司有着多种应用场景,主要有以下几个方面:
- 大多时候作为mq的替代者,当缓存,计数,统计,热数据
- 分布式锁
- 接口限流器
- Redis和DB数据一致性处理
- 防止缓存穿透和雪崩
- 分布式session共享
- 作为消息队列,生产一消费
- 作为订阅发布器,似聊天工具或推送
选择一些经典的问题:
- Redis和DB数据一致性处理
对于读操作流程:先到redis缓存中查询数据,如果为null,那么再到数据库查询出来再设置到redis中去,最后将数据返回给请求。
定义: 如果只是简单查询,缓存数据和数据库数据没有什么问题,当我们更新的时候就可能导致数据库数据和缓存数据不一致了。 数据库库存为 999 缓存数据为1000 这就是更新导致的情况。
解决方案:
1、比如操作菜单的时候,当我们增加 、删除、修改菜单时,操作成功之后就应该立刻根据菜单的key从redis缓存中把数据给删除,第二次查询 的时候肯定为null,从数据库查询再设置到redis中。这是马上见效情况
2、不是马上见效的情况,就是设置过期时间来确定,比如我们商城中web页面根据店铺搜索出来的数据有最新的4张照片,当我们在商家后台添加一个商品时,就应该显示在最新添加的照片,此时就不能按照删除key来操作redis了,因为多个商家添加多个商品,就失去了缓存的意义,那么会根据用户需求来设置过期时间,这里的redis缓存就可能和数据库不一致,需要过期时间来控制数据。因为缓存时间到了,就会被删除,再到数据库查询设置到redis中去。
- Redis实现分布式锁
基础方法:如果为空就插入值,返回true,如果不为空则不做操作,返回false----setIfAbsent(String key, String value)
插入新值并返回旧值----getAndSet(String key, String value)
具体思路:
- 基于Redis的限流器的实现
系统中的接口通常都有限流,比如 70次/秒 ,如何保证我们的接口的调用次数在超过第三方接口限流的时候快速失败?这时候就需要限流器了。
2.Redis支持的数据类型(必考)
3.zset跳表的数据结构(必考)
4.Redis的数据过期策略(必考)
5.Redis的LRU过期策略的具体实现
6.如何解决Redis缓存雪崩,缓存穿透问题
Redis缓存雪崩
定义:当 redis服务挂掉时,大量请求数据库,对数据库产生巨大的压力,导致数据库瘫痪。
场景: 把所有存入redis的所有数据设置相同过期的时间,过期时间失效后,就会大量请求数据库。
如何解决?
1、在缓存的时候我们给过期时间设置一个随机数,但是也要根据业务场景需求来设置
2、事发前:实现redis的高可用、主从架构+sentinel 或者 redis cluster
3、事发后:万一redis真的挂了、可以设置本地缓存ehcache+限流hystrix
4、事发后:redis持久化,重启后自动从磁盘上加载数据,快速恢复缓存数据
Redis缓存穿透
定义:大量到数据库请求一些不存在的数据,查询一个数据库不存在的数据。请求的数据在缓存大量不命中,导致大量请求数据库。
场景:比如我们表的数据的id是从1开始的正数,如果在这里有黑客攻击我们的系统,会设置一些负数的id到数据库查询数据,查询出来返回的数据为null,在这里,由于缓存不命中,并且处于容错考虑,从数据库查询的数据为null就不写到redis,这将导致每次查询数据都会到数据库查询,失去了缓存的意义。这样数据库迟早也会挂掉
如何解决缓存穿透?
1、由于请求的参数是不合法(-1) 每次请求都是不存在的数据,于是我们可以使用布隆过滤器(BloomFilter) 或者 压缩filter提前拦截,不合法就不能访问数据库。
2、当我们从数据库查询出来的数据为null时,也把他设置到缓存redis中,下次请求的时候就到redis中查询了,在这里后台可以判断,如果为null,那么设置一个较短的过期时间,到期自动就失效,否则就是按正常操作。
7.Redis的持久化机制(必考)
8.Redis的管道pipeline
9.Redis集群容错机制是什么样的?
10.Redis集群中某个master节点挂了,后面流程怎么判断?
11.Redis的缓存优化方向有哪些?你们怎么理解的?对热点键的注意事项设计什么?
12.高并发情况下,对于Redis的更新操作有哪些注意事项?
操作:先更新数据库,再删除缓存
正常的情况是这样的:
- 1、 先操作数据库,成功
- 2、再删除缓存,也成功
- 3、 如果原子性被破坏了:第一步成功(操作数据库),第二步失败(删除缓存),会导致数据库里是新数据,而缓存里是旧数据。
如果第一步(操作数据库)就失败了,我们可以直接返回错误(Exception),不会出现数据不一致。
如果在高并发的场景下,出现数据库与缓存数据不一致的概率特别低,也不是没有:缓存刚好失效//线程A查询数据库,得一个旧值//线程B将新值写入数据库//线程B删除缓存//线程A将查到的旧值写入缓存
要达成上述情况,还是说一句概率特别低,因为这个条件需要发生在读缓存时缓存失效,而且并发着有一个写操作。而实际上数据库的写操作会比读操作慢得多,而且还要锁表,而读操作必需在写操作前进入数据库操作,而又要晚于写操作更新缓存,所有的这些条件都具备的概率基本并不大。对于这种策略,其实是一种设计模式:Cache Aside Pattern
解决删除缓存失败的解决思路:将需要删除的key发送到消息队列中---自己消费消息,获得需要删除的key---不断重试删除操作,直到成功
操作:先删除缓存,再更新数据库
正常情况是这样的:
- 1、先删除缓存,成功;
- 2、再更新数据库,也成功;
- 3、如果原子性被破坏了
第一步成功(删除缓存),第二步失败(更新数据库),数据库和缓存的数据还是一致的。
如果第一步(删除缓存)就失败了,我们可以直接返回错误(Exception),数据库和缓存的数据还是一致的。
看起来是很美好,但是我们在并发场景下分析一下,就知道还是有问题的了:线程A删除了缓存///线程B查询,发现缓存已不存在
///线程B去数据库查询得到旧值///线程B将旧值写入缓存///线程A将新值写入数据库-------->所以也会导致数据库和缓存不一致的问题。
解决并发下解决数据库与缓存不一致的思路:将删除缓存、修改数据库、读取缓存等的操作积压到队列里边,实现串行化。
对比两种策略:
- 先删除缓存、再更新数据库----->在高并发下表现的不如意,在原子性被破环时表现优异
- 先更新数据库,再删除缓存(Cache Aside Pattern设计模式)) ----->在高并发先表现优异,在原子性被破坏时表现不如意
参考书籍、文献和资料
1.https://blog.csdn.net/weixin_42075468/article/details/89040452
2.http://www.360doc.com/content/18/0226/15/16915_732617375.shtml
3.https://blog.csdn.net/wang258533488/article/details/78913800
4.https://blog.csdn.net/wang258533488/article/details/78913827
转载:https://blog.csdn.net/xiaofeng10330111/article/details/105360939