2020-07-28 16:09:00
Redis本身在保存数据时不会自动加锁,其设计基于单线程模型处理命令,天然避免了多线程竞争问题,但不保证高并发场景下的数据一致性。以下是关键点解析:
核心机制与限制
Redis的命令执行是原子性的,例如SET key value或HSET hash field value等操作在单条命令内不会中断。但针对同一数据的多个并发修改(如多个客户端同时执行INCR)仍可能因指令交错导致数据错误。例如,两个客户端同时读取值1并尝试自增,最终结果可能仅增加1次而非2次。
锁的实现方式
客户端加锁
通过代码逻辑实现,例如在Java中使用synchronized或分布式锁框架(如Redisson),确保同一时间仅一个线程操作Redis。这种方式依赖客户端代码的严谨性,但无法解决跨服务或跨进程的竞争问题。
Redis原生命令模拟锁
SETNX(SET if Not eXists):
命令SETNX key value仅在键不存在时设置值,返回1表示获取锁成功,0表示失败。但需手动释放锁(DEL key),且存在死锁风险——若客户端崩溃未释放锁,其他请求将永久阻塞。
SET命令扩展参数:
Redis官方推荐使用SET key value NX EX seconds组合,其中NX表示键不存在时设置,EX seconds指定自动过期时间。例如:
SET my:lock 1 NX EX 10
此方式原子性同时设置锁和超时时间,避免死锁,但需确保超时时间合理(过长影响并发,过短可能导致业务未完成锁已释放)。
高并发场景实践
以电商秒杀为例,需保证库存扣减的原子性。典型流程:
总结
Redis本身无自动锁机制,但可通过SET NX EX等命令或客户端代码实现分布式锁。正确使用需兼顾原子性、超时控制与异常处理,避免死锁或数据竞争。对于复杂场景,建议使用成熟框架(如Redisson)简化实现。