Я пишу лотерейную программу на PHP, потому что для этой программы будет большой одновременный запрос, у меня ограниченное количество каждого приза, 10 в этом примере. Я не хочу, чтобы какой-либо приз превышал запас. поэтому я помещаю всю логику в транзакцию Redis (я использую predis(https://github.com/nrk/predis) в качестве моего PHP-клиента Redis), но он не работает, после более чем 10 запросов к этой программе я нашел более 10 записей в базе данных, которые я не мог понять. может кто знает причину? очень ценю ваше объяснение, спасибо!
вот мой PHP-код:
$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');
}
после прочтения документации о транзакции Redis я знаю, что использование приведенного выше кода совершенно неверно. затем я изменил его до версии ниже, используя оптимистическую блокировку и проверку и установку.
$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 в этом случае?