单机Redis实现分布式锁

  1 <?php
  2 /**
  3  * Class redis_lock
  4  *
  5  * 单机redis 分布式锁
  6  */
  7 
  8 class redis_lock
  9 {
 10     public $redis;
 11 
 12     public function __construct()    //连接Redis服务器
 13     {
 14         $this->redis = new \redis();
 15         $this->redis->connect('127.0.0.1', 6379);
 16 //      $this->redis->auth('123456');
 17 //      $this->redis->select(12);
 18     }
 19 
 20     /**
 21      * 单台Redis设置锁
 22      *
 23      * @param string $key
 24      * @param int $expire
 25      * @return bool
 26      */
 27     public function setLock($key, $expire = 10)
 28     {
 29         $res = $this->check_key($key);
 30         if (!$res) {
 31             return false;
 32         }
 33         $res = $this->check_expire($expire);
 34         if (!$res) {
 35             return false;
 36         }
 37         $res = $this->redis->set('Redis:Lock:' . $key, time() + $expire, ['nx', 'ex' => $expire]);
 38         if (!$res) {
 39             return false;
 40         }
 41         return true;
 42     }
 43 
 44     /**
 45      * 校验有效期
 46      *
 47      * @param mixed $expire
 48      * @return int
 49      */
 50     public function check_expire($expire)
 51     {
 52         if (!is_numeric($expire)) {
 53             return false;
 54         }
 55         return true;
 56     }
 57 
 58     /**
 59      * 校验$key
 60      *
 61      * @param mixed $key
 62      * @return bool
 63      */
 64     public function check_key($key)
 65     {
 66         if (!is_string($key) && !is_int($key)) {
 67             return false;
 68         }
 69         //允许数字、英文字符、下划线、英文冒号
 70         preg_match('/^[\w\:]*+$/', $key, $p_key);
 71         if (!isset($p_key[0]) || $p_key[0] != $key) {
 72             return false;
 73         }
 74         return true;
 75     }
 76 
 77     /**
 78      * 单台Redis设备锁,如果不能进入将等待
 79      *
 80      * @param string $key
 81      * @param int $expire
 82      * @param int $wait_seconds
 83      * @return bool
 84      */
 85     public function setLockAndWait($key, $expire = 10, $wait_seconds = 10)
 86     {
 87         /*如果是webserver,并且session服务器是文件或者memcache,最好加上这一行
 88         也可以用session_commit(),解除session锁。如果session服务器是redis,就不用了*/
 89         session_write_close();
 90         $time = time();
 91         $wait_time = $time + $wait_seconds;
 92         while (true) {
 93             $res = $this->setLock($key, $expire);
 94             if ($res) {
 95                 return $res;
 96             }
 97             if ($time >= $wait_time) {
 98                 return false;
 99             }
100             usleep(500);    //等待微妙数
101         }
102     }
103 
104     /**
105      * 单台Redis删除锁
106      *
107      * @param string $key
108      * @return bool
109      */
110     public function delLock($key)
111     {
112         $res = $this->redis->del($key);
113         if ($res === false) {
114             return false;
115         }
116         return true;
117     }
118 }
119 
120 $redis = new redis_lock();
121 $res = $redis->setLock('lock');
122 $redis->delLock('lock');
123 var_dump($res);125 ?>

 

上一篇:redis理论部分


下一篇:并发编程9-并发容器