四时宝库

程序员的知识宝库

php+redis实现分布式锁(php redis 分布式锁)

 /**
 * 添加锁
 * @param unknown $key_name 键的名称
 * @param unknown $uniqid 唯一值
 * @param unknown $key_expire 键的过期时间
 * @return int 0失败,1成功
 */
 static function lock($key_name, $uniqid, $key_expire)
 {
 $lua_script = <<<EOF
 local flag = redis.call("setnx", KEYS[1], ARGV[1])
 if tonumber(flag) > 0 then
 redis.call('expire', KEYS[1], ARGV[2])
 return redis.call('get', KEYS[1])
 else
 return 0
 end
EOF;
 $redis = MyRedisService::getInstance();
 return $redis->eval($lua_script, 1, $key_name, $uniqid, $key_expire); 
 }
 
 /**
 * 释放锁
 * @param unknown $key_name 键名称
 * @param unknown $key_val 键值校验
 * @return int 0失败,1成功
 */
 static function unlock($key_name, $key_val)
 {
 $lua_script = <<<EOF
 local lockKey = redis.call('get', KEYS[1])
 local lk = ARGV[1]
 if lockKey == lk then
 return redis.call('del', KEYS[1]) 
 else
 return 0
 end
EOF;
 $redis = MyRedisService::getInstance();
 return $redis->eval($lua_script, 1, $key_name, $key_val);
 }
 
 
 public function index()
 {
 //键名
 $key_name = 'index';
 
 //key过期时间
 $key_expire = 1;
 
 //键的唯一标识
 $uniqid = uniqid(null, true).microtime();
 
 //加锁
 $key_val = self::lock($key_name, $uniqid, $key_expire);
 
 //加锁成功,开始执行以下代码
 if($key_val > 0)
 {
 try
 {
 $redis = MyRedisService::getInstance();
 //从数据库或者redis中得到库存
 $store_nums = $redis->get("store_nums");
 if($store_nums > 0)
 {
 $redis->decrby("store_nums", 1);
 echo "去库存成功,剩余:".$redis->get('store_nums')."<br>";
 }
 else
 {
 echo "库存不足<br>";
 }
 }
 catch (\Exception $e)
 {
 //如果代码抛出异常,则直接删除key
 $redis->del($key_name);
 }
 }
 
 //释放锁
 $res = self::unlock($key_name, $key_val);
 
 //如果释放锁失败,则直接手动删除key
 if(intval($res) === 0)
 {
 $redis->del($key_name);
 }
 }

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接