如何利用Redis鎖解決高並發問題

來源:互聯網
上載者:User
高並發問題是我們經常可以遇到的問題,那麼該如何解決高並發這個問題呢?本篇文章介紹的內容就是利用Redis鎖解決高並發問題,一起來看看吧。

這裡我們主要利用Redis的setnx的命令來處理高並發。

setnx 有兩個參數。第一個參數表示鍵。第二個參數表示值。如果當前鍵不存在,那麼會插入當前鍵,將第二個參數做為值。返回 1。如果當前鍵存在,那麼會返回0。

建立庫存表

CREATE TABLE `storage` (  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,  `number` int(11) DEFAULT NULL,  PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1

設定初始庫存為10

建立訂單表

CREATE TABLE `order` (  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,  `number` int(11) DEFAULT NULL,  PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1

測試不用鎖的時候

$pdo = new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'root');$sql="select `number` from  storage where id=1 limit 1";$res = $pdo->query($sql)->fetch();$number = $res['number'];if($number>0){    $sql ="insert into `order`  VALUES (null,$number)";    $order_id = $pdo->query($sql);    if($order_id)    {        $sql="update storage set `number`=`number`-1 WHERE id=1";        $pdo->query($sql);    }}

ab測試類比並發,發現庫存是正確的。

mysql> select * from storage;+----+--------+| id | number |+----+--------+|  1 |      0 |+----+--------+1 row in set (0.00 sec)

在來看訂單表

mysql> select * from `order`;+----+--------+| id | number |+----+--------+|  1 |     10 ||  2 |     10 ||  3 |      9 ||  4 |      7 ||  5 |      6 ||  6 |      5 ||  7 |      5 ||  8 |      5 ||  9 |      4 || 10 |      1 |+----+--------+10 rows in set (0.00 sec)

發現存在幾個訂單都是操作的同一個庫存資料,這樣就可能引起超賣的情況。

修改代碼加入redis鎖進行資料控制

<?php/** * Created by PhpStorm. * User: daisc * Date: 2018/7/23 * Time: 14:45 */class Lock{    private static $_instance ;    private   $_redis;    private function __construct()    {        $this->_redis =  new Redis();        $this->_redis ->connect('127.0.0.1');    }    public static function getInstance()    {        if(self::$_instance instanceof self)        {            return self::$_instance;        }        return self::$_instance = new  self();    }    /**     * @function 加鎖     * @param $key 鎖名稱     * @param $expTime 到期時間      */    public function set($key,$expTime)    {        //初步加鎖        $isLock = $this->_redis->setnx($key,time()+$expTime);        if($isLock)        {            return true;        }        else        {            //加鎖失敗的情況下。判斷鎖是否已經存在,如果鎖存在切已經到期,那麼刪除鎖。進行重新加鎖            $val = $this->_redis->get($key);            if($val&&$val<time())            {                $this->del($key);            }            return  $this->_redis->setnx($key,time()+$expTime);        }    }    /**     * @param $key 解鎖     */    public function del($key)    {        $this->_redis->del($key);    }}$pdo = new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'root');$lockObj = Lock::getInstance();//判斷是能加鎖成功if($lock = $lockObj->set('storage',10)){    $sql="select `number` from  storage where id=1 limit 1";    $res = $pdo->query($sql)->fetch();    $number = $res['number'];    if($number>0)    {        $sql ="insert into `order`  VALUES (null,$number)";        $order_id = $pdo->query($sql);        if($order_id)        {            $sql="update storage set `number`=`number`-1 WHERE id=1";            $pdo->query($sql);        }    }    //解鎖    $lockObj->del('storage');}else{    //加鎖不成功執行其他動作。}

再次進行ab測試,查看測試結果

mysql> select * from `order`;+----+--------+| id | number |+----+--------+|  1 |     10 ||  2 |      9 ||  3 |      8 ||  4 |      7 ||  5 |      6 ||  6 |      5 ||  7 |      4 ||  8 |      3 ||  9 |      2 || 10 |      1 |+----+--------+10 rows in set (0.00 sec)

發現訂單表沒有操作同一個庫存資料的情況。所以利用redis鎖是可以有效處理高並發的。

這裡在加鎖的時候其實是可以不需要判斷到期時間的,這裡我們為了避免造成死結,所以加一個到期時間的判斷。當到期的時候主動刪除該鎖。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.