首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么我不能在Redis的事务中获得缓存的数据?

为什么我不能在Redis的事务中获得缓存的数据?
EN

Stack Overflow用户
提问于 2017-03-07 08:20:49
回答 1查看 700关注 0票数 1

我正在用PHP编写一个彩票程序,因为这个程序的并发请求会很大,我每个奖品的数量都是有限的,在本例中为10。我不想看到任何奖金超过股票。所以我把整个逻辑放在redis的事务中(我使用predis(https://github.com/nrk/predis)作为我的predis客户端),但是它不能工作,在对这个程序的请求超过10次之后,我在数据库中发现了超过10条我无法理解的记录。有谁知道原因吗?非常感谢您的解释,谢谢!

以下是我的PHP代码:

代码语言:javascript
复制
$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事务的文档之后,我知道上述代码的使用是完全错误的。然后,我将其修改为下面的版本,使用乐观锁和检查和设置。

代码语言:javascript
复制
$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表吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-03-07 10:26:56

您需要了解Redis事务是如何工作的-简而言之,所有生成事务的命令都由客户端缓冲(在您的情况下是predis),然后立即触发到服务器。您的代码试图在执行事务之前使用读取请求(get)的结果。有关更多细节,请参阅文档:https://redis.io/topics/transactions

要么读取事务外部的qty,然后使用WATCH来防止相互竞争的更新,要么将整个逻辑移动到Lua脚本。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42643380

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档