Redis 的数据类型
五种基本数据类型:
StringListSetHashZSet(有序集合)
三种特殊数据类型:
Stream(消息队列)HyperLogLog(基数统计)Bitmap(位图)Geospatial(地理位置)
Redis 为什么快?
-
基于内存操作,比磁盘快很多
-
redis数据类型(结构)性能很高 -
redis执行命令是单线程的,避免了上下文切换带来的性能问题,也不用考虑锁的问题
使用 String 还是 Hash 存储对象数据更好?
-
当对象结构简单,而且操作是整体操作的时候使用
String更适合 -
如果需要操作对象的字段或者节省内存,选择
Hash更合适
购物车信息用 String 还是 Hash 存储更好?
- 购物车中的商品频繁修改和变动, 使用
Hash存储
使用 Redis 的哪种数据结构实现点赞功能
-
使用
Set实现,Set适用于点赞,关注/粉丝,去重(签到,注册等)场景 -
Set支持快速添加/删除,还能自动去重
如何使用 Redis 实现一个排行榜
- 使用
Sorted Set(有序集合) - 相关的一些命令:
ZRANGE(从小到大排序)、ZREVRANGE(从大到小排序)、ZREVRANK(指定元素排名)
Set 的应用场景
Set是无序集合,集合中的元素没有先后顺序但都唯一,类似于Java中的HashSet
常见应用场景:
-
存放的数据不能重复的场景:网站
UV统计、文章点赞、动态点赞等等 -
获取交集、并集和差集:共同好友(交集), 好友推荐(差集)、音乐推荐(差集)、订阅号推荐(差集+交集)等
-
需要随机获取元素的场景:抽奖系统、随机点名等
Redis 除了做缓存, 还能做什么?
- 分布式锁
- 消息队列
- 计数器与限流器
- 延时队列
- 分布式
session
Redis 是单线程的,但是为什么还那么快?
- 单线程, 避免了线程切换和锁竞争开销
- 核心原因:
- 基于内存操作, 读写速度快
IO多路复用:用epoll/kqueue等机制处理多客户端连接,单线程高效处理并发请求- 高效数据结构:如跳表(Sorted Set)、压缩列表(Hash)等,操作复杂度低
- 无阻塞命令:核心命令(如
GET、SET)执行时间短,避免单线程阻塞
Redis 持久化机制
-
RDB(快照), 定期将内存中数据生成快照写入二进制文件(.rdb),重启时快速加载,适合大数据量的恢复 -
AOF(追加日志), 每执行一次写操作,就把该命令追加到文件里(appendonly.aof),数据持久性最好 -
混合持久化(Redis 4.0+):
RDB + AOF
Redis事务
-
用于保证一组命令的原子性(要么全部执行,要么全部不执行),不支持回滚操作
-
redis事务的实现使用MULTI(事务的开始)和EXEC(事务的结束)命令 -
输入
MULTI命令后,redis返回OK表示事务开启,然后输入需要在本次事务中执行的所有命令,每次输入命令不会立即执行,而是返回QUEUED,表示命令已经并排入事务队列,最后输入EXEC命令后,才会依次执行这些命令.
``
- 核心命令:
MULTI:开启事务- 命令序列:如
SET key1 val1、INCR key2等(入队,未执行) EXEC:执行事务内所有命令DISCARD:取消事务WATCH key:监视 key,若事务执行前 key 被修改,则事务中断(乐观锁机制)
缓存
| 问题 | 定义 | 解决方案 |
|---|---|---|
| 缓存击穿 | 热点数据的缓存突然过期,大量请求直接冲击数据库 | 1.互斥锁 2.逻辑过期(缓存永不过期,后台异步更新) |
| 缓存穿透 | 查询不存在的数据,请求绕过缓存直接访问数据库 | 1.布隆过滤器 2.缓存空值 |
| 缓存雪崩 | 大量Key同时过期,或缓存集群宕机,导致所有请求直接访问数据库 |
1.随机过期时间,分散key过期时间 2.使用多级缓存 3.使用Redis 集群部署,主从 + 哨兵模式 |
什么是布隆过滤器?
-
一种概率型数据结构,通过多个哈希函数将数据映射到位图(
bitmap),用于快速判断元素是否 "可能存在" -
特点:
- 优点:空间效率高,查询速度快
- 缺点:可能误判,不支持删除操作
Redis 分布式锁如何实现?
方法一: 基于 Redis 的 SET 命令实现
加锁:
redis
SET lock:order:1001 "UUID:threadId" NX PX 30000
-
NX:当key不存在时才设置(保证互斥) -
PX 30000:设置 30 秒过期时间(避免死锁)
解锁 :通过 Lua 脚本原子性判断并删除锁
方法二: 使用 Redisson 框架
如何合理控制分布式锁的有效时长
-
基础原则:设置略大于业务执行时间的过期时间(如业务需 5 秒,设 10~15 秒)
-
动态续期:使用
Redisson的Watch Dog机制,若线程未执行完,每隔1/3过期时间自动延长锁有效期
Redis 双写问题是什么?如何解决?
-
定义:同时更新数据库和缓存时,因为并发操作、网络延迟或执行顺序不当等导致缓存与数据库数据不一致
-
解决:
- 先更数据库,再删缓存
- 延迟双删:删除缓存后延迟
100ms再次删除,避免并发更新时的脏数据 - 最终一致性:通过消息队列或定时任务同步缓存与数据库差异
Redis 的数据过期策略有哪些?
- 惰性删除:访问
key时才检查是否过期,过期则删除 - 定期删除:每隔一段时间随机检查部分过期 key 并删除
- 内存淘汰:当内存达到
maxmemory阈值时,触发淘汰策略
Redis 的数据淘汰策略有哪些?
- volatile-lru:从设置了过期时间的 key 中,淘汰最近最少使用的
- allkeys-lru:从所有 key 中,淘汰最近最少使用的(最常用)
- volatile-lfu:从过期 key 中,淘汰最不经常使用的
- allkeys-lfu:从所有 key 中,淘汰最不经常使用的
- volatile-random:从过期 key 中随机淘汰
- allkeys-random:从所有 key 中随机淘汰
- volatile-ttl:淘汰过期时间最近的 key
- noeviction:默认策略,不淘汰任何 key,写操作返回错误
Redis集群方案
-
主从模式:一个
master节点,多个slave节点,master节点宕机,slave自动变成主节点 -
哨兵模式:在主从集群基础上添加哨兵节点或哨兵集群,用于监控
master节点健康状态,通过投票机制选择slave成为主节点 -
分片集群:多个
master节点, 不同master保存不同的数据,master之间通过ping相互监测健康状态。客户端请求任意一个节点都会转发到正确节点,因为每个master都被映射到0-16384个插槽上,集群的key是根据key的hash值与插槽绑定
什么是 Redis 主从同步?
主从同步第一次是全量同步, slave 第一次请求 master 节点根据 replid 判断是否是第一次同步,是的话 master 会生成 RDB 发送给 slave
增量同步, 后续主节点的写操作会通过复制缓冲区同步到从节点
好处:提高读吞吐量,主节点故障时从节点可切换为主节点
Redis 分片集群中数据是怎么存储和读取的?
- 存储 :
- 集群将 16384 个哈希槽分配给各主节点(如 3 主节点分别负责 0-5460、5461-10922、10923-16383 槽)
- 写入 key 时,通过
CRC16(key) % 16384计算槽位,自动路由到对应主节点
- 读取 :
- 客户端首次连接时获取集群槽位映射表,后续直接定位节点
- 若槽位迁移(如扩容),节点返回
MOVED重定向,客户端更新映射表后重试
Redis 集群脑裂是什么?如何解决?
- 定义:主从集群中,主节点网络波动导致哨兵误判其下线,选举从节点为新主,原主节点恢复后出现 "双主"(脑裂),数据写入旧主会丢失
- 解决方法 :
- 配置
min-replicas-to-write 1:主节点必须至少有 1 个从节点连接正常才允许写操作 - 配置
min-replicas-max-lag 10:从节点同步延迟超过 10 秒,主节点拒绝写操作
- 配置
怎么保证 Redis 的高并发高可用?
- 高并发 :
- 分片集群(Redis Cluster)分散读写压力
- 合理使用管道(Pipeline)和批量命令(如
MSET)减少网络交互 - 优化数据结构(如用
Hash替代多个String)
- 高可用 :
- 主从 + 哨兵模式,自动故障转移
- 数据持久化(RDB+AOF)防止数据丢失
- 限流保护(如用
redis-cell模块)避免突发流量压垮集群