Redis 事務
目錄
- Redis 事務
- 事務
- 1. 命令有序
- 2. 始終原子
- 開啟使用事務
- Redis事務中出現錯誤
- 1. EXEC前的錯誤
- 2. EXEC后的錯誤
- 為什么出錯了不支持roll backs?
- Redis的樂觀鎖實作check-and-set
- 小結
- 事務
Redis操作時支持事務的,事務具有原子性atomic,包含在事務中的操作要么都執行成功,要么都執行失敗,但是redis不支持回滾,但是可以在測驗開發環節避免錯誤操作,可以說原子性上是半支持的,看后面原因,
很多時候我們需要進行事務操作,
翻譯官檔:https://redis.io/topics/transactions
實際操作:python版使用參考
https://github.com/7Edge/redis-demo/blob/master/redis_pipeline.py
事務
MULTI, EXEC, DISCARD 和 WATCH 操作都是redis事務的基礎操作,這些操作可以讓一組操作看作一個操作原子執行,之所以能做到,是因為一下兩個重要的保障:
1. 命令有序
在事務中的所有命令都是有序的,且執行是順序執行的,當另一個客戶端連接發生錯誤,是不可能影響到當前正在執行的事務的,這點就保證了命令執行時是相互隔離的操作,因為是單執行緒,且redisserver利用i/o多路復用來處理并發連接,
2. 始終原子
在事務中無論全部命令執行了,還是一個命令都沒執行,redis的事務都是原子的,EXEC命令開啟事務中所有命令的執行,如果在呼叫multi命令前沒有,client到server端的連接斷開,沒有任何操作會被執行;如果EXEC命令被執行了, 所有的操作都會被執行,如果配置時使用了append-only file ,redis會使一個single write(2) syscall寫入到aof檔案中,然而,如果redis server crashes 或者被管理員強制kill掉,這時可能只有一部分操作被注冊了,這種情況下,redis在重啟的時候會發現這種情況,并且啟動失敗退出,報一個錯誤, 這時就要使用 redis-check-aof 工具,該工具將會修復aof檔案,洗掉只有部分的事務,然后再重啟redis即可,
開啟使用事務
1. 執行MULTI # 開啟事務, 回傳OK或者其它
2. 執行多個命令 # 事務中的操作, 回傳QUEUED,表明加入事務命令佇列
3. EXEC # 執行,回傳每個事務中命令的回傳結果串列
4. DISCARD 如果在EMULTI之后EXEC之前要關閉事務,再EXEC之前執行即可flush所有事務命令佇列中的命令并關閉事務
Redis事務中出現錯誤
在事務中,有些操作可能或遇到執行出錯,大致有兩種命令執行錯誤:
1. EXEC前的錯誤
有一個錯誤在執行EXEC命令前,即命令沒有成功的加入到佇列中,如:執行的命令引數個數錯誤,命令名使用錯誤等,
對于這種錯誤,client是可以感知到的,因為執行命令時,其實是加入到命令佇列中的,如果回傳QUEUED說明加入成功,其它回傳都是錯誤,這種錯誤,大多數client將會中斷事務并自動DISCARD事務,(python得redis模塊中,由于pipeline和multi/exec結合,redis.exceptions.ResponseError例外,但是沒有例外得命令還是會執行,就是由于與pipeline結合)
然而,在Redis 2.6.5 后,server將會記錄錯誤在累積命令到命令佇列中時,這時執行EXEC,server將會拒絕事務的執行并回傳一個錯誤,自動discard.
而在Redis2.6.5之前,對于這種錯誤,server行為是,只會執行成功加入到佇列中的命令,相當于命令集中的一個子集被執行一次,盡管有錯誤發生,Redis 2.6.5 server沒有了這種處理邏輯,而是將邏輯加入到新的命令中,就是pipeline管道命令,管道可以實作之前的行為,管道會回傳命令的回傳結果的串列,
2. EXEC后的錯誤
錯誤在EXEC執行后,如key沖突,對于這種錯誤,沒有handle方法,所有的其它命令都會被執行,即使一新命令出錯在事務期間,
為什么出錯了不支持roll backs?
像關系型資料庫,事務都是支持回滾的,而在redis事務中竟然支持錯誤的發生,redis之所以有這種行為是因為一下兩點:
- redis 命令失敗只會是語法錯誤或者 存在的key修改成了錯誤的資料型別,這些錯誤是非常容易在開發或者測驗階段被發現的,
- redis本應該是簡單且快速的,不需要roll back能力,
Redis事務所指的原子性僅僅只針對將命令加入執行佇列的程序,Redis事務不支持在命令執行程序中的錯誤回滾,
Redis的樂觀鎖實作check-and-set
并發事務,都會有修改同一資料的時候,雖然redis事務因為讀執行緒時隔離了的,但是有時候我們需要鎖定資料,獨占使用,就只有使用redis提供的樂觀鎖來鎖定我們的資料,這個樂觀鎖只能配合事務使用,檢查行為是在事務執行EXEC時,如果有變化,那么EXEC執行回失敗,WATCH 被用于提供CAS行為用于redis事務中,CAS即是我們常說的樂觀鎖,
樂觀鎖的事務執行失敗,必須檢測結果,失敗就要重試,
我們知道事務的4特性ACID:
Atomic原子性: 事務中操作集,要么都成功,要么都失敗回滾,
Redis事務所指的原子性僅僅只針對將命令加入執行佇列的程序,Redis事務不支持在命令執行程序中的錯誤回滾,
Consistency 一致性: 事務前后,資料庫是從一個一致性狀態到另一個一致性狀態,如轉賬前后總數是一致的,
Isolation 隔離性: 并發事務時,事務之間都不會由于訪問同一資料而被干擾,在這個隔離層面講,就有多種隔離級別,因為隔離級別時影響并發事務效率和資料安全性的,要在效率和安全間平衡是關鍵,隔離級別太嚴格,并發效率低,資料安全;隔離級別太低,又怕資料不安全,
Durability 持久性:事務一旦被提交,改變時永久的,即要持久化,很多都會將事務操作完后追加到操作日志檔案中,資料者寫入磁盤檔案系統持久化,
WATCH 命令用于監控key的改變,如果被監控時的key發生了修改在執行EXEC之前,那么這個事務將aborts,并且回傳一個Null,表明事務失敗,可用在要鎖定資料的事務前,WATCH 配合MULTI和EXEC
使用UNWATCH可以flush掉所有WATCHED keys,
小結
- Redis事務所指的原子性僅僅只針對將命令加入執行佇列的程序,Redis事務不支持在命令執行程序中的錯誤回滾
- 利用watch可以樂觀鎖資料,樂觀cas,悲觀讓別人等,
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/42315.html
標籤:NoSQL
上一篇:redis入門初學知識
