我正在用PHP編寫一個彩票程序,因爲這個程序會有很大的併發請求,每個獎項的數量都有限,在這個例子中有10個。我不想看到任何獎金超過股票。所以我把整個邏輯放在Redis的事務中(我使用predis(https://github.com/nrk/predis)作爲我的PHP redis客戶端),但它不起作用,經過10次以上的請求後,我發現數據庫中有10多條記錄我無法理解。有誰知道原因?非常感謝您的解釋,謝謝!爲什麼我無法在Redis交易中獲得緩存數據?
這裏是我的PHP代碼:
閱讀Redis的的交易文件後$this->load->model('Lottery_model');
$money = $this->_get_lottery();//which prize do you get
if($money > 0){
$key = $this->_get_sum_key($money);
$dbmodel = $this->Lottery_model;
// Executes a transaction inside the given callable block:
$responses = $redis->transaction(function ($tx) use ($key, $money, $dbmodel){
$qty = intval($tx->get($key));
if($qty < 10){
//not exceed the stock limit
$dbmodel->add($customer, $money); // insert record into db
$tx->incr($key);
}else{
log_message('debug', $money . ' dollar exceed the limit');
}
});
}else{
log_message('debug', 'you are fail');
}
,我知道以上代碼的使用是完全錯誤的。然後我將它修改爲低於版本,使用樂觀鎖定和檢查和設置。
$options = array(
'cas' => true, // Initialize with support for CAS operations
'watch' => $key, // Key that needs to be WATCHed to detect changes
'retry' => 3,
);
try{
$responses = $redis->transaction($options, function ($tx) use ($key, $money, $username, $dbmodel, &$qty){
$qty = intval($tx->get($key));
if($qty < 10){
$tx->multi();
$tx->incr($key);
$dbmodel->add($username, $money);// insert into mysql db
}else{
log_message('debug', $money . ' dollar exceed the limit');
}
});
}catch(PredisException $e){
log_message('debug', 'redis transaction failed');
}
但問題是,在數據庫記錄的數量超過該獎項的限制,保存在Redis的總數量不會。解決這類問題的通用解決方案是什麼?在這種情況下,我必須鎖定INNodb表嗎?
非常感謝!我已閱讀您提到的文檔。我知道Redis交易現在如何運作。所以我用CAS解決方案用樂觀鎖定改變了我的代碼,現在qty的值是正確的,最終達到10,但數據庫中的記錄仍然遠遠超過10.你知道爲什麼嗎? –
對不起 - 我不明白這個問題。 –
對不起,我用第二版的源代碼更新了我的原始問題。新的問題就在那裏。謝謝! –