国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 語言 > PHP > 正文

php 使用redis鎖限制并發訪問類示例

2024-05-04 23:51:45
字體:
來源:轉載
供稿:網友

本文介紹了php 使用redis鎖限制并發訪問類,并詳細的介紹了并發訪問限制方法。

1.并發訪問限制問題

對于一些需要限制同一個用戶并發訪問的場景,如果用戶并發請求多次,而服務器處理沒有加鎖限制,用戶則可以多次請求成功。

例如換領優惠券,如果用戶同一時間并發提交換領碼,在沒有加鎖限制的情況下,用戶則可以使用同一個換領碼同時兌換到多張優惠券。

偽代碼如下:

if A(可以換領)
    B(執行換領)
    C(更新為已換領)
D(結束)

如果用戶并發提交換領碼,都能通過可以換領(A)的判斷,因為必須有一個執行換領(B)后,才會更新為已換領(C)。因此如果用戶在有一個更新為已換領之前,有多少次請求,這些請求都可以執行成功。

2.并發訪問限制方法

使用文件鎖可以實現并發訪問限制,但對于分布式架構的環境,使用文件鎖不能保證多臺服務器的并發訪問限制。

Redis是一個開源的使用ANSI C語言編寫、支持網絡、可基于內存亦可持久化的日志型、Key-Value數據庫,并提供多種語言的API。

本文將使用其setnx方法實現分布式鎖功能。setnx即Set it N**ot eX**ists。

當鍵值不存在時,插入成功(獲取鎖成功),如果鍵值已經存在,則插入失敗(獲取鎖失敗)

RedisLock.class.PHP

<?php/** * Redis鎖操作類 * Date:  2016-06-30 * Author: fdipzone * Ver:  1.0 * * Func: * public lock  獲取鎖 * public unlock 釋放鎖 * private connect 連接 */class RedisLock { // class start  private $_config;  private $_redis;  /**   * 初始化   * @param Array $config redis連接設定   */  public function __construct($config=array()){    $this->_config = $config;    $this->_redis = $this->connect();  }  /**   * 獲取鎖   * @param String $key  鎖標識   * @param Int   $expire 鎖過期時間   * @return Boolean   */  public function lock($key, $expire=5){    $is_lock = $this->_redis->setnx($key, time()+$expire);    // 不能獲取鎖    if(!$is_lock){      // 判斷鎖是否過期      $lock_time = $this->_redis->get($key);      // 鎖已過期,刪除鎖,重新獲取      if(time()>$lock_time){        $this->unlock($key);        $is_lock = $this->_redis->setnx($key, time()+$expire);      }    }    return $is_lock? true : false;  }  /**   * 釋放鎖   * @param String $key 鎖標識   * @return Boolean   */  public function unlock($key){    return $this->_redis->del($key);  }  /**   * 創建redis連接   * @return Link   */  private function connect(){    try{      $redis = new Redis();      $redis->connect($this->_config['host'],$this->_config['port'],$this->_config['timeout'],$this->_config['reserved'],$this->_config['retry_interval']);      if(empty($this->_config['auth'])){        $redis->auth($this->_config['auth']);      }      $redis->select($this->_config['index']);    }catch(RedisException $e){      throw new Exception($e->getMessage());      return false;    }    return $redis;  }} // class end?>

demo.php

<?phprequire 'RedisLock.class.php';$config = array(  'host' => 'localhost',  'port' => 6379,  'index' => 0,  'auth' => '',  'timeout' => 1,  'reserved' => NULL,  'retry_interval' => 100,);// 創建redislock對象$oRedisLock = new RedisLock($config);// 定義鎖標識$key = 'mylock';// 獲取鎖$is_lock = $oRedisLock->lock($key, 10);if($is_lock){  echo 'get lock success<br>';  echo 'do sth..<br>';  sleep(5);  echo 'success<br>';  $oRedisLock->unlock($key);// 獲取鎖失敗}else{  echo 'request too frequently<br>';}?>

測試方法:

打開兩個不同的瀏覽器,同時在A,B中訪問demo.php

如果先訪問的會獲取到鎖

輸出

get lock success
do sth..
success

另一個獲取鎖失敗則會輸出request too frequently

保證同一時間只有一個訪問有效,有效限制并發訪問。

為了避免系統突然出錯導致死鎖,所以在獲取鎖的時候增加一個過期時間,如果已超過過期時間,即使是鎖定狀態都會釋放鎖,避免死鎖導致的問題。
源碼下載地址:點擊查看


注:相關教程知識閱讀請移步到PHP教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

主站蜘蛛池模板: 额尔古纳市| 永寿县| 萨嘎县| 松溪县| 达州市| 潜江市| 安阳县| 南川市| 神池县| 彰武县| 安陆市| 望城县| 江门市| 荣成市| 怀远县| 廊坊市| 平顺县| 抚远县| 辽阳县| 冕宁县| 长丰县| 武城县| 金川县| 清水河县| 沙洋县| 南皮县| 汤原县| 穆棱市| 广饶县| 韶关市| 冕宁县| 枝江市| 昌乐县| 仪征市| 高安市| 泽州县| 昌图县| 长兴县| 陆河县| 屯门区| 长春市|