PHP菜鸟博客_共同学习分享PHP技术心得【PHP爱好者】
php+redis实现分布式锁
2022-12-12 菜鸟站长


同一套代码部署再多台服务器,不同服务器多个线程同时执行某一个方法,让执行动作排序,保证线程安全。



<?php



header("Access-Control-Allow-Origin:*");

header('Access-Control-Allow-Methods:*');  

#分布式锁

class RedisLock {

    private $redis;

    #存储redis对象

    /**

     * @desc 构造函数

     * 

     * @param $host string | redis主机

     * @param $port int | 端口

    */

    public function __construct($host,$port=6379,$pass='') {

        $this->redis = new Redis();

        $this->redis->connect($host,$port);

        if(!!$pass){

            $this->redis->auth($pass); //密码验证 

        }

      

    }

    /**

     * @desc 加锁方法

     *

     * @param $lockName string | 锁的名字

     * @param $timeout int | 锁的过期时间

     * @return 成功返回identifier/失败返回false

    */

    public function getLock($lockName, $timeout=10) {

        $identifier=uniqid();

        #获取唯一标识符

        $timeout = intval($timeout);

        #确保是整数

        $end=time()+$timeout;

        #循环获取锁

        while(time()<$end) {

            #查看$lockName是否被上锁,为$lockName设置过期时间,防止死锁

            if($this->redis->set($lockName, $identifier, array('nx', 'ex' => $timeout))) {

                return $identifier;

            }

            usleep(0.001);

            #停止0.001ms

        }

        return false;

    }

    /**

     * @desc 释放锁

     *

     * @param $lockName string | 锁名

     * @param $identifier string | 锁的唯一值

     *

     * @param bool

    */

    public function releaseLock($lockName,$identifier) {

        // 判断是锁有没有被其他客户端修改

        if($this->redis->get($lockName)==$identifier) {

            $this->redis->multi();

            $this->redis->del($lockName);

            #释放锁

            $this->redis->exec();

            return true;

        } else {

            return false;

            #其他客户端修改了锁,不能删除别人的锁

        }

    }

}



header("content-type: text/html;charset=utf8;");

$rLock = new RedisLock('127.0.0.1','6379','*******');

$start=time();

$lockName = "lock:12";

$identifier = $rLock->getLock($lockName);

if($identifier===false) {

    var_dump($identifier);

    exit("失败了");

}



//模拟业务逻辑处理时长开始

sleep(4);



//模拟业务逻辑处理时长结束





$rLock->releaseLock($lockName,$identifier);

$end=time();

echo "this OK<br/>";

echo "执行时间为:".($end-$start);

?>

发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容