Contents

php解决并发操作影响:LuaScripts

背景

问题
异步操作同一个代码块时,比如多个队列,恰巧有两个一起被触发,会在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操作

相关文档

coffee