Redis知识点(面试篇)
1.为什么使用nosql
- 主要是由于随着互联网发展,数据量越来越大,对性能要求越来越高,传统数据库存在着先天性的缺陷,即单机(单库)性能瓶颈,并且扩展困难。
- NoSQL 根本性的优势在于在云计算时代,简单、易于大规模分布式扩展,并且读写性能非常高
2.nosql数据库分类
- 列存储、文档存储 、key-values存储、图存储、对象存储、xml数据库
3.CAP理论
对于一个分布式计算系统,不可能同时满足以下三点,只能两两满足。
- C:Consistency。即一致性, 所有节点在同一时间具有相同的数据视图。换句话说,如果一个节点在写入操作完成后,所有其他节点都能立即读取到最新的数据。
- A:Availability即可用性,所有的节点都保持高可用性,要求服务在接收到客户端请求后,都能够给出响应。每个非故障节点都能够在有限的时间内返回有效的响应,即系统一直可用。可用性强调系统对用户请求的及时响应。
- P:Partiton tolerance。分区容错性。分区是指系统中的节点由于网络故障无法相互通信,导致系统被分成多个孤立的子系统。在分布式系统中,不同节点之间通过网络进行通信。分区容忍性是指当分布式系统中出现网络分区(即系统中的一部分节点无法和其他节点进行通信)时,系统能够容忍这种情况,并且分离的系统也能够正常运行。这意味着,即使系统中某些节点或网络分区出现故障或延迟,整个系统仍然能够继续运作,不会受到单点故障的影响。
CA - 单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大。比如,单一数据中心数据库,所有节点都位于同一个数据中心,并且节点之间的通信是高可靠的。
CP-满足一致性,分区容忍性的系统,通常性能不是特别高。例如: Zookeeper,ETCD,Consul,MySQL的PXC等集群就是追求的强一致
AP - 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些。例如:MySQL主从复制,默认是异步机制就可以实现AP,但是用户接受所查询的到数据在一定时间内不是最新的.
4.缓存的实现流程
5.缓存穿透,缓存击穿和缓存雪崩
- 缓存穿透:指缓存和数据库中都没有的数据,而用户不断发起请求,这时的用户可能是攻击者,会导致数据库压力过大。
- 解决:接口层增加校验,如用户鉴权校验,ID做基础校验
- 缓存击穿:指缓存中没有但数据库中有的数据,比如:热点数据的缓存时间到期后,这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大
- 解决:设置热点数据永不过期
- 缓存雪崩:指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机
- 解决:缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生
- 如果缓存数据库是分布式部署,将热点数据均匀分布在不同缓存数据中
- 设置热点数据永不过期
- 缓存宕机crash
- Redis 缓存服务宕机,造成 缓存服务失效
- 解决方法:Redis高可用集群
6、redis慢查询
6.1什么是redis慢查询,和mysql慢查询有什么区别
- Redis 慢查询:Redis 会记录执行时间超过预设阈值的命令,存入慢查询日志,用来定位执行耗时过高的 Redis 命令。
- 区别
- 统计范围
- MySQL 慢查询:包含网络传输、锁等待、执行时间;
- Redis 慢查询:只统计服务端命令执行耗时,不统计网络往返、队列等待时间。命令在队列排队阻塞,哪怕整体客户端耗时很久,只要命令本身执行快,不会进慢查询。
- 存储方式
- MySQL:写入磁盘日志文件;
- Redis 慢查询:默认存内存环形队列,重启全部丢失,不会自动落盘。
- 触发对象:MySQL 是 SQL 语句;Redis 是 Redis 命令(keys、hgetall、smembers 等)。
- 统计范围
6.2Redis 慢查询两个核心配置参数 slowlog-log-slower-than、slowlog-max-len含义,单位是啥?
- slowlog-log-slower-than:慢查询阈值,单位微秒
- 值为0:记录所有命令
- 值为负数:关闭慢查询
- 超过阈值的命令会被记录慢查询
- slowlog-max-len:慢查询内存队列最大长度
- redis慢查询保存在内存环形队列,不写磁盘。达到长度上限后,旧的慢查询记录会被新的记录挤出去丢弃。
6.3线上 Redis,客户端反馈请求响应很慢,但是看 Redis 慢查询日志几乎没有记录,会是什么原因?
因为redis慢查询值统计命令执行耗时,下面这些场景客户端延迟很高,但是不会产生慢查询记录:
- 命令排队阻塞:Redis 单线程模型,如果前面有一条大命令占住主线程,后面大量请求在队列排队等待。后面的命令本身执行很快,但排队等待时间久。客户端看到延迟高,但是这些后续命令执行时间很短,不会进入慢查询。
- 网络问题:客户端和服务端网络抖动、带宽打满、TCP 丢包,网络往返耗时高,服务端执行命令很快。
- 客户端自身问题:客户端 CPU 高、线程池耗尽、连接池耗尽,请求在客户端排队等待发送。
- Redis 触发持久化 fork 子进程:RDB fork,操作系统拷贝页表会短暂阻塞主线程,造成请求卡顿,但实际每条命令执行本身很快。
- 大量 key 过期、大 key 驱逐:内存淘汰策略触发大量 key 清理,主线程阻塞。
排查思路:看 Redis 的latency延迟监控、查看 CPU、网络、客户端连接池情况,不能只依赖慢查询。
6.4线上大量慢查询,拿到慢查询记录之后,完整排查、处理的思路是什么?
- 通过slowlog get 拿到慢查询,确认时哪一类命令:是全量遍历(keys/hgetall/smembers)?还是复杂操作?还是大key操作?记录命令、耗时、发生时间。
- 确认慢查询发生频率:是偶发还是持续大量出现
- 判断根因:
- 若是高危全量命令:推动业务改成 scan 迭代方式;
- 若是大 key:定位大 key,拆分 key;
- 若是批量操作:业务侧拆分请求,减少单次操作数据量;
- 环境侧检查:Redis 内存是否打满、是否频繁内存淘汰、是否有 fork RDB/AOF 刷盘阻塞。
- 监控加固:脚本定时采集慢查询日志落盘,配置监控告警,当慢查询数量突增触发告警;
- 输出记录给到开发,推动业务代码优化,更新运维故障文档
6.5慢查询日志抓到一条慢查询是 KEYS *,为什么这个命令会很慢,生产怎么处理?
- keys *遍历 Redis 全量 key,单线程执行,key 数量巨大的时候会阻塞整个 Redis 主线程,所有其他命令全部被阻塞,属于高危命令。
- 禁止在线上业务直接使用 keys;
- 替代方案:
- 如果要遍历 key,生产使用 SCAN游标迭代遍历,分批获取 key,不会阻塞主线程;
- 运维排查,可在从库执行 scan,避免影响主库业务。
7持久化
7.1什么是 RDB?RDB 持久化的两种触发方式分别是什么?
RDB 是 Redis 的快照持久化机制,把 Redis 某一时刻内存中全量数据,以二进制快照文件保存到磁盘,文件名叫
dump.rdb。分为自动触发、手动触发。手动触发
SAVE:主线程同步执行 RDB,Redis 阻塞,大数据量会卡死业务,生产基本禁用。BGSAVE:fork 子进程做快照;父进程继续处理客户端请求,不会阻塞主线程(fork 瞬间会短暂阻塞)。
自动触发(配置 save 参数)
- redis.conf 中
save 900 1 #含义:900 秒内至少发生 1 次 key 改动,则执行 BGSAVE。注意:save 配置本质是自动调用 BGSAVE,不是 SAVE。
额外触发场景:
Redis 正常关闭(shutdown),如果没有开启 AOF,会自动执行 BGSAVE 生成 rdb;
主从全量同步,主库执行 BGSAVE,把 RDB 发送给从库做数据同步。
7.2RDB模式的优缺点
- 优点
- RDB快照只保存某个时间点的数据,恢复的时候直接加载到内存即可,不用做其他处理,这种文件适合用于做灾备处理.可以通过自定义时间点执行redis指令bgsave或者save保存快照,实现多个版本的备份。比如: 可以在最近的24小时内,每小时备份一次RDB文件,并且在每个月的每一天,也备份一个RDB文件。这样的话,即使遇上问题,也可以随时将数据集还原到指定的不同的版本。
- RDB在大数据集时恢复的速度比AOF方式要快
- 缺点
- 不能实时保存数据,可能会丢失自上一次执行RDB备份到当前的内存数据。如果需要尽量避免在服务器故障时丢失数据,那么RDB并不适合。虽然Redis允许设置不同的保存点(save point)来控制保存RDB文件的频率,但是,因为RDB文件需要保存整个数据集的状态,所以它可能并不是一个非常快速的操作。因此一般会超过5分钟以上才保存一次RDB文件。在这种情况下,一旦发生故障停机,就可能会丢失较长时间的数据。
- 在数据集比较庞大时,fork()子进程可能会非常耗时,造成服务器在一定时间内停止处理客户端请求,如果数据集非常巨大,并且CPU时间非常紧张的话,那么这种停止时间甚至可能会长达整整一秒或更久。另外子进程完成生成RDB文件的时间也会花更长时间.
- 误删除,无法恢复
7.3SRE 视角,线上 RDB 生产最佳实践是什么?
- 不要把 RDB 作为唯一持久化方案,生产建议 RDB + AOF 同时开启;
- 大内存主库关闭自动 save 触发,RDB 备份放在从库执行,减轻主库 fork 阻塞压力;
- 定时将 rdb 文件异地备份(其他机器 / 对象存储),不要只存在本机;
- 监控 BGSAVE 执行状态、fork 耗时,配置告警;
- 预留足够磁盘空间,防止生成 rdb 时磁盘满导致备份失败;
- 业务高峰期避免手动执行 BGSAVE;
- 系统内核参数调优vm.overcommit_memory=1,避免 fork 失败。
7.4什么是 AOF?AOF 三种刷盘策略分别是什么,SRE 角度分析各自优缺点
AOF(Append‑Only File),日志追加持久化。Redis 把每一条写命令以文本协议格式追加写入 AOF 日志文件,重启时重放 AOF 里面的命令恢复内存数据。
appendfsync三个刷盘策略:- appendfsync always每执行一条写命令就调用 fsync 刷盘到磁盘。 优点:最多丢失 1 条命令,数据安全性最高; 缺点:IO 极其频繁,磁盘压力巨大,性能很差,生产几乎不用。
- appendfsync everysec(生产默认推荐)Redis 每秒执行一次 fsync,把缓冲区数据刷入磁盘。 优点:性能较好;最坏情况宕机丢失1 秒的数据,兼顾性能与安全。 缺点:如果磁盘 IO 压力很高,fsync 会被阻塞。
- appendfsync no交给操作系统控制刷盘时机,Redis 不主动 fsync。 优点:性能最好; 缺点:丢失数据取决于操作系统,可能丢失几秒到几十秒数据,风险高。
生产会结合业务容忍丢失数据的程度选择刷盘策略
7.5AOF 重写(AOF‑Rewrite)是什么?为什么需要 AOF 重写?触发方式?
为什么需要重写。AOF 不断追加写命令,文件会越变越大。比如同一个 key 多次 set,AOF 会保存多条 set;恢复时全部重放,文件臃肿、重启恢复慢。 AOF 重写:Redis 生成一份新 AOF 文件,只保留 key 最终状态,丢弃中间冗余命令,实现 AOF 文件压缩变小。重写不会读取旧 AOF,读取当前内存数据生成新日志。
触发分为手动、自动:
手动触发:BGREWRITEAOF,后台子进程执行,类似BGSAVE
自动触发,配置两个参数控制:
auto‑aof‑rewrite‑percentage100#AOF文件相比上次重写后增长100%触发重写auto‑aof‑rewrite‑min‑size 64mb#AOF至少达到64MB才允许触发重写
8消息队列
8.1说一下消息队列两种模式
- 生产者消费者模式
- 生产者消费者模式下,多个消费者同时监听一个频道(redis用队列实现),但是生产者产生的一个消息只能被最先抢到消息的一个消费者消费一次,队列中的消息由可以多个生产者写入,也可以有不同的消费者取出进行消费处理.此模式应用广泛
- 发布者订阅者模式
- 在发布者订阅者Publisher/Subscriber模式下,发布者Publisher将消息发布到指定的频道channel,事先监听此channel的一个或多个订阅者Subscriber都会收到相同的消息。即一个消息可以由多个订阅者获取到. 对于社交应用中的群聊、群发、群公告等场景适用于此模式
9高可用
9.1主从复制故障恢复
- 当从节点宕机时,将redis client指向另一个slave节点即可,并及时修复故障从节点
- 当master节点故障时,需要提升slave为新的master;master故障后,当前还只能手动提升一个slave节点为master;而master的切换会导致master_repild发生变化,slave之前的这个和当前的master不一致从而会引发所有的slave的全量同步
,将redis client指向另一个slave节点即可,并及时修复故障从节点
- 当master节点故障时,需要提升slave为新的master;master故障后,当前还只能手动提升一个slave节点为master;而master的切换会导致master_repild发生变化,slave之前的这个和当前的master不一致从而会引发所有的slave的全量同步