1. Redis为什么早期选择单线程?
其实就是历史原因,开发者嫌多线程麻烦,后来这个CPU的利用问题就被抛给了使用者。
Redis 4.0 之后开始变成多线程,除了主线程外,它也有后台线程在处理一些较为缓慢的操作,例如清理脏数据、无用连接的释放、大 Key 的删除等等。
2. Redis6.0使用多线程是怎么回事?
其实Redis在执行命令时,使用的还是单线程;在执行I/O和协议解析等操作时,执行的是多线程。
这是因为Redis的性能瓶颈在网络I/O而非CPU。

3. Redis持久化方式有哪些?有什么区别?
Redis持久化方式有AOF和RDB。
- AOF:以独立日志的方式记录每次写命令, 重启时再重新执行AOF文件中的命令达到恢复数据的目的。AOF的主要作用是解决了数据持久化的实时性,目前已经是Redis持久化的主流方式。
- RDB:RDB方式则是将当前数据快照存储到磁盘,分手动触发和自动触发,RDB文件是一个压缩的二进制文件。
4. RDB 和 AOF 各自有什么优缺点?
RDB:
- 优点:
- 数据恢复快
- 容灾性好,可以将备份数据远程拷贝到其他机器,用于容灾恢复
- 缺点:
- 实时性低,RDB并不能做到秒级持久化,而是会间隔一段时间再持久化
AOF:
- 优点:
- 实时性好
- 缺点:
- AOF文件较大,并且恢复速度慢
5. Redis的主从复制原理了解吗?
- 首先在从节点(slave)保存主节点的ip和端口号
- 从节点(slave)发现主节点(master)后,向主节点(master)发送ping请求进行首次通信,本次通信是检测主从之间网络套接字是否可用、主节点当前是否可以接受处理命令。
- 若主节点要求密码验证,从节点需要发送账号密码用于验证
- 建立连接后,主节点会把数据全部发送给从节点
- 之后的主节点会持续把
写命令
发送给从节点,保证数据一致性
6. 主从复制存在哪些问题呢?
主从复制虽好,但也存在一些问题:
- 一旦主节点出现故障,需要手动将一个从节点晋升为主节点,同时需要修改应用方的主节点地址,还需要命令其他从节点去复制新的主节点,整个过程都需要人工干预。
- 主节点的写能力受到单机的限制。
- 主节点的存储能力受到单机的限制。
第一个问题是Redis的高可用问题,第二、三个问题属于Redis的分布式问题。
7. Redis Sentinel(哨兵)了解吗?
主从复制存在一个问题,没法完成自动故障转移。所以我们需要一个方案来完成自动故障转移,它就是Redis Sentinel(哨兵)。
Redis Sentinel ,它由两部分组成,哨兵节点和数据节点:
- 哨兵节点: 哨兵系统由一个或多个哨兵节点组成,哨兵节点是特殊的 Redis 节点,不存储数据,对数据节点进行监控。
- 数据节点: 主节点和从节点都是数据节点;

8. 什么是缓存击穿、缓存穿透、缓存雪崩?
- 缓存击穿:缓存击穿是指访问量很大的某个key突然失效,请求一下全部打到数据库。解决方案如下:
- 若缓存是基本不更新的,可以设置为永不过期
- 若缓存中数据经常使用,且为热点数据,那么可以每查询一次便重新更新他的失效时间(我在项目中就是这样做的)
- 加锁更新,比如请求查询A,发现缓存中没有,对A这个key加锁,同时去数据库查询数据,写入缓存,再返回给用户,这样后面的请求就可以从缓存中拿到数据了(感觉这样性能比较差)
- 缓存穿透:缓存穿透是指查询的是缓存中和数据库都不存在的数据,这样每次请求都打到数据库上。解决方案如下:
- 每次都数据库查数据时,如果没查到数据,就写一个空值到缓存中去,再设置一个失效时间,这样再有相同请求走的都是缓存。
- 缓存雪崩:缓存雪崩是指大量缓存突然失效,造成大量请求打到数据库
- 事前:Redis 高可用,主从+哨兵,Redis cluster,避免全盘崩溃。
- 事中:本地 ehcache 缓存 + hystrix 限流&降级,避免 MySQL 被打死。
- 事后:Redis 持久化,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据。
9. 什么是布隆过滤器?
布隆过滤器,它是一个连续的数据结构,每个存储位存储都是一个bit
,即0
或者1
, 来标识数据是否存在。
存储数据的时时候,使用K个不同的哈希函数将这个变量映射为bit列表的的K个点,把它们置为1。
我们判断缓存key是否存在,同样,K个哈希函数,映射到bit列表上的K个点,判断是不是1:
- 如果全不是1,那么key不存在;
- 如果都是1,也只是表示key可能存在。
简单说,布隆过滤器就是判断某个数据在不在布隆过滤器内,使用方式如下:
Redis实现布隆过滤器的底层是通过bitmap数据结构。
1 | <dependency> |
1 | public static void main(String[] args) { |
布隆过滤器也有一些缺点:
- 它在判断元素是否在集合中时是有一定错误几率,因为哈希算法有一定的碰撞的概率。
- 不支持删除元素。
在openArt项目中,我们在判断用户短信验证码是否重复验证时使用了。
10. Redis的过期淘汰策略?
Redis的过期淘汰策略是:定时删除 + 惰性删除。
Redis的默认定时100ms拿出一批数据来删除其中过期的数据。
但是如果数据量过大,有10wkey,就不可能每次删除都遍历一遍看是否过期然后删除,那样性能消耗过高。所以Redis执行的是定时随机抽取一批数据,看里面是否有过期的数据,如果过期,便删除。
但是这样会有大量过期的Key没被删除,这样就会走内存淘汰策略。
Redis的内存淘汰策略有以下几种:
- 当内存不足以容纳新写入数据时,新写入操作会报错(很少有人用)
- 当内存不足以容纳新写入数据时,在键空间内,删除最近最久未使用的key(常用)
- 当内存不足以容纳新写入数据时,随机干掉某个key(很少有人用)
- 当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近 最少使用的 key(这个一般不太合适)
- 在设置了过期时间的键空间中,随机 移除某个 key
11. Redis报内存不足怎么处理?
- 增加Redis可用内存
- 修改内存淘汰策略
- 使用 Redis 集群模式,进行横向扩容
12. 大key问题了解吗?
大key的成因:
- 单个的key的value很大,超过10kb
- list、set、zset或hash存储了过多元素
大key会造成什么问题呢?
客户端耗时增加,甚至超时
对大key进行IO操作时,会严重占用带宽和CPU
造成Redis集群中数据倾斜
主动删除、被动删等,可能会导致阻塞
如何找到大key?
- bigkeys命令:使用bigkeys命令以遍历的方式分析Redis实例中的所有Key,并返回整体统计信息与每个数据类型中Top1的大Key
- redis-rdb-tools:redis-rdb-tools是由Python写的用来分析Redis的rdb快照文件用的工具,它可以把rdb快照文件生成json文件或者生成报表用来分析Redis的使用详情。
怎么处理大key?
- 删除大key
- 当Redis版本大于4.0时,可使用UNLINK命令安全地删除大Key,该命令能够以非阻塞的方式,逐步地清理传入的Key。
- 当Redis版本小于4.0时,避免使用阻塞式命令KEYS,而是建议通过SCAN命令执行增量迭代扫描key,然后判断进行删除。
- 压缩和拆分key
- 当vaule是string时,比较难拆分,则使用序列化、压缩算法将key的大小控制在合理范围内,但是序列化和反序列化都会带来更多时间上的消耗。
- 当value是string,压缩之后仍然是大key,则需要进行拆分,一个大key分为不同的部分,记录每个部分的key,使用multiget等操作实现事务读取。
- 当value是list/set等集合类型时,根据预估的数据规模来进行分片,不同的元素计算后分到不同的片。
13. Redis底层数据结构有哪些,编码方式有哪些?
- 底层数据结构:ZipList、SDS、SkipList、ht(字典)、list、intset(整数集合)

14. 假如Redis里面有1亿个key,其中有10w个key是以某个固定的已知的前缀开头的,如何将它们全部找出来?
使用 keys
指令可以扫出指定模式的 key 列表。但是要注意 keys 指令会导致线程阻塞一段时间,线上服务会停顿,直到指令执行完毕,服务才能恢复。这个时候可以使用 scan
指令,scan
指令可以无阻塞的提取出指定模式的 key
列表,但是会有一定的重复概率,在客户端做一次去重就可以了,但是整体所花费的时间会比直接用 keys
指令长。