Redis 应用之分布式锁

原文连接 https://www.gwalker.cn/article-1482d08g8952e122a6044ab1c87bdd95.html

设计思路

任何一个请求进来时;先向redis申请"加锁操作"
若加锁成功则进行执行业务逻辑,执行完毕之后,释放锁;否则 不执行业务逻辑。

设计细节

1 加锁时设置过期时间;这样可保证运行中间出现异常,没有进行到锁删除操作。一定时间之后,锁会自动释放,防止死锁。
2 释放锁操作,判断锁是否是自己加的。若是自己加的,才可以进行释放操作。防止锁超时,释放的为其他请求生成的锁。

实现细节

1 因为php-redis扩展提代的方法为 public function set( $key, $value, $timeout = 0 ) {},
实现不了 SET key value [EX seconds] [PX milliseconds] [NX|XX] 这样的原生命令。所以只能使用$redis->rawCommand()方法执行,原生redis指令。

2 释放锁,原子性操作,需要判断锁为自己设定的,才可进行删除。redis没有提供这样的原子性操作命令。采取$redis->eval()发送lua脚本去实现。

// 分布式锁
$redis = new Redis();
$redis->connect('172.17.0.3', 6379);

// 锁名
$key = 'lock:xxx';

// 锁值
$tag = uniqid();

// 加锁 且锁的有效时间为5秒,NX(意为 NOT EXISTS)如果锁不存在,才可设置成功。
$re = $redis->rawCommand('set', $key, $tag, 'EX', 5, 'NX');

if(!$re){
    die('系统繁忙,请稍后重试');
}

// do_something(); // 待执行的业务逻辑

// 释放锁
$luaScript =<<
                    
                    

你可能感兴趣的:(Redis 应用之分布式锁)