圖解 Redis 事務 ACID特性 |源碼解析|EXEC、WATCH、QUEUE

寫在前面

Redis 通過 MULTIEXECWATCH 等命令來實現事務功能。Redis的事務是將多個命令請求打包,然后一次性、按照順序的執行多個命令的機制,并且在事務執行期間,服務器不會中斷事務而該去執行其他客戶端的命令請求。 就像下面這樣:

redis> MULTI
OK
redis(TX)> SET fanone 1
QUEUED
redis(TX)> SET fantwo 2
QUEUED
redis(TX)> GET fanone
QUEUED
redis(TX)> EXEC
1) OK
2) OK
3) "1"

本文我們就從redis的事務執行過程以及ACID四個方面來介紹redis的事務

事務實現

在這里插入圖片描述
從上面的例子我們可以知道,redis的事務是從MULTI命令開始的,所有的命令都會按照FIFO的順序進入一個QUEUE隊列中,當執行EXEC操作后才將這些命令逐步執行。

MULTI

事務隊列是一個multiCmd類型的數組,數組中的每個multiCmd結構都保存了一個已入隊命令的相關信息,包括指向命令實現函數的指針、命令的參數,以及參數的數量:

typedef struct multiCmd{robj **argv; 	// 參數int argc; 		// 參數數量struct redisCommand *cmd // 命令指針
} multiCmd;

事務隊列以FIFO先進先出的方式保存入隊的命令,還是用上面的例子來畫一個原型圖:

在這里插入圖片描述
當一個處于事務狀態的客戶端向服務器發送EXEC命令的時候,這個EXEC命令將立即被服務器執行。服務器會遍歷這個客戶端的事務隊列,執行隊列中保存的所有命令,最后將執行命令所得的結果全部返回給客戶端。EXEC的偽代碼如下:

void EXEC() {std::vector<Reply> reply_queue;  // 創建空白的回復隊列for (const auto& cmd : client.mstate.commands) { // 執行事務中的所有命令Reply reply = execute_command(cmd.command, cmd.argv, cmd.argc);reply_queue.push_back(reply);}client.flags &= ~REDIS_MULTI; // 清理事務狀態client.mstate.count = 0;release_transaction_queue(client.mstate.commands);send_reply_to_client(client, reply_queue);// 發送回復給客戶端
}

WATCH

接著我們來講講WATCH命令,其實這是一個樂觀鎖(optimistic locking),可以在EXEC命令執行之前,監視任意數量的數據庫鍵,并在EXEC命令執行時,檢查被監視的鍵是否有已經被修改過了的,如果是的話,服務器將拒絕執行事務,并向客戶端返回代表事務執行失敗的空回復

在這里插入圖片描述
比如下面這個例子:
在這里插入圖片描述

時間客戶端A客戶端B
T1WATCH “fanone”
T2MULTI
T3SET “fanone” 1
T4SET “fanone” 2
T5EXEC

而在時間T4,客戶端B修改了fanone鍵的值,當客戶端A在T5執行EXEC命令的時候,服務器會發現WATCH監視的鍵fanone已經被修改了,因此服務器拒絕執行客戶端A的事務,并且向客戶端A返回空回復

每個Redis數據庫都保存著一個watched_keys字典,這個字典的鍵是某個被WATCH命令監視的數據庫鍵,而字典的值則是一個鏈表,鏈表中記錄了所有監視數據庫鍵的客戶端。

typedef struct redisDb {dict *watched_keys; // 正在被WATCH命令監視的鍵 
}

在這里插入圖片描述

ACID

Redis的事務是否符合ACID呢?

原子性 Atomicity

在這里插入圖片描述

事務具有原子性是指,數據庫將事務中的多個操作當作一個整體來執行,要么全部執行,要么全部不執行。對于Redis的事務功能來說,事務隊列中的命令要么就都全部都執行,要么就一個都不執行,因此Redis的事務是具有原子性的。 比如以下成功執行的事務,事務中的所有命令都被執行:

redis> MULTI
OK
redis(TX)> SET fanone 1
QUEUED
redis(TX)> GET fanone
QUEUED
redis(TX)> EXEC
1) OK
2) "1"

與此相反,如果其中有一個命令是錯誤的,那么整個命令就不會執行。fanone這個key是一個string,并不是set,所以不能使用SADD命令執行。

redis> MULTI
OK
redis(TX)> SET fanone 1
QUEUED
redis(TX)> SADD fanone 2
QUEUED
redis(TX)> EXEC
1) OK
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value

那么大家會發現Redis的事務和傳統的關系型數據庫事務的最大區別在于,Redis不支持事務回滾機制,也就是rollback。

Redis的作者在事務功能的文檔中也解釋道,不支持事務回滾是因為這種復雜的功能和Redis追求簡單高效的設計主旨不相符。

在這里插入圖片描述

一致性 Consistency

事務具有一致性指的是,如果數據庫在執行事務之前是一致的,那么在事務執行之后,無論事務是否執行成功,數據庫也應該依然是一致的。 而這個一致指的是 數據符合數據庫本身的定義和要求,沒有包含非法或者無效的錯誤數據

比如執行完事務不會多一個之前沒有的命令,或者某個key是string類型,不會變成set類型。我們用上面同一個例子來說明:

redis> MULTI
OK
redis(TX)> SET fanone 1
QUEUED
redis(TX)> SADD fanone 2
QUEUED
redis(TX)> EXEC
1) OK
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value

fanone 這個key是string類型,但是無法通過SADD命令將fanone變成set類型。雖然在入隊列的時候,redis沒有報錯,但是在EXEC的時候,redis報了,所以這個key一開始是string類型,事務執行完后也會是string類型,事務執行前后保持了一致。

在這里插入圖片描述

隔離性 Isolation

事務的隔離型是指**即使數據庫中有多個事務并發的執行,各個事務之間也不會互相影響,并且在并發狀態下執行的事務和穿行執行的事務的結果是完成相同的。**

在這里插入圖片描述

因為Redis是使用單線程的方式來執行事務以及事務隊列中的命令,并且在服務器穩定的情況下,執行事務不會中斷,因此,redis的事務總是串行的方式執行的,所以具備隔離性。
在這里插入圖片描述

持久性 Durability

事務的持久性值得是當一個事務執行完畢的時候,執行這個事務所得的結果已經被保存到永久性存儲介質里面了,即使服務器在事務執行完畢之后停機,執行事務所得的結果也不會丟失。

由于Redis的事務比較簡潔,沒有提供持久化的能力,所以Redis的事務是依賴于Redis所使用的持久話模式,也就是AOF、RDB,我們一個個來討論

  • 當服務器無持久化運行的時候,事務不具備持久性,一旦服務器宕機,事務數據將會丟失。

  • 當服務器在RDB持久化模式下運作的時候,服務器只會在特定的保存條件下滿足,比如使用BGSAVE命令,隊數據庫進行保存,但是異步執行的BGSAVE也不能保證,第一時間保存在硬盤中,因此RDB持久化模式下事務不具備持久性
    在這里插入圖片描述

  • 而當服務器運行在AOF持久話模式下,并且appendfsync選項是always的時候,服務器總會在執行完命令之后調用同步sync函數,將命令數據保存在硬盤中,而此時事務具備持久性,其他選擇比如everysec或者no的時候都不具備持久性。

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/77408.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/77408.shtml
英文地址,請注明出處:http://en.pswp.cn/web/77408.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

LeetCode --- 446 周賽

題目列表 3522. 執行指令后的得分 3523. 非遞減數組的最大長度 3524. 求出數組的 X 值 I 3525. 求出數組的 X 值 II 一、執行指令后的得分 照著題目要求進行模擬即可&#xff0c;代碼如下 // C class Solution { public:long long calculateScore(vector<string>&…

山東大學軟件學院項目實訓-基于大模型的模擬面試系統-前端美化滾動條問題

模擬面試界面左側底部 通過檢查工具定位到其所在的位置&#xff1a; 直接對該組件進行美化&#xff1a; <!-- AI面試官列表 --><div class"ai-interviewer-section" v-show"activeTab interviewer"><el-scrollbar class"no-horizont…

git版本回退 | 遠程倉庫的回退 (附實戰Demo)

目錄 前言1. 基本知識2. Demo3. 彩蛋 前言 &#x1f91f; 找工作&#xff0c;來萬碼優才&#xff1a;&#x1f449; #小程序://萬碼優才/r6rqmzDaXpYkJZF 爬蟲神器&#xff0c;無代碼爬取&#xff0c;就來&#xff1a;bright.cn 本身暫存區有多個文件&#xff0c;但手快了&…

什么事Nginx,及使用Nginx部署vue項目(非服務器Nginx壓縮包版)

什么是 Nginx? Nginx(發音為 “engine-x”)是一個高性能的 HTTP 和反向代理服務器,也是一個 IMAP/POP3/SMTP 代理服務器。它以其高性能、高并發處理能力和低資源消耗而聞名。以下是 Nginx 的主要特性和用途: 主要特性 高性能和高并發 Nginx 能夠處理大量并發連接,適合高…

第十六周藍橋杯2025網絡安全賽道

因為只會web&#xff0c;其他方向都沒碰過&#xff0c;所以只出了4道 做出來的&#xff1a; ezEvtx 找到一個被移動的文件&#xff0c;疑似被入侵 提交flag{confidential.docx}成功解出 flag{confidential.docx} Flowzip 過濾器搜索flag找到flag flag{c6db63e6-6459-4e75-…

高性能的開源網絡入侵檢測和防御引擎:Suricata介紹

一、Debian下使用Suricata 相較于Windows&#xff0c;Linux環境對Suricata的支持更加完善&#xff0c;操作也更為便捷。 1. 安裝 Suricata 在Debian系統上&#xff0c;你可以通過包管理器 apt 輕松安裝 Suricata。 更新軟件包列表: sudo apt update安裝 Suricata: sudo apt …

IP-address-space

導航 (返回頂部) 1. IPv4地址分配表 1.2 IPv4 專用地址注冊表1.3 各國IPv4地址分配列表 2. IPv6地址分配表 2.1 IANA IPv6 專用地址注冊表2.2 IPv6 多播地址分配 1. IPv4地址分配表1.2 IPv4 專用地址注冊表1.3 各國IPv4地址分配列表 2. IPv6地址分配表2.1 IANA IPv6 專用地址…

Ubuntu使用war包部署Jenkins并通過systemcl管理

目錄 一、當前系統環境 二、安裝Java 二、安裝Jenkins 三、使用systemctl管理 一、當前系統環境 操作系統&#xff1a;ubuntu 24.04 Jenkins版本&#xff1a;2.506 格式&#xff1a;war JDK版本&#xff1a;OpenJDK_17 二、安裝Java 1.下載jdk安裝包 # wget下載 wget …

牛客 verilog入門 VIP

1、輸出1 答案&#xff1a; timescale 1ns/1nsmodule top_module(output wire one );assign one 1b1; endmodule 2、wire連線 答案&#xff1a; timescale 1ns/1nsmodule wire0(input wire in0,output wire out1 );assign out1 in0; endmodule 3、多wire連線 timescale 1…

簡易版2D我的世界C++程序(有點BUG,但是可以玩!!!)

1、按空格鍵來切換模式&#xff08;挖掘模式和放置模式&#xff09;&#xff0c;一律用鼠標右鍵來操作&#xff01;&#xff01;&#xff01; 2、按數字1和2鍵來切換放置的方塊&#xff08;1是草&#xff0c;2是木&#xff09;&#xff0c;樹葉不能放置&#xff01;&#xff01…

ubuntu使用dify源碼安裝部署教程+避坑指南

很多人,包括我在最初使用dify的時候都習慣使用docker來部署安裝環境,但在二次開發使用過程中,我們可能希望使用源碼來安裝,那么這篇文章我將給大家分享如何在ubuntu系統下使用源碼安裝,并提供大家遇到的疑難雜癥如下: dify安裝使用過程中報錯:/console/api/workspaces/…

java知識體系結構導航

很全&#xff1a;java知識體系結構 個人筆記鏈接 開發工具IDEA IDEA 插件推薦清單 IDEA快捷鍵大全 Java基礎難點 基礎知識_java動態代理 基礎知識_java反射機制 基礎知識-java流steam 基礎知識-java集合collection Spring 01.Spring 框架的演化&#xff1a;從 XML 配置到…

RabbitMQ 的專業術語

術語定義示例/說明生產者&#xff08;Producer&#xff09;發送消息到 RabbitMQ 的客戶端應用程序。日志系統將錯誤信息發送到 RabbitMQ。消費者&#xff08;Consumer&#xff09;從 RabbitMQ 隊列中接收并處理消息的客戶端應用程序。一個訂單處理服務從隊列中讀取消息并更新數…

mac安裝vm虛擬機安裝包

因為mac安裝虛擬機時&#xff0c;發現下載過程變得不太一樣&#xff0c;會比較麻煩。所以決定發一下我已經下載的安裝包&#xff0c;個人用戶使用免費&#xff0c;商業版請自行去官網下載&#xff01; 百度網盤下載鏈接 百度網盤 請輸入提取碼 提取碼:d4rc

LLama Factory從入門到放棄

目錄 簡介 安裝 LLama Factory界面介紹 數據格式要求 微調訓練 今天在這里介紹一種常用的大模型微調框架——LLama Factory。 簡介 LLama Factory 是一個高效的界面化大語言模型微調工具庫&#xff0c;支持多種參數高效微調技術&#xff0c;提供簡潔接口和豐富示例&#…

如何借助全球動態IP實現多平臺賬號的批量注冊?

無論是社交網絡、在線購物平臺還是專業應用軟件&#xff0c;賬號的創建和使用都是必不可少的。然而&#xff0c;在面對不同平臺各自的注冊限制和策略時&#xff0c;如何高效、安全且合法地進行賬號批量注冊成為了亟待解決的問題。本文將探討全球動態IP在這一過程中的作用及其如…

django admin 添加自定義頁面

在Django中&#xff0c;你可以通過多種方式向Django Admin添加自定義頁面。以下是一些常見的方法&#xff1a; 方法1&#xff1a;使用ModelAdmin的get_urls()方法 如果你只是想添加一個簡單的頁面來展示信息&#xff0c;你可以在你的ModelAdmin類中重寫get_urls()方法。 from…

Docker容器持久化

引言 Docker 容器作為一種輕量級、可移植的虛擬化技術&#xff0c;廣泛應用于開發、測試和生產環境中。然而&#xff0c;容器天生是短暫的&#xff0c;意味著它們在生命周期結束后會被銷毀&#xff0c;而其中的數據也會隨之丟失。為了確保容器中的數據能夠持久化&#xff0c;我…

ShaderToy學習筆記 02.圓

1. 畫圓 1.1. 圓的方程 圓的方程是&#xff1a;(x^2 y^2 r^2)&#xff0c;其中(r)是圓的半徑。 我們可以使用 desmos 來驗證一下。 輸入 x^2 y^2 -10&#xff0c;即可得到圓。 類似下圖 1.2. 畫圓的方式 畫圓&#xff1a;使用圓的方程&#xff0c;判斷每個像素點是否在圓…

一文詳解卷積神經網絡中的卷積層和池化層原理 !!

文章目錄 前言 一、卷積核大小&#xff08;Kernel Size&#xff09; 1. 卷積核大小的作用 2. 常見的卷積核大小 3. 選擇卷積核大小的原則 二、步長&#xff08;Stride&#xff09; 1. Stride的作用 三、填充&#xff08;Padding&#xff09; 1. 填充的作用 四、通道數&#xff…