天天看點

簡短截說闡述redis中事務(Redis Transactions)的使用

作者:劉悅技術分享

我們知道,在關系型資料庫中,比如mysql,如果要使用事務,首先向資料庫伺服器發送 BEGIN ,然後執行各個互相一緻的寫操作和讀操作,最後,使用者可以選擇發送 COMMIT 來确認之前所做的修改,或者發送 ROLLBACK 來放棄那些修改。

同樣, Redis 中也有簡單的方法處理一連串互相一緻的讀操作和寫操作。首先是以 MULTI 指令開始事務,後續跟着一連串指令,最後以 EXEC 結束事務或者以 DISCARD 指令撤銷所有指令并結束事務。

但是redis事務和mysql事務最重要的一點差別是,redis事務不管指令正确或者錯誤,都會執行,中途遇見錯誤指令也會繼續執行後面的指令,Redis并沒有像mysql那樣的事務復原機制。mysql事務中如果執行過程中發生了錯誤不僅後面的sql語句不會執行,還會進行資料復原,這是二者事務的最大差別。Redis的事務出錯需要開發人員自己進行資料復原等操作。

在翻閱了redis官方手冊以後,官方對此的解釋是:If you have a relational databases background, the fact that Redis commands can fail during a transaction, but still Redis will execute the rest of the transaction instead of rolling back, may look odd to you. However there are good opinions for this behavior:

Redis commands can fail only if called with a wrong syntax (and the problem is not detectable during the command queueing), or against keys holding the wrong data type: this means that in practical terms a failing command is the result of a programming errors, and a kind of error that is very likely to be detected during development, and not in production.

Redis is internally simplified and faster because it does not need the ability to roll back.

An argument against Redis point of view is that bugs happen, however it should be noted that in general the roll back does not save you from programming errors. For instance if a query increments a key by 2 instead of 1, or increments the wrong key, there is no way for a rollback mechanism to help. Given that no one can save the programmer from his or her errors, and that the kind of errors required for a Redis command to fail are unlikely to enter in production, we selected the simpler and faster approach of not supporting roll backs on errors.

大白話的意思就是:redis的作者認為,當事務的執行時,一般發生錯誤都是因為業務程式設計錯誤造成的,這種錯誤通常隻會出現在開發環境中,而基本很少會在實際的生産環境中出現(因為這種業務錯誤都會在測試的時候消滅),是以他認為沒有必要為 Redis 開發事務自動復原功能,這和Redis追求的簡單高效的設計主旨不符合。

而mysql恰恰相反,mysql認為資料庫有必要也有責任處理事務中報錯的情況,是以mysql有自動復原的功能。

在redis中使用事務:

liuyue:~ liuyue$ redis-cli
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set test 123
QUEUED
127.0.0.1:6379> exec
1) OK
127.0.0.1:6379> get test
"123"
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set test 456
QUEUED
127.0.0.1:6379> discard
OK
127.0.0.1:6379> get test
"123"
127.0.0.1:6379> 
liuyue:~ liuyue$ clear
           

在python中操作redis事務

#導包
import redis

#定義ip
host = 'localhost'

#建立服務連接配接

r = redis.Redis(host=host)
pipe = r.pipeline()

#開啟事務
pipe.multi()
#存儲子指令
pipe.set('key2', 4)
#執行事務
pipe.execute()

print(r.get('key2'))           

繼續閱讀