1.为什么快?
-
基于key/value存储的 nosql 内存数据库
-
not only sql
-
内存 和 磁盘
-
内存是和cpu直接交互
-
磁盘 io
-
-
2.主从节点,怎么保证数据一致性?主从复制有什么作用?大致如何实现?
-
保证 master 和 slave 数据一致性
-
用主从复制
-
-
作用 故障转移 提升redis的qps
-
其中master挂了,可以迅速选举一台新的从节点作为master,保证服务高可用
-
假如 master 是写 slave是读 读写分离 降低了redis数据库压力
-
-
实现
-
全量同步
-
当数据量过大的时候 效率比较低 时效也低了 主从节点之间是存在 明显的数据延迟的
-
-
增量同步
-
其中一台slave挂了
-
先全量同步 然后 再增量 或者 先从磁盘上进行加载 再进行增量同步
-
-
新加一台slave
-
先全量同步 然后 再增量
-
-
3.Redis的持久化机制有了解过吗?
-
RDB,默认的redis持久化机制
-
根据我们自己配置的时间或者手动去执行相关命令(BGSAVE或SAVE命令),Redis就会去生成RDB文件 (我们所谓的快照文件)
-
这个RDB文件实际上就是一个经过压缩的二进制文件,Redis可以通过这个文件在启动的时候来还原我们的数据
-
优缺点:RDB 是间隔⼀段时间⽣成⼀次,两次 RDB 创建之间,如果Redis 发⽣故障,会发⽣数据丢失
-
-
AOF
-
把Redis服务器接收到的所有写命令都记录到日志中
-
Redis重跑一遍这个记录下的日志文件,就相当于还原了数据
-
优缺点:AOF ⽂件较⼤,会触发 AOF 重写,重写时会竞争内存资源;AOF 恢复是回放命令操作,恢复速度慢于 RDB
-
-
RDB+AOF(运维岗位开启)
-
redis4.0,提供了混合持久化功能,RDB 以⼀定的频率执⾏,在两次快照之间,使用 AOF 日志记录这期间的所有命令操作,避免了⼀直记录 AOF 的开销(例如 AOF 重写)
-
4.有了解过哨兵吗?为什么有哨兵?哨兵的能力是什么?
-
记录 master或者salve的一些信息
-
保证redis服务高可用
-
如何选举哨兵Leader?由哪个哨兵进行主从故障转移?
-
每个哨兵会不断的ping主服务器,如果在一定时间内无响应,那当前哨兵会认为主服务器下线,其他哨兵同样ping该主服务器,如果足够多(配置)的哨兵都认为该主服务器下线,那就要进行故障转移了
-
投票机制
-
第一,拿到半数以上的赞成票
-
第二,拿到的票数同时还需要大于等于哨兵配置文件中的 quorum 值
-
举个例子,假设哨兵节点有 3 个,quorum 设置为 2,那么任何一个想成为 Leader 的哨兵只要拿到 2 张赞成票,就可以选举成功了。如果没有满足条件,就需要重新进行选举。
-
-
-
哨兵节点为什么至少设置为3个?
-
如果哨兵集群中只有 2 个哨兵节点,此时如果一个哨兵想要成功成为 Leader,必须获得 2 票,而不是 1 票
-
所以,如果哨兵集群中有个哨兵挂掉了,那么就只剩一个哨兵了,如果这个哨兵想要成为 Leader,这时票数就没办法达到 2 票,就无法成功成为 Leader,这时是无法进行主从节点切换的
-
-
5.故障恢复如何实现?
-
筛选+排序
-
筛选当前健康的slave,把挂掉的/不健康的给排除掉
-
排序
-
按照redis底层优先级配置进行排序,选举出优先级最高的slave作为master,通知给其他的slave
-
假如 优先级相同 根据复制偏移量来进行优先级的判定
-
复制偏移量(offset):根据slave的复制效率和数据完整性来进行判定
-
-
6.哨兵之间是如何通信的?(了解)
-
sentinel_hello 通道
-
换master/故障转移时是需要进行互相通信的
7.说一说雪崩&&击穿&&穿透
-
由于redis发生故障或者缓存集体失效,无法正常访问,导致大量请求请求到mysql,导致mysql压力变大,响应慢/直接挂掉,以至于整个服务都挂掉
-
主从复制 、Cluster模式
-
可以设置不同的过期时间,防止缓存集体失效。随机时间范围
-
-
由于某些热点缓存失效,导致请求打到mysql上,增大mysql压力,响应慢/直接挂掉,以至于整个服务都挂掉
-
可以定时去刷新redis的过期时间,以此来保证缓存不会失效,保证mysql和redis的数据一致性
-
设置永不过期的失效时间
-
-
请求打到redis,redis未查询到数据,去查询mysql,依旧没有查到,且这样的请求很密集,增大mysql压力,响应慢/直接挂掉,以至于整个服务都挂掉
-
布隆过滤器,用于检索一个元素是否在一个集合当中
-
手动设置一个过滤器,可以把mysql的可能存在的数据范围缓存到redis中,如果不在此范围内,我认为是非法请求
-
8.缓存淘汰策略有了解过吗?简单说一下
-
在缓存数据过多时,需要使用某种淘汰算法决定淘汰哪些数据
-
先进先出(FIFO):判断被存储的时间,离目前最远的数据优先会被淘汰掉
-
11:00 key1 12:00 key2
-
key1 被淘汰
-
-
最近最少使用(LRU):判断缓存最近被使用的时间,距离当前时间最远的数据优先被淘汰
-
12:00 key1 08:00 key2
-
key2 被淘汰
-
-
最不经常使用(LFU):在一段时间内,被使用次数最少的缓存优先被淘汰
-
key1 800次 key2 1200次
-
key1 被淘汰
-
-
云服务解决方案:弹性扩容
-
redis 8G 设置80%阈值
-
到达6.4G,触发扩容 8G-->16G
-
-
9.缓存预热有了解吗?什么场景用?怎么用?
-
用户请求数据前,先将数据加载到缓存系统中,用户查询事先被预热的缓存数据,以提高系统查询效率
-
系统启动加载(冷启动)
-
定时加载
-
-
通过xxl-job在凌晨2点进行热点数据的加载,就是将热点数据从mysql取出来,之后缓存到redis,在客户端访问热点数据时,直接从redis当中来取,减少了mysql的压力,也可以一定程度上防止击穿
-
提高查询效率
10.如何去做缓存更新?有哪几种策略?(如何保证redis和mysql数据一致性?)
-
在数据发生变化后及时将变化后的数据更新到缓存当中
-
定时更新
-
定时将底层数据库内的数据更新到缓存中,该方法比较简单,需要缓存的数据量不是特别大的应用场景
-
-
过期更新
-
定时将缓存中过期的数据更新为最新数据并更新对应缓存的过期时间
-
-
写请求更新
-
在用户有写请求时,先写入数据库同时来更新缓存,这适用于用户对缓存数据和数据库数据有一致性要求
-
-
读请求更新
-
在用户有读请求时,先判断该请求数据的缓存是否存在或过期
-
如果不存在或已过期,则进行底层数据库查询并将查询结果更新到缓存中,同时将查询结果返回给用户
-
-
-
11.缓存降级有没有了解过?(为什么要使用redis,可以用它来干什么?)
-
由于访问量剧增导致服务出现问题(如响应时间慢或不响应)时,优先保障核心业务的运行,减少或关闭非核心业务对资源的使用
-
写降级
-
在写请求增大时,可以只进行缓存的更新,然后将数据异步更新到数据库中,保障数据的最终一致性即可,即将写请求从数据库降级为缓存
-
-
读降级
-
在数据库服务负载过高或数据库系统故障时,可以只对缓存进行读取,并将结果返回给用户,在数据库服务正常后再去查询数据库,即将读请求从数据库降级为缓存,这种方式适用于对数据实时性要求不高的场景,保障了在系统发生故障的情况下用户依然能够访问到数据,只是访问到的数据相对有点延迟
-
-
12.分布式锁用redis怎么实现的?CAP(补充一下CAP内容)
-
先理解分布式锁,如果不做分布式锁,会有什么问题?
-
库存扣减,有可能导致负卖/超卖
-
-
setNX 基于AP模型 可用性+分区容忍度
-
redisson支持分布式锁的操作
-
reids实现分布式锁
-
定义一个redis的key值,key就是你想加锁的东西
-
当用户请求时,redis把key进行存储(手动加锁),设置过期时间
-
当有其他请求进来时,先通过redis获取key值,看是否存在
-
存在,意味着被加锁了,直接返回
-
不存在,意味着没有加锁,把key进行存储(手动加锁)
-
-
-
执行业务逻辑,删除刚才存储key(手动解锁)
-
-
-
zk consul CP模型 一致性+分区容忍度
第一种: Boolean flag = redisTemplate.opsForValue().setIfAbsent(key,value,expireTime); //true:代表能获取到锁 //false:代表拿不到锁,也就是被加锁了 if(flag){ //todo xxxx redisTemplate.opsForValue().add/put redisTemplate.del(); } 第二种: RLock lock = redisson.getLock("xxxx"); //加锁 lock.lock(); lock.unlock();
13.你也可以用mysql也可以存,为啥还要用redis?
-
从redis和mysql各自的优缺点结合自己的理解进行回答
14.你redis缓存的数据都是从mysql来的,如何保证数据和mysql一致呢?延迟能接受吗?
-
当前: 是将数据的crud、缓存redis、放在一个事务当中,流程较长,所以执行的效率较低,保证数据的强一致性
-
优化:将流程解耦,通过mq来进行redis的存储 ,也是为了保证数据的最终一致性而非数据的强一致性,也是相对当前的结构延迟更高一点
-
接受不了这个时延怎么办?
-
缓存预热
-
15.既然你说redis存取数据快,我为啥不把所有数据都存在redis呢?
-
存储成本 企业是有预算的
-
未做持久化的redis 宕机会导致数据丢失 故障转移时进行主从转换 可能导致偏移量数据丢失
-
不是特别匹配结构化存储(mysql关系型数据库,redis是非关系型数据库)
16.你说你redis提前预热了一些数据,那你这个失效时间都是统一的,到点我缓存都失效了,请求不都打到我们mysql了吗?服务不就挂了吗?
-
造成缓存击穿/雪崩 进而请求打到mysql 增大mysql压力,有宕机的风险,以至于整个服务都挂掉
-
可以定时去刷新redis的过期时间,以此来保证大批量/热点缓存不会失效,保证mysql和redis的数据一致性
-
可以设置不同的过期时间,防止缓存集体失效。随机时间范围
17.有没有踩过redis什么坑?(做项目的时候有没有遇到什么难点?)
-
击穿 凌晨预热一批数据 设置了对应8h失效时间 有一次 公司新推了一个整点的活动 导致流量变大 我缓存又集体过期了,导致瞬时mysql压力变大 内存飙升导致整体服务的响应时间变长 后来5min之后 内存慢慢恢复 后来排查 是因为redis被击穿了 请求打到了mysql上
-
分布式锁
-
之前是锁的整个售货机 A买可乐 B就啥都买不了
-
锁的是售货机+商品 A买可乐 B除了可乐都能买
-