這裡我們主要利用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
)}
ab測試模擬併發,發現庫存是正確的。
mysql> select * fromstorage;
+----+--------+
| 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
public
static
function getinstance()
return self::$_instance = new
self();
}/**
* @function 加鎖
* @param $key 鎖名稱
* @param $exptime 過期時間
*/public function set
($key,$exptime)
else
return $this->_redis->setnx($key,time()+$exptime);}}
/*** @param $key 解鎖
*/public
function del($key)
}$pdo = new pdo('
mysql:host=127.0.0.1;dbname=test
', '
root
', '
root');
$lockobj =lock::getinstance();
//判斷是能加鎖成功
if($lock = $lockobj->set('
storage
',10
)) }
//解鎖
$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
鎖是可以有效的處理高併發的。
這裡在加鎖的時候其實是可以不需要判斷過期時間的,這裡我們為了避免造成死鎖,所以加乙個過期時間的判斷。當過期的時候主動刪除該鎖。
利用Redis鎖解決高併發問題
這裡我們主要利用redis的setnx的命令來處理高併發。setnx 有兩個引數。第乙個引數表示鍵。第二個引數表示值。如果當前鍵不存在,那麼會插入當前鍵,將第二個引數做為值。返回 1。如果當前鍵存在,那麼會返回0。建立庫存表 create tablestorage idint 11 unsigned...
利用Redis鎖解決併發問題
用redis處理高併發是個很常見的方式,因為redis的訪問效率很高 直接訪問記憶體 一般我們會用來處理 一瞬間的併發量。那如果要使用redis來進行高併發問題的解決的話,應注意以下幾點 1 首先我們要先知道,我們在儲存時,應使用redis的setnx方法,不應該使用set方法,因為setnx擁有原...
Redis高併發問題
商品搶購秒殺等活動 使用redis列表結構實現佇列資料結構,強拆的用rpush入隊,再用lpop出隊.redis宕機或者連線不上 解決方法 配置主從複製,配置哨兵模式,一旦發現主機宕機,讓下乙個從機當做主機。最壞的情況,只能關閉redis連線,去往資料庫連線。但由於資料量大,這樣sql資料庫也會宕掉...