php - 为什么我在 Redis 事务中获取不到缓存数据?

标签 php transactions redis predis

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

最佳答案

您需要了解 Redis 事务的工作原理 - 简而言之,所有进行事务的命令都由客户端(在您的情况下为 predis)进行缓冲,然后一次性全部发送到服务器。您的代码尝试在事务执行之前使用读取请求 (get) 的结果。更多详细信息请参阅文档:https://redis.io/topics/transactions

要么读取交易外的qty,然后使用WATCH以防止竞争更新,或将此逻辑整个移动到 Lua 脚本。

关于php - 为什么我在 Redis 事务中获取不到缓存数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42643380/

相关文章:

caching - Redis 将数据存储在哪里

php - 在 Laravel 中关闭 Redis 进行测试

php - 被黑了,这段代码是做什么的?

php - 如何将总和值(使用 PHP 来自 MySQL)放在演示文稿表上方?

sql-server - SQL Server - 设置事务超时/自动回滚

transactions - Servicestack.redis 事务和哈希

php - 左连接不显示产品

php - PHP 中 0 到 1 之间的随机 float

java - 如何回滚第一个事务而不回滚新事务?

redis - 如何使用 StackExchange.Redis 客户端在特定的 redis 服务器上设置?