0

背景

我需要一种在 REDIS 中创建事务的方法,如果一个命令失败,我需要整个事务失败/回滚。

我之前尝试过询问一次(如果其中一个命令不起作用,REDIS-pipeline 不会失败

但也许我没有问清楚,或者我的问题的措辞中丢失了一些东西。或者我没看懂答案。但无论如何,我一直在做更多的研究,似乎 REDIS 确实通过 MULTI 和 EXEC 命令进行了事务。在我的例子中,由于我使用的是 pyredis,我可以创建一个将参数“transaction”设置为 True 的管道。

代码

为了更好地理解事务和管道的工作原理,我编写了代码来“模拟”失败,以证明我的事务中的命令正在回滚。所以这就是我的烧瓶应用程序中的内容:

@application.route("/test/transactions/<int:trigger>")
def test_transactions(trigger):
    try:
        logging.info('test transactions triggered')
        r = redis.Redis(connection_pool=POOL)
        p = r.pipeline(transaction=True)
        p.hmset('multitest', {'thefield':'thevalue'})
        if trigger==1:  
            assert 1==0, "trigger enabled. this will cause failure."
        p.hmset('multitest2', {'a':'b'})
        retval = p.execute()
        logging.info(retval)
        return "keys created"
    except Exception as e:
        logging.error(e)
        return "keys not created"

当我传入 0 作为触发器时,它不会“失败”,因此系统会创建两个哈希值。当我设置触发器时,它似乎表现正确,因为我在数据库中没有任何哈希值。

问题

  1. 这是一个很好的测试吗?已经证明交易有效?如果没有,你能建议一个更好的测试吗?

  2. 在我的真实代码中,我计划检查 retval 的内容(顺便说一下,它看起来像这样: [0,0] 如果什么都没做,或者 [1, 1] 如果我确实添加/删除了一些东西.) 如果我期待一个 [1,1] 并且我得到不同的东西,我将假设事务失败并且让该方法只返回一个 false。有一个更好的方法吗?

提前感谢您的时间和投入。

4

1 回答 1

0

Redis 的事务没有“回滚”能力——一旦你调用p.execute()其中的操作,它就会被执行。您可以在执行前随时通过调用取消交易p.discard()

当您丢弃事务时,它不会回滚,因为实际上没有执行任何操作。

@application.route("/test/transactions/<int:trigger>")
def test_transactions(trigger):
    try:
        logging.info('test transactions triggered')
        r = redis.Redis(connection_pool=POOL)
        p = r.pipeline(transaction=True)
        p.hmset('multitest', {'thefield':'thevalue'})
        if trigger==1:  
            p.discard()
            return "discarded"
        else:
            p.hmset('multitest2', {'a':'b'})
            retval = p.execute()
            logging.info(retval)
            return "keys created"
    except Exception as e:
        logging.error(e)

注意:我没有完全得到你的代码——你可以先检查一下trigger,然后跳过交易尝试。

于 2019-01-19T12:40:52.250 回答