夜间模式
开
关
首页
工具箱
Redis 应用之分布式锁
原创
作者:巩文
2018.03.05 14:51
热度:2537
#### 设计思路 任何一个请求进来时;先向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 =<<