Redis总结
Redis面试总结
Redis 为什么这么快?
Redis 内部做了非常多的性能优化,比较重要的主要有下面 3 点:
- Redis 基于内存,内存的访问速度是磁盘的上千倍;
- Redis 基于 Reactor 模式设计开发了一套高效的事件处理模型,主要是单线程事件循环和 IO 多路复用;
- Redis 内置了多种优化过后的数据结构实现,性能非常高。

Redis 常用的数据结构有哪些?
- 5 种基础数据结构 :String(字符串)、List(列表)、Set(集合)、Hash(散列)、Zset(有序集合)。
- 3 种特殊数据结构 :HyperLogLogs(基数统计)、Bitmap (位存储)、Geospatial (地理位置)。
String 还是 Hash 存储对象数据更好呢?
- String 存储的是序列化后的对象数据,存放的是整个对象,String 消耗的内存约是 Hash 的一半,存储具有多层嵌套的对象时也方便很多。
- Hash 是对对象的每个字段单独存储,适用于部分数据经常变动的对象。
IO多路复用

Redis 内存淘汰机制了解么?
相关问题:MySQL 里有 2000w 数据,Redis 中只存 20w 的数据,如何保证 Redis 中的数据都是热点数据?
Redis 提供 6 种数据淘汰策略:
- volatile-lru(least recently used):从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
- volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
- volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
- allkeys-lru(least recently used):当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 key(这个是最常用的)
- allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
- no-eviction:禁止驱逐数据,也就是说当内存不足以容纳新写入数据时,新写入操作会报错。这个应该没人使用吧!
4.0 版本后增加以下两种:
- volatile-lfu(least frequently used):从已设置过期时间的数据集(server.db[i].expires)中挑选最不经常使用的数据淘汰
- allkeys-lfu(least frequently used):当内存不足以容纳新写入数据时,在键空间中,移除最不经常使用的 key
Redis 持久化机制
什么是 RDB 持久化?
Redis 可以通过创建快照来获得存储在内存里面的数据在某个时间点上的副本。类似MySQL的全量备份。
redis.conf 配置文件
1 | |
什么是 AOF 持久化?
与快照持久化相比,AOF 持久化的实时性更好,类似MySQL的binlog,redis.conf 配置文件
1 | |
通过aof-use-rdb-preamble开启RDB+AOF
Redis分布式锁
方案1
加锁与释放锁
1 | |
存在的问题
当客户端 1 拿到锁后,如果发生下面的场景,就会造成「死锁」:
- 程序处理业务逻辑异常,没及时释放锁
- 进程挂了,没机会释放锁
方案2
加锁的同时为锁设置有效期,避免因redis服务宕机而导致的死锁
1 | |
存在的问题
- 锁过期:客户端 1 操作共享资源耗时太久,导致锁被自动释放,之后被客户端 2 持有
- 释放别人的锁:客户端 1 操作共享资源完成后,却又释放了客户端 2 的锁
方案3
解决释放别人的锁的问题
1 | |
使用lua脚本保证获取锁和删除锁为原子性操作
1 | |
解决锁过期问题
使用Redisson的自动续期功能来避免锁过期
存在的问题
- 客户端 1 在主库上执行 SET 命令,加锁成功
- 此时,主库异常宕机,SET 命令还未同步到从库上(主从复制是异步的)
- 从库被哨兵提升为新主库,这个锁在新的主库上,丢失了!
方案4
使用RedLock,但也存在时钟问题,成本收益不成正比
Redlock 的方案基于 2 个前提:
- 不再需要部署从库和哨兵实例,只部署主库
- 但主库要部署多个,官方推荐至少 5 个实例
也就是说,想用使用 Redlock,你至少要部署 5 个 Redis 实例,而且都是主库,它们之间没有任何关系,都是一个个孤立的实例。
注意:不是部署 Redis Cluster,就是部署 5 个简单的 Redis 实例。
Redis总结
http://example.com/2023/03/09/interview/Redis总结/