redis 实现分布式锁
高并发下回出现数据错乱 如何解决
1 使用 redis 的setnx
Redis Setnx(SET if Not eXists) 命令在指定的 key 不存在时,为 key 设置指定的值
$goods_id = 1;
$exists redis->setnx(goods_id,"value");
if(!$exits){
return false; // 如果上面设置redis成功 说明是第一次进来,否则就是第二次 第三次,进来 直接返回false
}
// 执行逻辑
2 上面的问题 没有释放锁,那么这个商品,就永远没有其他人可以操作了。
解决办法 执行完成后释放锁
try{
$exists redis->setnx(goods_id,"value");
if(!$exits){
return false; // 如果上面设置redis成功 说明是第一次进来,否则就是第二次 第三次,进来 直接返回false
}
// 执行逻辑
}finally{
$redis->delete(key);
}
3. 上面程序问题,加入执行到finally之前,程序挂掉了,那锁还是永久没有被释放
解决办法 设置redis的时候,设置超时时间 并且是原子的 设置值和超时时间一起设置
4.上面程序问题 加入我程序还没执行完成,redis锁设置的超时时间到了
外面等着一堆请求进来,这个时候,当前请求执行完成,我的锁已经自动过期了,我然后把刚刚进来的锁给释放了
相当于释放了别人的锁。这样也许这把锁就永久都用不上,我放了别人的锁,第三个又进来,第二个又放了
第三个的锁
解决办法 只能释放自己的锁
redis设置值得时候,弄一个唯一值作为键值 这样就不会释放到别人的锁了
$value = md5(microtime();
$redis->setnx($key,$value,10);
finally{
$value = $redis->get($key)
if($value == $value){
$redis->delete();
}
}
5 .上面程序还有问题 如何控制我在程序还没有执行完的时候,redis锁不因为redis ttl自动过期
思路 可以启动定时器,在上面过期时间三分之一的时候,补齐时间,比如十秒自动过期 ,
定时器检测,当本程序还没执行完,而且到了三秒了,补齐为10s
java有个现成的 Redisson
php https://github.com/ronnylt/redlock-php
b站视频学习地址 https://www.bilibili.com/video/BV1d4411y79Y?p=1