Redis事務

Redis事務通過MULTI、EXEC、WATCH等命令來實現(xiàn)。事務提供一種將多個命令請求打包,然后一次性、按順序地執(zhí)行多個命令的機制,并且在事務執(zhí)行期間,服務器不會執(zhí)行其他客戶端的命令請求。

事務的實現(xiàn)

事務的三個階段:

  1. 事務開始
    MULTI命令會將客戶端的flags屬性打開REDIS_MULTI標識,意味著事務開始。

  2. 命令入隊
    當客戶端處于事務狀態(tài)時,服務器根據(jù)不同的命令會有不同的表現(xiàn):

  • 若是EXEC、DISCARD、WATCH、MULTI命令,則服務器立即執(zhí)行命令;
  • 否則,命令放入一個事務隊列中。


    image

每個Redis客戶端都有自己的事務狀態(tài),保存在mstate屬性中,mstate中包含一個事務隊列,事務隊列是一個multiCmd數(shù)組,數(shù)組中每個元素保存了一個已入隊命令的相關(guān)信息:

typedef struct redisClient {
... ...
multiState mstate;    // 事務狀態(tài)
... ...
} redisClient;

typedef struct multiState {
multiCmd *commands;  // 事務隊列,F(xiàn)IFO順序
int count;                         // 已入隊命令計數(shù)
} multiState;

typedef struct multiCmd {
robj **argv;                             // 參數(shù)
int argc;                                   // 參數(shù)數(shù)量
struct redisCommand *cmd; // 命令指針
} multiCmd;
image
  1. 事務執(zhí)行
    當一個處于事務狀態(tài)的客戶端向服務器發(fā)送EXEC命令時,服務器會遍歷這個客戶端的事務隊列,執(zhí)行隊列中保存的所有命令,最后將執(zhí)行命令所得到的結(jié)果全部返回給客戶端。

WATCH命令的實現(xiàn)

WATCH命令是一個樂觀鎖,在EXEC命令執(zhí)行之前監(jiān)視任意數(shù)量的數(shù)據(jù)庫鍵,并在EXEC執(zhí)行時,檢查被監(jiān)視的鍵是否有被修改過了(被另一個客戶端修改了),如果是的話服務器將拒絕執(zhí)行事務,并向客戶端返回表示事務執(zhí)行失敗的空回復。

每個Redis數(shù)據(jù)庫都保存著一個watch_keys字典,鍵是被WATCH命令監(jiān)視的數(shù)據(jù)鍵,值是一個鏈表,鏈表記錄了所有監(jiān)視對應鍵的客戶端:

typedef struct redisDb {
... ...
dict *watch_keys;   // 正被WATCH監(jiān)視的鍵
... ...
} redisDb;
image

所有對數(shù)據(jù)庫進行修改的命令,包括SET、LPUSH、SADD、ZREM、DEL、FLUSHDB等,在執(zhí)行之后都會對watch_keys進行檢查,查看是否有客戶端正在監(jiān)視剛剛被修改的數(shù)據(jù)庫鍵,若有則將被修改鍵的客戶端的REDIS_DIRTY_CAS標識打開,表示蓋客戶端的事務安全性已經(jīng)被破壞。

當服務器接收到客戶端發(fā)來的EXEC命令,服務器根據(jù)這個客戶端是否打開了REDIS_DIRTY_CAS標識來決定是否執(zhí)行事務:


image

事務的ACID性質(zhì)

事務的ACID性質(zhì):原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)和耐久性(Durability)。

  • 原子性
    事務的原子性是指數(shù)據(jù)庫將事務中的多個操作當作一個整體來執(zhí)行,服務器要么就執(zhí)行所有的操作,要么一個操作也不執(zhí)行。
    Redis不支持事務回滾機制,即使事務隊列中某個命令在執(zhí)行期間出現(xiàn)錯誤,整個事務也會繼續(xù)執(zhí)行下去,直到將事務隊列的所有命令都執(zhí)行完畢為止。
  • 一致性
    事務的一致性是指如果事務執(zhí)行之前是一致的,那么事務執(zhí)行之后,無論事務是否執(zhí)行成功,數(shù)據(jù)庫也應該是一致的。一致指的是數(shù)據(jù)符合數(shù)據(jù)庫本身的定義和要求,沒有包含非法或者無效的錯誤數(shù)據(jù)。
    Redis通過錯誤檢測和簡單的設(shè)計來保證事務的一致性:
    1. 入隊錯誤
      如果一個事務在入隊命令的過程中,出現(xiàn)了命令不存在火災命令格式錯誤等情況,那么Redis將拒絕執(zhí)行這個事務。
    2. 執(zhí)行錯誤
      事務執(zhí)行過程中還可能出現(xiàn)錯誤,這些錯誤無法在入隊時發(fā)現(xiàn),只會在執(zhí)行時觸發(fā);即使在事務執(zhí)行過程中發(fā)生了錯誤,服務器也不會中斷事務的執(zhí)行,它會繼續(xù)執(zhí)行事務中余下的其他命令,并且已執(zhí)行的命令不會被出錯的命令影響。
    3. 服務器停機
      若Redis服務器在執(zhí)行事務時停機,那么根據(jù)使用的持久化模式,可能有以下情況:
      • 若服務器運行在無持久化的內(nèi)存模式下,那么重啟后數(shù)據(jù)庫將是空白的,因此數(shù)據(jù)總是一致的;
      • 若服務器運行在RDB模式下,那么事務在中途停機不會導致不一致性,因為服務器可以根據(jù)現(xiàn)有的RDB文件來恢復數(shù)據(jù),從而將數(shù)據(jù)庫還原到一個一致狀態(tài)。如果找不到RDB文件,那么重啟后數(shù)據(jù)庫將是空白的,也是一致的;
      • 若服務器運行在AOF模式下,那么事務在中途停機不會導致不一致性,因為服務器可以根據(jù)現(xiàn)有的AOF文件來恢復數(shù)據(jù),從而將數(shù)據(jù)庫還原到一個一致狀態(tài)。如果找不到AOF文件,那么重啟后數(shù)據(jù)庫將是空白的,也是一致的。
  • 隔離性
    事務的隔離性指的是即使數(shù)據(jù)庫中多個事務并發(fā)地執(zhí)行,各個事務之間也不會相互影響,并且在并發(fā)狀態(tài)下執(zhí)行的事務和串行執(zhí)行的事務產(chǎn)生的結(jié)果相同。
  • 耐久性
    事務的耐久性是指當一個事務執(zhí)行完畢,執(zhí)行這個事務所得的結(jié)果已被保存到永久性存儲介質(zhì)中,即使服務器在事務執(zhí)行完畢后停機,事務所得結(jié)果也不會丟失。
    因為Redis事務使用隊列包裹一組Redis命令,并沒有提供持久化功能,所以Redis事務的耐久性由Redis所使用的持久化模式?jīng)Q定:
    • 當服務器在無持久化的內(nèi)存模式下運行,事務不具有耐久性:一旦服務器停機,所有數(shù)據(jù)庫數(shù)據(jù)都將丟失;
    • 當服務器運行在RDB模式,服務器只會在特定的保存條件被滿足時才會執(zhí)行BGSAVE命令保存數(shù)據(jù),并且BGSAVE不能保證事務數(shù)據(jù)被第一時間保存到硬盤中,因此不具有耐久性;
    • 當服務器運行在AOF模式,并且appendfsync選項的值為always時,程序總會在執(zhí)行命令之后調(diào)用同步函數(shù),并將數(shù)據(jù)真正保存到硬盤里,具有耐久性;
    • 當服務器運行在AOF模式,并且appendfsync選項的值為everysec時,程序每秒會同步一次數(shù)據(jù),若是停機剛好發(fā)送在等待同步的1s內(nèi),則會造成數(shù)據(jù)丟失,不具有耐久性;
    • 當服務器運行在AOF模式,并且appendfsync選項的值為no時,程序交由操作系統(tǒng)來決定何時將數(shù)據(jù)同步到硬盤中,數(shù)據(jù)可能在等待同步的過程中丟失,不具有耐久性;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

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

  • redis事務 Redis 通過 MULTI 、 DISCARD 、 EXEC 和 WATCH 四個命令來實現(xiàn)事務...
    全能程序猿閱讀 2,253評論 0 11
  • 在多個客戶端同時處理相同的數(shù)據(jù)時,不謹慎的操作很容易導致數(shù)據(jù)出錯。一般的關(guān)系型數(shù)據(jù)庫中有事務保證了數(shù)據(jù)操作的原子性...
    rainybowe閱讀 3,551評論 0 5
  • redis 是一個高性能的key-value 數(shù)據(jù)庫。作為no sql 數(shù)據(jù)庫redis 與傳統(tǒng)關(guān)系型數(shù)據(jù)庫相比有...
    點融黑幫閱讀 3,000評論 1 15
  • 1. 概述: 和眾多其它數(shù)據(jù)庫一樣,Redis作為NoSQL數(shù)據(jù)庫也同樣提供了事務機制。在Redis中,MULTI...
    六月星空2011閱讀 376評論 0 0
  • 量化自身,是為了更好地了解自己 簡單記錄一下目前量化自身的方法。 時間都去哪兒了 RescueTime 我大部分的...
    luciferz2012閱讀 632評論 1 4

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