php解决并发操作:LuaScripts

2019-03-26  本文已影响0人  段义纬

1、文档:https://redis.io/commands/eval#atomicity-of-scripts

2、异步操作同一个代码块时,比如多个队列,恰巧有两个一起被触发,会在mysql读取到脏数据,虽然在laravel中可以使用lockForUpdate避免,但是若有很多并发队列,会造成这条记录一直处于被锁的状态,以至于其他地方无法正常获取数据。因为如果get()和set的操作不是原子性的,会造成很小概率的,第二条队列在第一条set()之前get()了,导致无法锁上,所以采用以下方式加锁。

private function getLock($key)
    {
        // 解决并发导致的Jpush重复发送
        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);
    }

3、今天又看到laravel官方文档
https://learnku.com/docs/laravel/5.7/queues/2286#max-job-attempts-and-timeout
中使用的 频率限制 的框架封装的 funnel 方法 ,是一个道理,都是循环获取锁进行sleep操作。

上一篇下一篇

猜你喜欢

热点阅读