Redis有哪些基本数据类型?常见应用场景呢?
string 缓存对象(JSON/XML)、计数器(访问量、点赞数)、分布式锁(setnx),验证码、Session
hash 用做传输对象的存储、存储用户信息(id、name、email)、购物车、配置表
list 可以用来做消息队列,存放消息,做顺序存储
set 存相同属性的数据 ,标签(去重)、共同好友、抽奖、随机推荐
zset 排行版、定时任务(score=时间戳)、优先级队列
bitmap 存大数据量、统计活跃用户、签到、二进制标
stream 用于做流式存储,比如高可靠消息队列、日志采集
缓存穿透?击穿?雪崩?
缓存穿透:客户端大量请求数据库中和缓存中不存在的数据,导致频繁的请求数据库。
解决方案:缓存null值到缓存,布隆过滤器过滤、做接口参数校验
缓存击穿:某个 热点 key 缓存刚好过期,瞬间有大量请求打到数据库。
解决方案:互斥锁、给key设置逻辑过期时间
缓存雪崩:大量 key 在同一时间同时失效,请求全都打到数据库,压垮系统。
解决方案:给key设置随机TTL+ 预热 + 高可用
你怎么保证缓存与数据库一致性?
保证缓存和数据库完全一致性在高并发场景下几乎是不可能的,通常我们采取的策略是尽量减少不一致的时间窗口,同时根据业务选择合适的缓存更新策略。
常见做法包括:
- 先更新数据库再删除缓存
- 这是最常用策略。删除缓存后,下次请求会从数据库重新读取并写入缓存。
- 为了避免并发情况下数据不一致,可以采用延迟双删策略:先删缓存 → 更新数据库 → 等一段时间再删缓存一次。等待时间可参考数据库写入并更新缓存的耗时。
- 消息队列异步更新缓存
- Canal + MQ 异步更新
- 通过数据库 binlog(Canal)监听数据变更,再推送消息给缓存服务。
- 分布式锁保证强一致性
- 写操作加分布式锁(如 Redis、Zookeeper),确保同一时间只有一个线程可以修改数据库和缓存。
- 缺点:性能低,无法高并发写。
常见缓存更新策略有哪些?
| | | |
|---|
| | | |
| | | |
写回(Write Back / Asynchronous Write) | | | 风险:缓存宕机可能丢数据,需持久化机制(如 MySQL redo log) |
| | | |
补充原理:
- 类似 MySQL 的 Buffer Pool:先写到缓存/内存,再异步刷盘。
- 操作系统 Page Cache 也是同样原理。
为什么要删除缓存而不是直接更新?
删除缓存比更新缓存操作简单,避免复杂的更新逻辑。
更新缓存可能带来并发写冲突:假设线程 A 和 B 同时更新数据,如果 A 先写数据库但 B 先更新缓存,就会导致缓存数据不一致。
删除缓存失败怎么办?
可以采用 延迟双删策略:
- 先删除缓存
- 更新数据库
- 等一段时间再删除缓存一次
- 等待时间可参考数据库写入和缓存更新的耗时
- 保证并发情况下脏数据不会长期存在
读写分离的场景下还能保证一致性吗?
读写分离存在小概率不一致:主库写入后同步到从库存在延迟,如果同时有请求访问从库,可能读到旧数据。
- 解决办法:
- 强一致场景加分布式锁
- 合理设置缓存过期时间
- 部分关键数据读写走主库
总结面试核心观点
- 缓存一致性很难完全保证,只能尽量减少脏数据存在时间。
- 延迟双删:适合读多写少场景,强一致但性能低,写多读少不适合。
- 分布式锁:保证强一致性,但牺牲并发性能。
- 消息队列 / Canal + MQ:异步策略,降低耦合,保证最终一致性(Eventual Consistency)。
- 策略选择要结合业务场景:读多写少 vs 写多读少,不同策略效果差异很大。
Redis的主从同步?持久化机制了解过吗?
主从同步(Replication)
Redis 主从同步是用来保证数据在多个节点之间一致性与高可用的机制。
- 全量同步:当从节点第一次连接主节点或者从节点落后过多时,主节点会把整个 RDB 文件发送给从节点,然后从节点加载到内存中。
- 增量同步:全量同步完成后,主节点会将后续写操作以命令流的方式同步给从节点。
- 同步原理:主节点发送数据时会维护一个“数据偏移量(offset)”,从节点确认接收到的命令,保证主从数据一致。
- 哨兵机制(Sentinel):
- 监控节点状态,发现主节点宕机
- 进行故障转移(选择复制偏移量最大、优先级高的从节点升级为主节点)
- 保证集群可用性和自动恢复
持久化机制(Persistence)
Redis 提供两种主要持久化机制:
- RDB(快照):
- 定期生成内存快照保存到磁盘
- 优点:效率高、恢复快
- 缺点:最近几秒的数据可能丢失
- AOF(Append Only File):
- 记录每条写命令到日志,类似 MySQL binlog
- 优点:持久性强,可以配置 fsync 策略保证数据安全
- 缺点:日志大时性能开销大
- 混合持久化:
- AOF 重写时,将当前内存数据以 RDB 写入 AOF 文件,再追加新命令
- 综合 RDB 快速恢复和 AOF 持久性
Redis为什么快?
Redis 之所以快,主要有几个原因:
- 内存存储:所有数据都保存在内存中,避免了磁盘 I/O 开销,访问速度非常快。
- 单线程模型:Redis 使用单线程处理命令,避免多线程上下文切换和锁竞争的开销。
- I/O 多路复用:单线程可以同时处理大量客户端连接请求而不阻塞。
- 高效数据结构:提供 String、Hash、List、Set、ZSet 等多种数据结构,支持快速查找、排序和聚合操作。
- 原子性保证:单条命令天然原子,Lua 脚本可以保证多条命令原子执行,无需锁。
解释下I/O 多路复用模型(Reactor 模型)?
Redis 单线程能够处理上千甚至上万并发连接,关键是使用了 I/O 多路复用(I/O multiplexing) 模型。
- 原理:单线程通过一个事件循环,监听所有客户端 socket 的 I/O 状态(可读、可写、异常)。
- 当某个 socket 可读或可写时,事件循环会通知线程处理该事件,而不是每个连接都占用一个线程。
- 常用实现:
select、poll、epoll(Linux)、kqueue(BSD/macOS)
- 优势:
- 单线程避免锁竞争,减少上下文切换
- 高效处理大量并发连接
- 与 Redis 的内存数据结构结合,保证操作快速完成
Redis的IO多路复用模型是其实现高并发的核心基石,它允许Redis在单线程模型下依然能高效地处理成千上万个客户端连接,而不会因某个连接的IO操作而阻塞。它的本质是,Redis将所有客户端Socket连接都注册到一个事件分发器上(在Linux上通常是epoll),由这个分发器来统一监听所有连接的IO事件。当某个连接准备好读或写数据时,分发器就会通知Redis主线程,主线程才去处理这个就绪的连接,处理完后又立刻返回继续等待下一个事件通知。这种机制避免了为每个连接创建线程的巨大开销,也避免了单线程轮询所有连接造成的CPU浪费,通过将耗时的IO等待交给内核处理,使得单线程可以专注于实际的数据读写和计算,从而实现了极高的处理性能。
Redis实现登录机制?
1️⃣ 思路:使用 Redis 管理 Session / Token
- 用户登录
- 用户提交账号密码 → 后端验证数据库
- 验证成功后生成 Token(UUID 或 JWT)
- 将 Token 和用户信息存入 Redis,并设置 过期时间(TTL)
- 登录状态维护
- 每次请求带上 Token
- 后端在 Redis 中查 Token 是否存在
- 存在 → 用户已登录
- 不存在 → 登录过期 / 未登录
- 退出登录
- 删除 Redis 中的 Token
- 用户请求再校验 Redis,找不到即登出成功
2️⃣ Redis 数据设计
- Key:
login:token:{token}
- Value: 用户信息 JSON(如 userId、角色等)
- TTL: 根据业务需求设置,例如 30 分钟或 1 天
- 示例:
Key: login:token:UUID123 Value: {"userId":1001,"username":"ynchen"} TTL: 30分钟
Redis实现防抖和节流?
Redis 实现防抖和节流主要利用它的高性能内存存储和 TTL 机制。
防抖的思路是:每次事件触发时,在 Redis 设置一个带过期时间的 key,如果 key 已存在就忽略操作,只有最后一次触发事件后过期时间到才执行操作,从而避免短时间内重复执行。
节流的思路是:利用 Redis 的计数器和 TTL,每次请求先自增计数,如果计数超过限制就拒绝请求,否则执行操作,计数器过期后重置,这样可以保证固定时间内执行次数不超过阈值。Redis 的高并发性能和自动过期特性,使其非常适合做分布式防抖和节流。
bigkey和hotkey如何优化?
1️⃣ 概念
- Big Key(大键)
- 指占用内存特别大的 key,例如一个 Hash 包含几十万条字段,或者一个 List/ZSet 元素特别多。
- 会导致操作耗时过长,阻塞 Redis 单线程,影响其他请求。
- Hot Key(热键)
- 指被频繁访问或写入的 key,高并发访问时可能成为性能瓶颈,甚至引发雪崩。
2️⃣ 优化策略
Big Key 优化
- 拆分数据
- 将大 Hash、List、ZSet 拆分成多个小 key,降低单个操作耗时。
- 例如购物车 10 万商品 → 按用户或分类拆分多个 Hash。
- 使用分页或批量操作
- 对 List/ZSet 使用
LRANGE、ZREVRANGE 分页读取,避免一次性遍历大集合。
- 避免频繁操作大 key
- 大 key 的写操作最好异步或通过队列处理,减少阻塞。
Hot Key 优化
- 缓存分片/热点拆分
- 将一个热点 key 拆成多个小 key,分散访问压力。
- 本地缓存 + Redis 二级缓存
- 热点数据先在应用内存缓存一部分,减少对 Redis 的频繁访问。
- 异步处理写操作
- 限流 + 防止雪崩
- 设置 TTL + 随机过期,防止热点同时过期造成缓存雪崩。
3️⃣ 面试亮点
- Big Key 优化核心是减少单个 key 的操作耗时
- Hot Key 优化核心是分散访问压力、防止瞬时并发打满 Redis
- 实际生产中,两者常结合 TTL、异步队列和本地缓存策略使用