Redis 事務支援 ACID 嗎?以下這篇文章帶大家了解一下Redis的事務,介紹一下Redis實現事務的方法,聊聊Redis 事務支援 ACID嗎,希望對大家有幫助!
騰訊面試官:「Redis 的事務了解麼?它的事務機制能實現ACID 屬性麼?」
程許遠:「撓頭,這個…我知道lua 腳本能實現事務…」
騰訊面試官:「好的,回去等通知吧。」
##碼哥,我斬獲了很多offer,沒想到最後敗在了「Redis 如何實現事務?」這個問題。我們來一步一步分析:
- 什麼是交易 ACID?
- Redis 如何實作交易?
- Redis 的事務能實現哪些屬性?
- Lua 腳本實作。
什麼是事務的ACID
鬼吹燈之《雲南蟲谷》中的摸金校尉有句話叫「合則生,分則死」,為了尋找雮塵珠他們三人分工明確、齊心協力共進退方可成功。
交易(Transaction)是並發控制單位,一個操作序列組合而成,這些操作要么都執行,要么都不執行。 【相關推薦:Redis影片教學】
「是一個不可分割的工作單位」。 事務在執行時,會提供專門的屬性保證:- 原子性(Atomicity):一個事務的多個操作必須完成,或者都不完成( ps:MySQL 的原子性靠什麼實現呢?歡迎留言區評論);
- #一致性(Consistency):事務執行結束後,資料庫的完整性限制沒有被破壞,事務執行的前後順序都是合法資料狀態。 資料庫的完整性限制包括但不限於:
- 實體完整性(如行的主鍵存在且唯一);
- 列完整性(如字段的類型、大小、長度要符合要求)
- 外鍵約束;
- 使用者自訂完整性(如轉帳前後,兩個帳戶餘額的和應該不變)。
- 隔離性(Isolation):交易內部的操作與其他交易是隔離的,並發執行的各個事務之間不能互相干擾。 講究的是不同事務之間的相互影響,嚴格的隔離性對應隔離等級中的可串行化(Serializable)。
- 持久性(Durability):交易一旦提交,所有的修改將永久的保存到資料庫中,即使系統崩潰重啟後資料也不會遺失。
碼哥,了解了 ACID 的特定要求後,Redis 如何實現事務機制?
Redis 如何實作交易
MULTI、EXEC、DISCARD 和WATCH 指令是Redis 實作交易的基礎。
Redis 交易的執行過程包含三個步驟:- 開啟交易;
- 指令入隊;
- 執行交易或丟棄;
#明確開啟一個交易
客戶端透過MULTI 指令明確表示開啟一個事務,隨後的指令將排隊緩存,並不會實際執行。
命令入隊
客戶端把事務中的要執行的一系列指令傳送到服務端。 要注意的是,雖然指令傳送到服務端,但是 Redis 實例只是把這一系列指令暫存在一個指令佇列中,並不會立刻執行。執行交易或丟棄
客戶端向服務端發送提交或丟棄交易的命令,讓Redis 執行第二步驟中發送的具體指令或清空佇列指令,放棄執行。 Redis 只要在呼叫EXEC 時,即可安排佇列指令執行。
也可透過DISCARD 丟棄第二步驟中保存在佇列中的指令。
Redis 事務案例
透過線上偵錯網站執行我們的範例程式碼:try.redis.io
#正常執行
透過MULTI
和EXEC
執行一個事務程序:
# 开启事务 > MULTI OK # 开始定义一些列指令 > SET “公众号:码哥字节” "粉丝 100 万" QUEUED > SET "order" "30" QUEUED > SET "文章数" 666 QUEUED > GET "文章数" QUEUED # 实际执行事务 > EXEC 1) OK 2) OK 3) OK 4) "666"
我們看到每個讀寫指令執行後的回傳結果都是QUEUED
,表示謝謝操作都被暫存到了命令隊列,還沒有實際執行。
當執行了 EXEC
指令,就可以看到具體每個指令的回應資料。
放棄交易
透過MULTI
和DISCARD
丟棄佇列指令:
# 初始化订单数 > SET "order:mobile" 100 OK # 开启事务 > MULTI OK # 订单 - 1 > DECR "order:mobile" QUEUED # 丢弃丢列命令 > DISCARD OK # 数据没有被修改 > GET "order:mobile" "100"
#碼哥,Redis 的事務能保證ACID 特性麼?
這個問題問得好,我們一起來分析下。
Redis 事務滿足 ACID?
Redis 交易可以一次執行多個命令, 並且帶有以下三個重要的保證:
- ##批次指令在執行EXEC 指令之前會放入佇列暫存;
- 收到EXEC 指令後進入事務執行,事務中任意指令執行失敗,其餘的指令依然被執行;
- 事務執行過程中,其他客戶端提交的命令不會插入到目前命令執行的序列中。
原子性
#碼哥,如果事務執行過程中發生錯誤了,原子效能保證麼?在交易期間,可能遇到兩種指令錯誤:
- 在執行
- EXEC
指令前,發送的指令本身就錯誤。如下:
- 參數數量錯誤;
- 命令名稱錯誤,使用了不存在的命令;
- 記憶體不足(Redis 實例使用
- maxmemory
指令配置內存限制)。
在執行 - EXEC
指令後,指令可能會失敗。例如,命令和操作的資料類型不符(對 String 類型 的 value 執行了 List 清單操作);
在執行交易的 - EXEC
命令時。 Redis 實例發生了故障導致交易執行失敗。
EXEC 執行前報錯誤
在命令入隊時,Redis 就會報錯並且記錄下這個錯誤。
此時,我們還能繼續提交指令操作。
等到執行了EXEC指令之後,Redis 就會
拒絕執行所有提交的命令操作,回傳事務失敗的結果。
事務中的所有指令都不會再被執行了,保證了原子性。
如下是指令入隊發生錯誤,導致交易失敗的例子:#开启事务 > MULTI OK #发送事务中的第一个操作,但是Redis不支持该命令,返回报错信息 127.0.0.1:6379> PUT order 6 (error) ERR unknown command `PUT`, with args beginning with: `order`, `6`, #发送事务中的第二个操作,这个操作是正确的命令,Redis把该命令入队 > DECR b:stock QUEUED #实际执行事务,但是之前命令有错误,所以Redis拒绝执行 > EXEC (error) EXECABORT Transaction discarded because of previous errors.
EXEC 執行後報錯
事務操作入隊時,命令和操作的資料類型不匹配,但Redis 實例沒有檢查出錯誤。 但是,執行完 EXEC 指令以後,Redis 實際執行這些指令,就會報錯。敲黑板了:Redis 雖然會對錯誤指令報錯,但是事務依然會把正確的命令執行完,這時候事務的原子性就無法保證了!
碼哥,為什麼 Redis 不支援回溯?其實,Redis 中並沒有提供回溯機制。雖然 Redis 提供了 DISCARD 命令。 但是,這個指令只能用來主動放棄交易執行,把暫存的指令佇列清空,起不到回滾的效果。
EXEC 執行時,發生故障
如果 Redis 開啟了 AOF 日誌,那麼,只會有部分的交易操作被記錄到 AOF 日誌中。 我們需要使用 redis-check-aof 工具檢查 AOF 日誌文件,這個工具可以把未完成的事務操作從 AOF 文件中移除。 這樣一來,我們使用 AOF 恢復實例後,事務操作就不會再被執行,從而保證了原子性。簡單總結:
- 命令入隊時就報錯,會放棄事務執行,保證原子性;
- 命令入隊時沒報錯,實際執行時報錯,不保證原子性;
- EXEC 指令執行時實例故障,如果開啟了AOF 日誌,可以保證原子性。
一致性
一致性會受到錯誤指令、執行個體故障發生時機的影響,依照指令出錯實例故障兩個維度的發生時機,可以分成三種情況來分析。EXEC 執行前,入隊報錯
事務會被放棄執行,所以可以保證一致性。EXEC 執行後,實際執行時報錯誤
有錯誤的執行不會執行,正確的指令可以正常執行,一致性可以保證。EXEC 執行時,實例故障
實例故障後會進行重啟,這就和資料復原的方式有關了,我們要根據實例是否開啟了RDB 或AOF 來分情況討論下。如果我們沒有開啟 RDB 或 AOF,那麼,在實例故障重新啟動後,資料都沒有了,資料庫是一致的。
如果我們使用了 RDB 快照,因為 RDB 快照不會在交易執行時執行。
所以,交易指令操作的結果不會被儲存到 RDB 快照中,使用 RDB 快照進行復原時,資料庫裡的資料也是一致的。
如果我們使用了 AOF 日誌,而交易操作還沒有被記錄到 AOF 日誌時,實例就發生了故障,那麼,使用 AOF 日誌復原的資料庫資料是一致的。
如果只有部分操作被記錄到了 AOF 日誌,我們可以使用 redis-check-aof 清除交易中已經完成的操作,資料庫復原後也是一致的。
隔離性
交易執行又可以分成指令入隊(EXEC 指令執行前)和指令實際執行(EXEC 指令執行後)兩個階段。
所以在並發執行的時候我們針對這兩個階段分兩種情況分析:
並發操作在
EXEC
指令前執行,隔離性需要透過WATCH
機制保證;並發操作在
EXEC
指令之後,隔離性可以保證。
碼哥,什麼是 WATCH 機制?
我們重點來看第一種情況:當一個事務的 EXEC 指令還沒執行時,事務的指令操作是暫存在指令佇列中的。
此時,如果有其它的並發操作,同樣的 key 被修改,需要看交易是否使用了 WATCH
機制。
WATCH 機制的作用是:在交易執行前,監控一個或多個鍵的值變化情況,當交易呼叫EXEC 指令執行時,WATCH 機制會先檢查監控的鍵是否被其它客戶端修改了。
如果修改了,就放棄交易執行,避免事務的隔離性被破壞。
同時,客戶端可以再次執行事務,此時,如果沒有並發修改事務資料的操作了,事務就能正常執行,隔離性也得到了保證。
沒有 WATCH
如果沒有 WATCH 機制, 在 EXEC 指令執行前的並發操作對資料讀寫。
當執行 EXEC 的時候,事務內部要操作的資料已經改變,Redis 並沒有做到事務之間的隔離。
並發操作在EXEC 之後接收執行
至於第二種情況,因為Redis 是用單執行緒執行指令,而且,EXEC 指令執行後,Redis 會保證先把指令佇列中的所有指令執行完再執行之後的指令。
所以,在這種情況下,並發操作不會破壞交易的隔離性。
持久性
#如果Redis 沒有使用RDB 或AOF,那麼交易的持久化屬性肯定得不到保證。
如果Redis 使用了RDB 模式,那麼,在一個事務執行後,而下一次的RDB 快照還未執行前,如果發生了實例宕機,資料遺失,這種情況下,事務修改的數據也是不能保證持久化的。
如果 Redis 採用了 AOF 模式,因為 AOF 模式的三個設定選項 no、everysec 和 always 都會存在資料遺失的情況。
所以,事務的持久性屬性也還是得不到保證。
不管 Redis 採用什麼持久化模式,交易的持久性屬性是得不到保證的。
總結
- #Redis 具備了一定的原子性,但不支援回滾。
- Redis 不具備 ACID 中一致性的概念。 (或者說 Redis 在設計時就無視這點)
- Redis 具備隔離性。
- Redis 無法保證持久性。
Redis 的交易機制可以保證一致性和隔離性,但無法保證持久性。
不過,因為 Redis 本身就是記憶體資料庫,持久性並不是一個必須的屬性,我們更加關注的還是原子性、一致性和隔離性這三個屬性。
原子性的情況比較複雜,當事務中使用的命令語法有誤時,原子性得不到保證,在其它情況下,事務都可以原子性執行。
更多程式相關知識,請造訪:程式設計入門! !
以上是什麼是事務的ACID? Redis事務能實現ACID嗎?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

Redis是现在最热门的key-value数据库,Redis的最大特点是key-value存储所带来的简单和高性能;相较于MongoDB和Redis,晚一年发布的ES可能知名度要低一些,ES的特点是搜索,ES是围绕搜索设计的。

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了关于redis的一些优势和特点,Redis 是一个开源的使用ANSI C语言编写、遵守 BSD 协议、支持网络、可基于内存、分布式存储数据库,下面一起来看一下,希望对大家有帮助。

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了Redis Cluster集群收缩主从节点的相关问题,包括了Cluster集群收缩概念、将6390主节点从集群中收缩、验证数据迁移过程是否导致数据异常等,希望对大家有帮助。

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了Redis实现排行榜及相同积分按时间排序,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,希望对大家有帮助。

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了关于原子操作中命令原子性的相关问题,包括了处理并发的方案、编程模型、多IO线程以及单命令的相关内容,下面一起看一下,希望对大家有帮助。

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了bitmap问题,Redis 为我们提供了位图这一数据结构,位图数据结构其实并不是一个全新的玩意,我们可以简单的认为就是个数组,只是里面的内容只能为0或1而已,希望对大家有帮助。

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了Redis实现排行榜及相同积分按时间排序,本文通过实例代码给大家介绍的非常详细,下面一起来看一下,希望对大家有帮助。

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了关于实现秒杀的相关内容,包括了秒杀逻辑、存在的链接超时、超卖和库存遗留的问题,下面一起来看一下,希望对大家有帮助。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器

Dreamweaver Mac版
視覺化網頁開發工具

SublimeText3 英文版
推薦:為Win版本,支援程式碼提示!

記事本++7.3.1
好用且免費的程式碼編輯器