Redis(远程字典服务) 基于内存的键值存储数据库,也支持持久化
Redis面试题
1.说说常用的命令
Keys * 查看所有的Key 线上不允许使用
FlushAll 删除所有 线上不允许使用
get set hset hget lpush lpop SETNX(尝试设置锁)
ttl 查询key过期时间
expire key续期 (redis 通过 setNX和expire(设置过期时间) 实现分布式锁)
2.用过哪些Redis数据类型
对数据类型的理解 结合使用场景、底层实现描述Redis数据类型
-
String 短信验证码 SDS简单动态字符串 TTL EXPIRE 限流 限流的数量(使用Redis中的INCR命令对特定键进行自增操作 表示请求次数 使用EXPIRE命令设置过期时间 过期时间等于窗口大小 窗口时间到达后,Redis会自动删除过期的键)
-
Hash 购物车/场站详情 Hash表.压缩列表 对某个字段频繁修改
-
Set 不重复 无序 Hash表 可以实现共同好友 好友推荐(根据两个人拥有的标签的交集)
-
Zset 不重复,有序 排行榜 跳表 压缩列表
-
List 有序 消息队列 生产消费模式 队列/列表
-
GEO 位置信息存储 底层实现了Zset 通过RedisTemplate的GEO类型方法操作得到的Stations 通过Stations.radius(circle,args)方法可以得到到点的距离
3.Redis中的数据能丢失吗?
Redis中的数据可以持久化
持久化把数据保存到磁盘
1.RDB[默认] 快照
间隔时间 某一时刻 把内存里的数据 拍个照片 写入磁盘
RDB触发方式
-
手动 save bgsave 不建议线上操作
-
自动 配置文件 配置保存路径 配置策略 save (间隔多久) (数据库发生多少次变化)
RDB持久化的优缺点
优点:把内存的数据压缩 速度快 持久化快 恢复快
缺点:拍照 时间间隔 的 数据 能丢失 但如果拍照频率过高 影响性能(写磁盘)
2.AOF(Append Only File)
配置AOF 只要有操作 写在文件的后面
AOF触发方式
-
appendfsync always 执行一次命令 追加一次 不丢失数据 耗资源
-
appendfsync everysec 每一秒执行一次 最多丢失一秒的数据
-
appendfsync no 由操作系统内核决定
这三种方式也叫AOF刷盘策略 结合业务场景原则适合的的刷盘策略 为了保证数据的绝对安全 选择 always
3.1AOF文件越来越大怎么办?
AOF重写 eg:对同一个key 操作的可以重写
3.2线上使用的是那种持久化方案?
RDB+AOF 结合
3.3做了持久化数据后还会丢失吗?
会
单点故障 磁盘故障 RDB和AOF文件丢失 换了磁盘重启Redis重启后 无法基于文件恢复
怎么办?
-
集群架构 主(leader master) 从(slave,follewer) 读写分离
数据同步 主从节点之间数据要进行同步 数据不一致的问题
CAP理论 C 一致性 A 可用性 P 分区容错性
P只要在分布式下 就是 必须的 AP CP 牺牲另一方
Redis Nacos 采用AP 高性能
ZooKeeper CP
-
分片
集群架构主服务器挂掉怎么办?
选举 故障转移 failover :当活动的服务或应用意外终止时,快速启用冗余或备用的服务器接替他们的工作
Sentinel 哨兵
-
监听 当半数以上哨兵确认服务器宕机 才是宕机(客观宕机) 只有自己说宕机是主观宕机
-
选主 选择数据全的(数据偏移量大的)
-
通知 通知客户端 谁是主 通知所有从谁是主
4.大量数据需要放进Redis中怎么办?
性能考虑: 单机 内存存储数据越大 生成RDB文件和基于RDB恢复耗时越长
集群 第一次主从复制性能耗时长
所以选择分片模式(Sharding)
HashSlot 确定数据存在哪个节点 就去哪个节点查 HashSlot算法
Hash冲突 拉链法解决
HashTag 把不同的数据存放到一个槽中 eg:计价数据同步 不能把每一次同步的数据放在不同的槽里
Gossip 分布式一致性协议-> 小白白成长之旅
5.Redis数据过期策略是什么意思?
淘汰策略:Redis把内存中数据删除的一种策略
写入Redis内存的时候,Redis内存满了
-
拒绝 OOM 不能写入
-
可以写 allkeys-LRU(最近最少使用) LFU(最不常使用) RANDOM 来淘汰数据
-
可以写 设置过期时间(volatile) 通过LRU LFU RANDOM 来淘汰数据
选择过期策略根据业务来选择?
重要的数据 noeviction(默认策略) 不删不淘汰 不写入
不重要的 allkeys-LRU/LFU 删除
5.1 Redis数据怎么过期的?
-
定期删除 定时任务,到期删除
-
惰性删除 用户访问的时候 判断是否过期 过期删除
6.Redis常见的问题 穿透 缓存 雪崩
- 穿透 数据在Redis和数据库中都没有 请求一直落在数据库上 压力激增
从Redis和数据库中查询都没有之后 把一个空值(Blank,Empty)放到Redis
之后就在Redis找到数据 不会去请求数据库了
当数据库有了数据后 通过双写 写入Redis
Redis 布隆过滤器 (在查询缓存前 可以用布隆过滤器判断数据是否存在 若不存在直接 返回不访问数据库)
2.雪崩 Redis数据大部分失效 全去查数据库 压力激增
别让Redis中的数据同时过期 设置随机的过期时间
3.击穿 某个Key被频繁的访问(热点数据),当热点数据过期,会打到数据库上 压力激增
把热点数据的Key 设置为永不过期
7.Redis中的缓存一致性?
数据库和Redis的数据一致性
-
Cannl
-
CacheAsidePattern 旁路缓存
-
读操作 读缓存 缓存没有读数据库
-
写操作 数据发生变化后 保持数据一致性 对数据库和缓存进行操作(更新删除)
-
双写 写数据库 写缓存 先后顺序问题(先写谁)? 数据操作问题(更新还是删除)?
延迟双删:线程操作了数据库 那么数据库就是新数据 删除缓存 sleep再删一次 缓存没 有值 查询数据库 放入Redis 新值
兜底 对缓存删除失败情况下 重试 数据一致性要求越高 重试频率越高
8.分布式锁
Redis分布式锁的实现主要基于Redis的一些原子性操作命令 SETNX EXPIRE
-
加锁 客户端使用SET命令尝试在Redis设置一个特定的键(作为锁的名称),这个键的值可以是一个唯一标识符或随机字符串,用于标识持有锁的客户端.同时,可以使用NX(Not Exists 键不存在时设置) 和PX(设置键的过期时间 ms级) 这两个作为选项来保证操作的原子性和锁的自动过期
-
解锁 当客户端完成对共享资源的操作后,可以说hi用DEL命令来删除锁键,从而释放锁.ps:DEL是一个原子操作,因此可以确保释放锁的安全性
-
锁续期 为了防止因为客户端执行时间过长导致锁的过期,客户端可以定期使用EXPIRE命令来重置锁的超时时间,实现锁的续期.
在业务中 缓存预热 多个设备节点 在启动时都会进行预热 重复执行
加了分布式锁 设备服务在启动时,抢到锁的才进行预热 抢不到锁无需预热
保证只有一个节点 进行预热
9.Redis为什么这么快?
-
基于内存的存储 数据的读写操作都是在内存级别进行的 非磁盘级别
-
优化的数据结构和算法 SDS 哈希表 跳表 压缩列表 哈希表用于实现键值对的快速存储和查找 调表用于有序集合(ZSet)的快速插入 删除和查找
-
非阻塞IO模型 Redis采用异步非阻塞IO模型来处理客户端请求,意味着Redis正在处理一个客户端请求时,可以同时接受其它请求放在队列中等待
-
网络模型 高效的网络模型 多路复用