2017-03-07 88 views
1

我正在用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表嗎?

回答

1

您需要了解Redis事務是如何工作的 - 簡而言之,所有生成事務的命令都由客戶端緩衝(在您的情況下爲predis),然後一次性釋放到服務器。您的代碼嘗試在執行事務之前使用讀取請求的結果(get)。請參考文檔瞭解更多信息:https://redis.io/topics/transactions

無論是讀取事務之外的qty,並使用WATCH,以防止競爭的更新,或移動的全部這樣的邏輯來一個Lua腳本。

+0

非常感謝!我已閱讀您提到的文檔。我知道Redis交易現在如何運作。所以我用CAS解決方案用樂觀鎖定改變了我的代碼,現在qty的值是正確的,最終達到10,但數據庫中的記錄仍然遠遠超過10.你知道爲什麼嗎? –

+0

對不起 - 我不明白這個問題。 –

+0

對不起,我用第二版的源代碼更新了我的原始問題。新的問題就在那裏。謝謝! –

相關問題