0%

基础实现

如何用 Redis 实现分布式锁?核心步骤是什么?

一句话原理:Redis 分布式锁基于“占用式”思想,利用 SET NX EX 原子命令抢占锁标识,通过唯一 Value 防止误删,并结合 Lua 脚本确保“判断+删除”解锁过程的原子性。

一句话源码:在 db.c 中,SET NX 命令本质上调用 setKey 函数,在 lookupKeyWrite 查找 Key 不存在时执行 dbAdd 写入并关联 setExpire 过期时间,从而实现互斥。

一句话项目/场景:在电商秒杀扣减库存场景中,使用 SET lock:stock UUID NX EX 10 加锁,业务执行完毕后通过 Lua 脚本校验 UUID 并 DEL,严防超卖与死锁。

Redis 为什么这么快?(内存、IO 多路复用、单线程)

一句话原理:Redis 基于纯内存操作规避磁盘 I/O 瓶颈,利用 epoll 机制实现 IO 多路复用,在单线程事件循环中串行处理命令,彻底避免了多线程上下文切换与锁竞争的开销。

一句话源码:核心逻辑位于 aeProcessEvents 函数,通过 aeApiPoll 监听就绪 Socket,将网络读写与命令执行封装为 FileEvent 事件,在主线程中由 aeMain 循环按顺序无锁调度执行。

一句话项目/场景:在 Redis 6/7 版本的高并发场景下,针对网络 I/O 瓶颈引入多线程进行数据协议的读写解析,但核心命令执行仍保持单线程,既利用多核提升吞吐,又规避了事务与 Lua 脚本的并发原子性问题。

数据库和缓存双写时,如何保证一致性?

一句话原理: 采用“先更新数据库,再删除缓存”的策略(Cache Aside Pattern),配合异步重试机制或 Binlog 订阅(如 Canal),在保证数据库持久化成功的前提下,最终一致性地删除过期缓存。

一句话源码: 在业务 Service 层代码中,通常将数据库更新操作与缓存删除操作封装在同一个本地事务 @Transactional 下,顺序执行 db.update()cache.delete(),并通过消息队列记录删除失败的 Key 以便补偿。

一句话项目/场景: 在电商“订单状态修改”场景中,先更新 MySQL 订单表,再删除 Redis 中的订单缓存,若因网络抖动导致删除失败,通过监听 MySQL Binlog 自动触发缓存删除重试,确保用户查询时能读到最新状态,避免“退款成功但前端仍显示处理中”的业务故障。

入门

Redis 支持哪些数据类型?各自的应用场景是什么?

五大基础数据类型

一句话原理:Redis提供五种核心数据类型String(字符串)、Hash(哈希)、List(列表)、Set(集合)、ZSet(有序集合),每种类型底层采用不同的数据结构实现,满足多样化的业务场景需求。