Redis分布式锁实战
Redis分布式锁实战
引言
多服务器部署项目时,多个服务实例同时操作同一资源,会出现并发争抢问题。Redis分布式锁可以保证同一时间只有一个请求执行临界代码,常用于订单扣库存、定时任务防重复执行场景。
实现原理
利用RedisSET key value NX EX命令:NX仅当key不存在才设置,EX设置过期时间。原子命令可以防止锁成功后服务宕机导致死锁。解锁时需要校验锁的值,防止误删除别人的锁。
PHP代码示例
<?php
$redis = new Redis();
$redis->connect('127.0.0.1',6379);
$lockKey = 'order:lock:1001';
$lockVal = uniqid();
// 获取锁,过期10秒
$ok = $redis->set($lockKey,$lockVal,['NX','EX'=>10]);
if($ok){
try{
// 临界区业务代码
echo "获取锁,执行业务";
}finally{
// lua脚本原子解锁,判断value一致才删除
$lua = 'if redis.call("get",KEYS[1]) == ARGV[1] then return redis.call("del",KEYS[1]) else return 0 end';
$redis->eval($lua,[$lockKey,$lockVal],1);
}
}else{
echo "获取锁失败,资源被占用";
}
注意事项
- 锁必须设置过期时间,防止程序崩溃死锁;
- 解锁必须用Lua脚本,保证判断和删除原子操作;
- 业务执行时间不能超过锁过期时间,可增加锁续期逻辑;
- 单机Redis存在单点故障,高可用场景用Redis集群或Redlock。
总结
Redis分布式锁简单易用,适合中小型Web项目并发控制。理解原子操作、锁过期、安全解锁三个关键点,避免网上简易版本带来的并发漏洞。