鍍金池/ 問答/人工智能  PHP  HTML/ php+redis搶購功能,并發(fā)問題

php+redis搶購功能,并發(fā)問題

今天嘗試寫并發(fā)搶購功能,再網上找了相關資料后,實現(xiàn)了如下:

<?php
#開始搶購,檢測庫存
$inventoryData = $this->redis->get($inventoryKey);
if ($inventoryData == null) {
    //庫存不足
    return '-1';
}

#解析json
$inventoryData = json_decode($inventoryData, true);
#檢測庫存
if ($inventoryData['inventory'] == 0) {
    //庫存不足
    return '-1';
}
//開啟事務
$this->redis->watch($inventoryKey);
//事務開始
$this->redis->multi();
//將搶購數(shù)據(jù)加入redis
$this->redis->lPush('kill_goods_' . $data['goods_id'], json_encode($data));
$goodsData = ['id' => $data['goods_id'], 'inventory' => $inventoryData['inventory'] - 1];
$this->redis->set($inventoryKey, json_encode($goodsData));
$result = $this->redis->exec();
if ($result) {
    file_put_contents('1.txt', $inventoryData['inventory'] . PHP_EOL, FILE_APPEND);
    return 1;
}
return '-1';

經過并發(fā)測試:始終都會有重復的,請各位大佬講解講解

回答
編輯回答
怣痛

庫存做原子自減

2017年3月22日 16:02
編輯回答
巷尾

我覺得這個問題可以不用事務解決的啊,還有原子自減string也是可以減為負的啊,難道負的庫存也合理么?這個東西用list完美解決,根本不需要事務啊

2017年2月13日 20:41
編輯回答
六扇門

用原子自減只能解決redis本身內的并發(fā)問題,但程序中并發(fā)處理也有問題。像Nine所說的一樣,會存在多條訪問全都通過前面的檢測。必須在php程序內做原子限制。像一些高并發(fā)下的活動頁面,根據(jù)實際業(yè)務做法有很多。像樓主的業(yè)務邏輯,我覺得首先可以讓庫存的key自減,然后直接根據(jù)返回key的值直接判斷是否小于或者等于0。

2018年9月16日 12:46
編輯回答
離魂曲

這種方式其實并沒有解決并發(fā)的問題,舉個簡單的例子:我們假設現(xiàn)在還剩下最后一個產品,兩個用戶進來之后,都通過了"庫存檢測"這道門檻,是不是存在著這樣一種可能,A用戶先開啟并完成事務,B緊接著再完成?

2017年12月31日 18:32