redis事務(wù)與關(guān)系型數(shù)據(jù)庫(kù)事務(wù)比較

redis 是一個(gè)高性能的key-value 數(shù)據(jù)庫(kù)。作為no sql 數(shù)據(jù)庫(kù)redis 與傳統(tǒng)關(guān)系型數(shù)據(jù)庫(kù)相比有簡(jiǎn)單靈活、數(shù)據(jù)結(jié)構(gòu)豐富、高速讀寫等優(yōu)點(diǎn)。

本文主要針對(duì)redis 在事務(wù)方面的處理與傳統(tǒng)關(guān)系型數(shù)據(jù)庫(kù)(使用mysql)進(jìn)行比對(duì),所使用的環(huán)境為ubuntu 14.04.1,mysql 5.5.49,redis 3.2.3。

1、操作事務(wù)命令

mysql 使用start transaction 開(kāi)啟事務(wù),rollback 回滾事務(wù),commit 提交事務(wù)。redis 使用multi 開(kāi)始事務(wù),discard 取消事務(wù),exec 提交事務(wù)。開(kāi)始實(shí)驗(yàn)前為mysql 和redis 準(zhǔn)備測(cè)試數(shù)據(jù),tom1 賬戶準(zhǔn)備1000元,tom2 賬戶準(zhǔn)備500元。

(圖1-數(shù)據(jù)準(zhǔn)備)


場(chǎng)景1:使用事務(wù)從tom1轉(zhuǎn)100元到tom2 。

步驟如下:


(圖2-mysql 事務(wù)執(zhí)行過(guò)程)
(圖3-redis 事務(wù)執(zhí)行過(guò)程)

從場(chǎng)景1中可以看出mysql 開(kāi)啟事務(wù)后事務(wù)中的sql 語(yǔ)句在commit 之前就已經(jīng)執(zhí)行了sql 語(yǔ)句的,只是并未真正提交到數(shù)據(jù)庫(kù)。redis 使用multi 開(kāi)啟事務(wù)后,編寫的sql 語(yǔ)句都進(jìn)入queue 隊(duì)列中,待執(zhí)行exec 提交事務(wù)時(shí)才一次性按進(jìn)入queue 隊(duì)列的順序提交到數(shù)據(jù)庫(kù)。同樣針對(duì)回滾,mysql 執(zhí)行rollback 會(huì)將提交的數(shù)據(jù)回滾,redis 因?yàn)闆](méi)有提交到數(shù)據(jù),使用discard 只是單純?nèi)∠趒ueue 中的sql 語(yǔ)句。

場(chǎng)景2: 在執(zhí)行tom1 向tom2 轉(zhuǎn)過(guò)程中100元的過(guò)程中使用了語(yǔ)法錯(cuò)誤的sql。


(圖4-mysql 事務(wù)中存在語(yǔ)法錯(cuò)誤語(yǔ)句)
(圖5-redis 事務(wù)中存在語(yǔ)法錯(cuò)誤語(yǔ)句)

從場(chǎng)景2中可以看出,mysql 事務(wù)即使遇到錯(cuò)誤的語(yǔ)句也會(huì)提交正確的sql 到數(shù)據(jù)庫(kù),需要程序員控制當(dāng)遇到語(yǔ)句異常時(shí)進(jìn)行回滾,redis 與mysql 不同,提交事務(wù)時(shí)當(dāng)queue 中有語(yǔ)法錯(cuò)誤語(yǔ)句會(huì)discard 整個(gè)事務(wù)中的sql 語(yǔ)句。

場(chǎng)景3: 在執(zhí)行tom1 向tom2 轉(zhuǎn)過(guò)程中100元的過(guò)程中使用了錯(cuò)誤的執(zhí)行對(duì)象。

步驟如下:


(圖6-mysql 中存在操作錯(cuò)誤對(duì)象的sql 語(yǔ)句)
(圖7-redis 中存在操作錯(cuò)誤對(duì)象的sql語(yǔ)句)

從場(chǎng)景3中可以看出,mysql 和redis 事務(wù)當(dāng)遇到操作對(duì)象類型不正確的時(shí)候都會(huì)提交執(zhí)行事務(wù)。

2、事務(wù)鎖

在關(guān)系型數(shù)據(jù)庫(kù)中主要通過(guò)樂(lè)觀鎖和悲觀鎖進(jìn)行數(shù)據(jù)庫(kù)事務(wù)的并發(fā)控制。而在redis 中是通過(guò)watch 加樂(lè)觀鎖對(duì)數(shù)據(jù)庫(kù)進(jìn)行并發(fā)控制。

mysql 悲觀鎖是通過(guò)select * from table where for update將數(shù)據(jù)加鎖,導(dǎo)致其他線程或事務(wù)不能更新該數(shù)據(jù)。相對(duì)于悲觀鎖,在對(duì)數(shù)據(jù)庫(kù)進(jìn)行處理的時(shí)候,樂(lè)觀鎖并不會(huì)使用數(shù)據(jù)庫(kù)提供的鎖機(jī)制。一般的實(shí)現(xiàn)樂(lè)觀鎖的方式就是記錄數(shù)據(jù)版本。數(shù)據(jù)版本為數(shù)據(jù)增加的一個(gè)版本標(biāo)識(shí)。當(dāng)讀取數(shù)據(jù)時(shí),將版本標(biāo)識(shí)的值一同讀出,數(shù)據(jù)每更新一次,同時(shí)對(duì)版本標(biāo)識(shí)進(jìn)行更新。當(dāng)我們提交更新的時(shí)候,判斷數(shù)據(jù)庫(kù)表對(duì)應(yīng)記錄的當(dāng)前版本信息與第一次取出來(lái)的版本標(biāo)識(shí)進(jìn)行比對(duì),如果數(shù)據(jù)庫(kù)表當(dāng)前版本號(hào)與第一次取出來(lái)的版本標(biāo)識(shí)值相等,則予以更新,否則認(rèn)為是過(guò)期數(shù)據(jù)。

關(guān)系型數(shù)據(jù)庫(kù)mysql 實(shí)現(xiàn)數(shù)據(jù)版本主要有兩種方式,第一種是使用版本號(hào),第二種是使用時(shí)間戳。使用版本號(hào)時(shí),可以在數(shù)據(jù)初始化時(shí)指定一個(gè)版本號(hào),每次對(duì)數(shù)據(jù)的更新操作都對(duì)版本號(hào)執(zhí)行+1操作。并判斷當(dāng)前版本號(hào)是不是該數(shù)據(jù)的最新的版本號(hào)。

(圖8-mysql樂(lè)觀鎖)

圖8展示了mysql 樂(lè)觀鎖的示例,開(kāi)啟兩個(gè)mysql 客戶端,客戶端1執(zhí)行start transaction 查詢數(shù)據(jù),這時(shí)客戶端2更新了客戶端1查詢到的數(shù)據(jù)及version 字段,然后客戶端1在第3步試圖更新在第一步中查詢到的數(shù)據(jù)時(shí)因version 已改變因此更新失敗。

(圖9-redis 樂(lè)觀鎖(watch))

redis 是通過(guò)watch 命令監(jiān)控?cái)?shù)據(jù)是否發(fā)生變化實(shí)現(xiàn)樂(lè)觀鎖的。如圖9所示打開(kāi)兩個(gè)redis 客戶端,客戶端1對(duì)數(shù)據(jù)tom2 進(jìn)行watch,打開(kāi)事務(wù)更改tom1,tom2,客戶端2更改客戶端1中watch 的對(duì)象,步驟3客戶端1提交事務(wù)由于watch 的對(duì)象被更改了,導(dǎo)致事務(wù)放棄執(zhí)行。

3、事務(wù)的ACID 性質(zhì)

下面討論下事務(wù)的ACID 性質(zhì)。傳統(tǒng)關(guān)系型數(shù)據(jù)庫(kù)事務(wù)具備ACID 性質(zhì),這里不做詳細(xì)討論。

針對(duì)Redis 事務(wù)具有原子性(Atomicity),一致性(Consistency),和隔離性(Isolation),當(dāng)redis 在持久化模式運(yùn)行時(shí),也具備持久性(Durability)。在場(chǎng)景1~3和樂(lè)觀鎖示例中redis 全部執(zhí)行事務(wù)隊(duì)列中的sql 語(yǔ)句即使其中sql存在操作對(duì)象錯(cuò)誤,要么全部discard放棄執(zhí)行,因此redis 事務(wù)具有原子性(Atomicity)。

redis 事務(wù)在執(zhí)行過(guò)程中發(fā)生錯(cuò)誤或進(jìn)程被終結(jié),都能保證數(shù)據(jù)的一致性(Consistency)。因?yàn)閞edis 使用單線程串行方式來(lái)執(zhí)行事務(wù)的,在執(zhí)行事務(wù)期間不會(huì)對(duì)事務(wù)進(jìn)行中斷(一致性),因此redis 事務(wù)也具有隔離性(Isolation)。redis 可以只將運(yùn)行結(jié)果保存在內(nèi)存中,但當(dāng)redis 服務(wù)器使用AOF 持久化模式并appendfsync 設(shè)置為always 時(shí),程序執(zhí)行sql 后會(huì)調(diào)用sync 函數(shù)將數(shù)據(jù)保存到硬盤里,因此redis 事務(wù)也可以具有持久性(Durability)。

通過(guò)下表對(duì)redis 事務(wù)和關(guān)系型數(shù)據(jù)庫(kù)事務(wù)做一個(gè)簡(jiǎn)單的總結(jié)。

參考文檔:

http://redis.io/topics/transactions

《redis設(shè)計(jì)與實(shí)現(xiàn)》黃健宏


本文作者:Tom(點(diǎn)融黑幫),現(xiàn)任點(diǎn)融Fin-Tech高級(jí)研發(fā)工程師,曾任職于IBM。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容