什么是分布式锁
- 分布式锁: 进行逻辑处理时经常会遇到并发问题。可以借助redis来实现分布式锁,简单来说就是限制两个操作不同时进行,每次执行某个操作的时候用setnx()加锁,当没被锁再执行下一个操作.限制程序的并发执行!
- 一般步骤: 使用 setnx(set if not exists) 指令,只允许被一个客户端占坑。先来先占,用完了,再调用 del 指令释放茅坑。
- setnx lock:XXX true
分布式锁问题
-
锁的释放问题: 如果执行到一半出现问题,没有执行del释放锁,那么锁就得不到释放
可以给锁加个expire过期时间
-
锁的超时问题: 当设置过期时间比较短的时候,可能程序还未执行完毕,锁已经超时过期了.第二个线程重新持有了这把锁, 但是紧接着第一个线程执行完了业务逻辑,就把锁给释放了,第三个线程就会在第二个线程逻 辑执行完之间拿到了锁。(超时后使用del 导致误删其他线程的锁)
- 分布式锁不要用于长时间的任务
- 给value设置一个随机数,释放的时候匹配随机数是否一致再删除
- 编写守护进程,当一个锁快要过期的时候,任务还未结束,可以给锁续一波命(过期时间),任务结束关闭该守护进程
lua脚本实现匹配和删除的一个原子操作
# delifequals
if redis.call("get",KEYS[1]) == ARGV[1]
then
return redis.call("del",KEYS[1])
else
return 0
end
<?php
// php中使用redis执行lua脚本
$lua = <<<SCRIPT
lua代码
SCRIPT;
$s = $redis->eval($lua,'参数');
- 请求加锁失败的处理:
- 抛出异常,稍后重试
- 将请求添加到延时队列
- sleep几秒钟
分布式锁应用场景
- 订单等并发请求
- 任务队列