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操作。
网友评论