雞肋的Redis事務
沒錯,Redis也有事務管理,但是功能很簡單,在正式開發中也並不推薦使用。但是面試中有可能會問到,所以本文簡單談一談Redis的事務。
透過這篇文章,你會了解
Redis為什麼要提供事務? Redis事務基本指令和使用方法 CAS樂觀鎖是什麼? Redis事務為什麼不支援回滾?
1. 為什麼要用事務
我們知道Redis的單個命令是原子性的,比如get
、set
、mget
、mset
等指令。
原子性是指操作是不可分割的,在執行完畢之前不會被任何其它任務或事件中斷,也就不會有併發的安全性問題
在涉及到多個命令的時候,如果需要把多個命令設定為一個不可分割的處理序列,就需要用到事務了。
比如,招財和陀螺各有100元,招財給陀螺轉了10元,這時候需要在Redis中把招財的金額總數-10,同時需要把陀螺的金額總數+10。這兩個操作要麼同時成功,要麼同時失敗,這時候就需要事務了。
實際上,Redis連這個簡單的需求都沒辦法完美做到,至於為啥,接著往下看吧
2. 事務的用法
2.1 5個基本指令
Redis提供了以下5個基本指令,先混個眼熟就行,接下來在案例中進行實操,想記不住都難
MULTI EXEC DISCARD WATCH UNWATCH
2.2 案例演示
案例場景:招財和陀螺各有100元,招財給陀螺轉了10元,這時候需要在Redis中把招財的金額-10,同時需要把陀螺的金額+10。
2.2.1 事務提交
我們首先為陀螺和招財初始化自己的金額;然後使用MULTI
命令顯式開啟
Redis事務。該命令總是直接返回OK。此時使用者可以傳送多個指令,Redis不會立刻執行這些命令,而是將這些指令依次放入
當前事務的指令佇列中;EXEC
被呼叫後,所有的命令才會被依次執行。
# 給陀螺初始化100元
127.0.0.1:6379> set tuoluo 100
OK
# 給招財初始化100元
127.0.0.1:6379> set zhaocai 100
OK
# 顯式開啟事務
127.0.0.1:6379> MULTI
OK
# 給陀螺增加10元
127.0.0.1:6379(TX)> INCRBY tuoluo 10
QUEUED
# 給招財減少10元
127.0.0.1:6379(TX)> DECRBY zhaocai 10
QUEUED
# 執行事務中的所有指令(提交事務)
127.0.0.1:6379(TX)> EXEC
1) (integer) 110
2) (integer) 90
2.2.2 巢狀事務
Redis不支援巢狀事務,多個MULTI
命令和單個MULTI
命令效果相同。
# 第一次開啟事務
127.0.0.1:6379> MULTI
OK
# 嘗試巢狀事務
127.0.0.1:6379(TX)> MULTI
(error) ERR MULTI calls can not be nested
# 仍然處於第一個事務當中
127.0.0.1:6379(TX)>
2.2.3 放棄事務
如果開啟事務之後,中途後悔了怎麼辦?呼叫DISCARD
可以清空事務中的指令佇列,退出事務。
127.0.0.1:6379> MULTI
OK
# 在事務中呼叫DISCARD指令
127.0.0.1:6379(TX)> DISCARD
OK
# 會退出當前事務
127.0.0.1:6379>
2.2.4 watch指令
假如我們在一個客戶端連線中開啟了事務,另一個客戶端連線修改了這個事務涉及的變數值,將會怎樣?
client1開啟了一個轉賬的事務,事務開始時招財和陀螺各自擁有100元,在執行EXEC
指令之前,client2將陀螺的餘額新增了10元,此時執行EXEC
之後,陀螺最終的金額為120元,招財為90元。
很明顯,這種情況下存在資料安全問題。
為此Redis提供了WATCH
的指令,該指令可以為Redis事務提供CAS樂觀鎖
行為,即多個連線同時更新變數的時候,會和變數的初始值進行比較,只在這個變數的值沒有被修改的情況下才會更新成新的值。
2.2.4.1 WATCH用法
對應我們的案例,我們可以使用WATCH
監聽一個或多個key,如果開啟事務之前,至少有一個被監視的key在EXEC
執行之前被修改了,那麼整個事務都會被取消,直接返回nil
(見下面的案例)。UNWATCH
是WATCH
的反操作。
2.2.4.2 CAS機制
CAS(Compare And Swap)比較並替換,是多併發時常用的一種樂觀鎖技術
CAS需要三個變數資訊,分別是記憶體位置(JAVA中的記憶體地址,V),舊的預期值(A)和新值(B)。CAS執行時,當且僅當V和預期值A相等時,更新V的值為新值B,否則不執行更新。
3. 事務執行出錯怎麼辦
事務執行時可能遇到問題,按照發生的時機不同分為兩種:
執行 EXEC
之前執行 EXEC
之後
3.1 執行EXEC之前發生錯誤
比如指令存在語法錯誤(引數數量不對,指令單詞拼錯)導致不能進入commands
佇列,這一步主要是編譯錯誤,還未到執行時。
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> SET tuoluo
(error) ERR wrong number of arguments for 'set' command
127.0.0.1:6379(TX)> EXEC
(error) EXECABORT Transaction discarded because of previous errors.
這種情況下事務會執行失敗,佇列中的所有指令都不會得到執行。
3.2 執行EXEC之後發生錯誤
這種錯誤往往是型別錯誤,比如對String使用了Hash的命令,這是執行時錯誤,編譯期間不會出錯
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> SET tuoluo 100
QUEUED
127.0.0.1:6379(TX)> LPOP tuoluo
QUEUED
127.0.0.1:6379(TX)> EXEC
1) OK
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
我們發現,SET tuoluo 100
的命令居然執行成功了,也就是在發生了執行時異常的情況下,錯誤的指令不會被執行,但是其他的命令不會受影響。
這種方式顯然不符合我們對原子性
的定義,也就是Redis的事務無法實現原子性,無法保證資料一致。
針對這種缺陷,Redis官方也是做了說明的。
4. Redis事務為什麼不支援回滾
引自Redis官方文件。
為了方便大家理解,我翻譯一下就是:
你們程式設計師的鍋,關我們Redis屁事兒!
Redis官方認為,只有在命令語法錯誤或者型別錯誤的時候,Redis命令才會執行失敗。而且他們認為有這種錯誤的語法一般也不會進入到生產環境。而且不支援回滾可以使他們有更多時間玩兒Redis執行得更簡單快捷。
這種說法多牛!如果出問題就是程式設計師的問題,寫錯了還讓程式碼進入生產環境,那就是罪上加罪,你永遠賴不著Redis官方。
這可能就是不推薦使用Redis事務的原因了吧,雞肋是一方面,萬一被官方打臉了呢?所以Redis事務的知識稍微瞭解一下就好,面試被問到能回到上來就可以了。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024924/viewspace-2935125/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Oracle OMF 為雞肋Oracle
- PG 的 MergeJoin 就是雞肋
- Python多執行緒雞年不雞肋Python執行緒
- Redis的事務Redis
- 防止OA系統成為雞肋
- 我所瞭解的JavaScript糟粕和雞肋JavaScript
- Redis 事務Redis
- redis事務Redis
- Redis 中的事務Redis
- 十、Redis事務、事務鎖Redis
- 雲端計算:亞馬遜的救心丸 騰訊的雞肋 阿里的王牌亞馬遜阿里
- 當紅炸子雞圖資料庫商業化落地“雞肋”?資料庫
- redis的事務處理Redis
- Redis事務操作Redis
- redis-事務Redis
- Mybatis-聊一聊雞肋的快取體系MyBatis快取
- Redis系列(九):Redis的事務機制Redis
- Redis系列12:Redis 的事務機制Redis
- 【Redis 系列】redis 學習六,redis 事務處理和監控事務Redis
- 能把SAP系統玩成雞肋的公司,太有才了!
- python 多執行緒為什麼雞肋?Python執行緒
- 入侵檢測技術,雞肋還是機會?
- Redis--事務理解Redis
- NoSql-Redis事務SQLRedis
- 冰鑑科技CEO顧凌雲: AI金融產品是「雞肋」還是「雞腿」?AI
- 不支援原子性的 Redis 事務也叫事務嗎?Redis
- Redis 中的事務分析,Redis 中的事務可以滿足ACID屬性嗎?Redis
- (騷操作)Laravel 中一個鮮為人知的雞肋功能Laravel
- Django認證系統並不雞肋反而很重要Django
- 你應該知道的Redis事務Redis
- redis-19.事務-鎖Redis
- AWE部分功能相對“雞肋”再次成為智慧家電的痛點
- 以圖搜尋——網際網路影象搜尋引擎的“雞肋”?
- redis學習(九) redis事務和redis指令碼的比較Redis指令碼
- 關於BBSxp/LeadBBS的後臺上傳Webshell的雞肋防範Webshell
- 遇到個小問題,Java泛型真的是雞肋嗎?Java泛型
- 跨Mysql、Redis、Mongo的分散式事務MySqlRedisGo分散式
- 【話題討論】如何把運維人員從雞肋轉變成雞大腿的故事之討論運維