PHP 实现一个可用的redis 事务锁, 解决并发问题

 

调用代码

require("./redis_lock/RedisLock.php");


$redis_lock = new RedisLock("127.0.0.1", 6379);

$name = "goods";
$id = 100002;
$lock_name = $name.$id;

$redis_lock -> setLockName($lock_name,$id);
$redis_lock -> exe(function (){

    echo "我抢到了\n";

},function (){


    echo "我没有抢到\n";
});
<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/9/17
 * Time: 14:04
 * Desc: redis 分布式事务锁, 非原子性操作
 */

class RedisLock
{

    private $redis = null;

    private $lock_name = "";
    private $check_flag = "";

    /**
     * RedisLock constructor.
     * @param $host string
     * @param $port string|int
     * @param string $pass
     */
    public function __construct($host,$port,$pass = "")
    {
        $redis = new Redis();
        $redis->connect($host, $port);
        if (!empty($pass)){
            $redis->auth($pass);
        }
        if (!$redis){
            echo "redis create error!";
            exit(1);
        }
        $this -> redis = $redis;
    }

    /**
     * @param $name string 锁名称
     * @param string $check_flag    校验参数
     */
    public function setLockName($name, $check_flag = "1"){
        $this -> lock_name = $name;
        $this -> check_flag = $check_flag;
    }


    /**
     * @param $callback
     * @param $errCallback
     * @param int $timeout  超时时间
     * @param int $overCount    尝试次数
     */
    public function exe($callback, $errCallback, $timeout = 10, $overCount = 3){

        $count = 0;
        do {  
            
            $key = $this -> lock_name;
            $value = $this -> check_flag;
            $redis = $this -> redis;

            $isLock = $redis -> setnx($key, $value);
            $redis -> expire($key,$timeout);

            if ($isLock) {
                if ($redis -> get($key) == $value) {  
                    // 执行内部代码
                    $callback();
                    // 释放锁
                    $this -> del_lock();
                    break;//执行成功删除key并跳出循环
                }
            } else {
                $count++;
                if ($count > $overCount){
                    $errCallback();
                    break;
                }
                sleep(1); //睡眠,降低抢锁频率
            }
        } while(!$isLock);
    }

    /**
     *  删除锁
     */
    public function del_lock(){
        $this -> redis -> del($this -> lock_name);
    }
}

参考教程

http://ukagaka.github.io/php/2017/09/21/redisLock.html

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值