Background
I need a way to create a transaction in REDIS, where if one command fails, I need the entire transaction to fail / rollback.
I tried asking once before (REDIS- pipeline doesnt fail if one of the commands don't work)
But perhaps I didn't ask clearly or something got lost in the wording of my question. Or I didn't understand the answer. But in any case, I've been doing more research and it seems that REDIS does have transactions via the MULTI and EXEC commands. And in my case, since I'm using pyredis, I can create a pipeline with the parameter "transaction" set to True.
Code
To better understand how transactions and pipelines work, I wrote code to "simulate" a failure to prove that commands in my transaction are rolling back. So this is what I have in my my flask app:
@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"
When i pass in a 0 as the trigger, it doesn't "fail" so the system creates both hashes. When I do set the trigger, it seems to behaving correctly because I don't have any hashes in the database.
Questions
is this a good test? have proven that transactions work? If not can you suggest a better to test?
In my real code, I'm plannning to check the contents of retval (which, by the way would look something like this: [0,0] if nothing was done, or [1, 1] if I did add / delete something.) If I'm expecting a [1,1] and i get back something different, i'm going to assume that transaction failed and have the method just return a false. Is there a better way to do this?
Thanks in advance for your time and input.
答案 0 :(得分: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
,然后跳过尝试进行交易。