日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

redis事务实现

發布時間:2024/2/2 综合教程 25 生活家
生活随笔 收集整理的這篇文章主要介紹了 redis事务实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

redis如何實現事務

事務的執行包含三個步驟,redis提供multi、exec兩個命令來完成這三個步驟。
第一步:客戶端要使用一個命令顯示的表示一個事務的開啟。在redis中這個命令就是multi。

第二步:客戶端把事務中本身要執行的具體操作(例如增刪改查)發送給服務器端。這些操作就是redis本身提供的數據讀寫命令,例如GET、SET等。這些命令雖然被客戶端發送到了服務器端,但redis實例只是把這些命令暫存到一個命令隊列中,并不會立即執行。

第三步:客戶端向服務器端發送提交事務的命令,讓數據庫實際執行第二步中發送的具體操作。redis提供的exec就是執行事務提交的。當服務器收到exec命令后,才會實際執行隊列中的命令。

#開啟事務
127.0.0.1:6379> MULTI
OK
#將a:stock減1,
127.0.0.1:6379> DECR a:stock
QUEUED
#將b:stock減1
127.0.0.1:6379> DECR b:stock
QUEUED
#實際執?事務
127.0.0.1:6379> EXEC
1) (integer) 4
2) (integer) 9

a:stock和b:stock兩個鍵的初始值是5和10.在multi命令后執行兩個decr,是把a:stock和b:stock兩個鍵的值分別-1,他們執行的結果都是QUEUED,這就表示這些操作都被暫時存放到了命令隊列,沒有實際執行。等到exec命令后,可以看到返回結果4和9,這就表明,兩個decr命令成功執行了。

redis的事務機制能保證ACID嗎?

原子性

如果事務正常執行,沒有發生任何錯誤,那么,multi和exec配合使用,就可以保證多個操作都完成。但是,如果事務執行發生錯誤了,原子性還能保證嗎?我們需要分三種情況來看。

第一種情況是,在執行exec命令前,客戶端發送的操作命令本身就有錯誤(比如語法錯誤,使用了不存在的命令),在命令入隊時就會被檢測出來。對于這種情況,在命令入隊時,redis就會報錯并且記錄下這個錯誤。此時,我們還能繼續提交命令。等到執行exec命令之后,redis就會拒絕執行所有提交的命令操作,返回事務失敗的結果。這樣一來所有命令都不會被執行,保證了原子性

#開啟事務
127.0.0.1:6379> MULTI
OK
#發送事務中的第?個操作,但是Redis不?持該命令,返回報錯信息
127.0.0.1:6379> PUT a:stock 5
(error) ERR unknown command `PUT`, with args beginning with: `a:stock`, `5`, 
#發送事務中的第?個操作,這個操作是正確的命令,Redis把該命令?隊
127.0.0.1:6379> DECR b:stock
QUEUED
#實際執?事務,但是之前命令有錯誤,所以Redis拒絕執?
127.0.0.1:6379> EXEC
(error) EXECABORT Transaction discarded because of previous errors.

在這個例子中,事務里包含了一個redis本身就不支持的put命令,所以在put命令入隊時,redis就保存了。雖然,事務中有一個正確的decr,但是,在最后執行exec命令后,整個事務被放棄執行了。

第二種情況。
和第一種情況不同的是,事務操作入隊時,命令和操作的數據類型不匹配,但redis實例沒有檢查出錯誤。但是,在執行exec命令后,redis實際執行這些事務操作時,就會報錯。不過,需要注意的是,雖然redis會對錯誤命令報錯,但還是會把正確的命令執行完。在這種情況下,事務的原子性就無法得到保證了

#開啟事務
127.0.0.1:6379> MULTI
OK
#發送事務中的第?個操作,LPOP命令操作的數據類型不匹配,此時并不報錯
127.0.0.1:6379> LPOP a:stock
QUEUED
#發送事務中的第?個操作
127.0.0.1:6379> DECR b:stock
QUEUED
#實際執?事務,事務第?個操作執?報錯
127.0.0.1:6379> EXEC
1) (error) WRONGTYPE Operation against a key holding the wrong kind of value
2) (integer) 8

事務中的LPOP命令對String類型數據進行操作,入隊時沒有報錯,但是,在exec執行時報錯了。lpop命令本身沒有執行成功,但事務中的decr命令卻成功執行了。

redis不像mysql提供了回滾機制,可以回滾事務,redis沒有提供回滾機制。雖然redis提供了discard命令,但是這個命令只能用來主動放棄事務執行,把暫存的命令隊列清空,起不到回滾的作用。

#讀取a:stock的值4
127.0.0.1:6379> GET a:stock
"4"
#開啟事務
127.0.0.1:6379> MULTI 
OK
#發送事務的第?個操作,對a:stock減1
127.0.0.1:6379> DECR a:stock
QUEUED
#執?DISCARD命令,主動放棄事務
127.0.0.1:6379> DISCARD
OK
#再次讀取a:stock的值,值沒有被修改
127.0.0.1:6379> GET a:stock
"4"

這個例子中,a:stock鍵的值一開始為4,然后,執行一個事務,相對a:stock的值-1.但是,在事務的最后,執行了discard命令,所以事務就被放棄了,再次查看a:stock的值,會發現仍然是4。

最后,再來看看第三種情況:在執行事務的exec命令時,redis發生了故障,導致事務執行失敗
這種情況下,如果redis開啟了AOF日志,那么,只會有部分事務操作被記錄到AOF日志中。可以使用redis-check-aof工具檢查AOF日志文件,這個工具可以把未完成的事務操作從AOF文件中刪除。這樣一來,使用AOF恢復數據庫實例后,事務操作不會再被執行,從而保證原子性。
當然,如果AOF日志并沒有開啟,那么實例重啟后,數據也就沒辦法恢復了,此時,就談不上原子性了。

總結:

命令入隊就報錯,會放棄事務執行,保證原子性
命令入隊不報錯,實際執行時報錯,不保證原子性
exec命令執行時實例故障,如果開啟了AOF日志,那么保證原子性。

一致性

事務的一致性保證會受到錯誤命令、實例故障的影響。所以,我們按照命令出錯和實例故障的發生時機,分成三種情況來看。
情況一:命令入隊時就報錯
在這種情況下,事務本身就會被放棄執行,所以可以保證數據庫的一致性。
情況二:命令入隊時沒報錯,實際執行時報錯
在這種情況下,有錯誤的命令不會被執行,正確的命令可以正常執行,也不會改變數據庫的一致性。
情況三:EXEC命令執行時實例發生故障
如果我們沒有開啟RDB或AOF,那么,實例故障重啟后,數據都沒有了,數據庫是一致的。

如果我們使用了RDB快照,因為RDB快照不會在事務執行時執行,所以,事務命令操作的結果不會被保存到RDB快照中,使用RDB快照進行恢復時,數據庫里的數據也是一致的。

如果我們使用了AOF日志,而事務操作還沒有被記錄到AOF日志時,實例就發生了故障,那么,使用AOF日志恢復的數據庫數據是一致的。如果只有部分操作被記錄到了AOF日志,我們可以使用redis-check-aof清除事務中已經完成的操作,數據庫恢復后也是一致的。

所以,總結來說,在命令執行錯誤或Redis發生故障的情況下,Redis事務機制對一致性屬性是有保證的

隔離性

redis單線程執行,不會存在隔離性問題。

持久性

因為Redis是內存數據庫,所以,數據是否持久化保存完全取決于Redis的持久化配置模式。

如果Redis沒有使用RDB或AOF,那么事務的持久化屬性肯定得不到保證。

如果Redis使用了RDB模式,那么,在一個事務執行后,而下一次的RDB快照還未執行前,如果發生了實例宕機,這種情況下,事務修改的數據也是不能保證持久化的。

如果Redis采用了AOF模式,因為AOF模式的三種配置選項no、everysec和always都會存在數據丟失的情況,所以,事務的持久性屬性也還是得不到保證。

所以,不管Redis采用什么持久化模式,事務的持久性屬性是得不到保證的。

總結

以上是生活随笔為你收集整理的redis事务实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。