背景
问题
异步操作同一个代码块时,比如多个队列,恰巧有两个一起被触发,会在mysql读取到脏数据,虽然可以使用lockForUpdate避免,但是若有很多并发队列,会造成这条记录一直处于被锁的状态,以至于其他地方无法正常获取数据。因为如果get()和set的操作不是原子性的,会造成很小概率的,第二条队列在第一条set()之前get()了,导致无法锁上,所以采用以下方式加锁。
使用lua脚本避免
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| private function getLock($key)
{
return $this->redis->eval(
$this->preventRepeated(),
1,
$key
);
}
private function preventRepeated()
{
return <<<'LUA'
local hash = redis.call('get', KEYS[1])
if hash then
return 0
else
redis.call('set',KEYS[1],1)
return 1
end
LUA;
}
private function releaseLock($keys)
{
$this->redis->del($keys);
}
|
laravel中使用的 频率限制
的封装的 funnel 方法 ,是一个道理,是用循环获取锁进行sleep操作
相关文档