Redis中的事務

所謂事務(Transaction) ,是指作為單個邏輯工作單元執(zhí)行的一系列操作

ACID回顧

1)Atomicity(原子性):構成事務的的所有操作必須是一個邏輯單元,要么全部執(zhí)行,要么全部不執(zhí)行。
Redis:一個隊列中的命令 執(zhí)行或不執(zhí)行
2)Consistency(一致性):數據庫在事務執(zhí)行前后狀態(tài)都必須是穩(wěn)定的或者是一致的。
Redis: 集群中不能保證時時的一致性,只能是最終一致性
3)Isolation(隔離性):事務之間不會相互影響。
Redis: 命令是順序執(zhí)行的,在一個事務中,有可能被執(zhí)行其他客戶端的命令的
4)Durability(持久性):事務執(zhí)行成功后必須全部寫入磁盤。
Redis有持久化但不保證 數據的完整性

Redis事務

1)Redis的事務是通過multi、exec、discard和watch這四個命令來完成的。
2)Redis的單個命令都是原子性的,所以這里需要確保事務性的對象是命令集合。
3)Redis將命令集合序列化并確保處于同一事務的命令集合連續(xù)且不被打斷的執(zhí)行
4)Redis不支持回滾操作

事務命令

multi:用于標記事務塊的開始,Redis會將后續(xù)的命令逐個放入隊列中,然后使用exec原子化地執(zhí)行這個命令隊列
exec:執(zhí)行命令隊列
discard:清除命令隊列
watch:監(jiān)視key
unwatch:清除監(jiān)視key


image.png
127.0.0.1:6379> multi 
OK
127.0.0.1:6379> set s1 222 
QUEUED 
127.0.0.1:6379> hset set1 name zhangfei 
QUEUED 
127.0.0.1:6379> exec 
1) OK
2) (integer) 1 
127.0.0.1:6379> multi 
OK
127.0.0.1:6379> set s2 333 
QUEUED 
127.0.0.1:6379> hset set2 age 23 
QUEUED 
127.0.0.1:6379> discard 
OK
127.0.0.1:6379> exec 
(error) ERR EXEC without MULTI 
127.0.0.1:6379> watch s1 
OK
127.0.0.1:6379> multi 
OK
127.0.0.1:6379> set s1 555 
QUEUED 
127.0.0.1:6379> exec # 此時在沒有exec之前,通過另一個命令窗口對監(jiān)控的s1字段進行修改
(nil) 
127.0.0.1:6379> get s1 
222 
127.0.0.1:6379> unwatch 
OK

事務機制

事務的執(zhí)行
  1. 事務開始
    在RedisClient中,有屬性flags,用來表示是否在事務中
    flags=REDIS_MULTI
  2. 命令入隊
    RedisClient將命令存放在事務隊列中
    (EXEC,DISCARD,WATCH,MULTI除外)
  3. 事務隊列
    multiCmd *commands 用于存放命令
  4. 執(zhí)行事務
    RedisClient向服務器端發(fā)送exec命令,RedisServer會遍歷事務隊列,執(zhí)行隊列中的命令,最后將執(zhí)行的結果一次性返回給客戶端。
    如果某條命令在入隊過程中發(fā)生錯誤,redisClient將flags置為REDIS_DIRTY_EXEC,EXEC命令將會失敗返回。


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

// 事務狀態(tài) 
typedef struct multiState{ 
    // 事務隊列,FIFO順序 
    // 是一個數組,先入隊的命令在前,后入隊在后 
    multiCmd *commands; 
    // 已入隊命令數 
    int count;
}multiState; 

// 事務隊列 
typedef struct multiCmd{ 
    // 參數 
    robj **argv; 
    // 參數數量 
    int argc; 
    // 命令指針 
    struct redisCommand *cmd;
}multiCmd;
Watch的執(zhí)行

使用WATCH命令監(jiān)視數據庫鍵
redisDb有一個watched_keys字典,key是某個被監(jiān)視的數據的key,值是一個鏈表.記錄了所有監(jiān)視這個數據的客戶端。
監(jiān)視機制的觸發(fā)
當修改數據后,監(jiān)視這個數據的客戶端的flags置為REDIS_DIRTY_CAS
事務執(zhí)行
RedisClient向服務器端發(fā)送exec命令,服務器判斷RedisClient的flags,如果為REDIS_DIRTY_CAS,則清空事務隊列。


image.png
typedef struct redisDb { 
    // ..... 
    // 正在被WATCH命令監(jiān)視的鍵 
    dict *watched_keys; 
    // ..... 
}redisDb;
Redis的弱事務性

Redis語法錯誤
整個事務的命令在隊列里都清除

127.0.0.1:6379> multi 
OK
127.0.0.1:6379> sets m1 44 
(error) ERR unknown command `sets`, with args beginning with: `m1`, `44`, 
127.0.0.1:6379> set m2 55 
QUEUED 
127.0.0.1:6379> exec 
(error) EXECABORT Transaction discarded because of previous errors. 
127.0.0.1:6379> get m1 
"22"

flags=REDIS_DIRTY_EXEC
Redis運行錯誤
在隊列里正確的命令可以執(zhí)行 (弱事務性)
弱事務性 :
1、在隊列里正確的命令可以執(zhí)行 (非原子操作)
2、不支持回滾

127.0.0.1:6379> multi 
OK
127.0.0.1:6379> set m1 55 
QUEUED 
127.0.0.1:6379> lpush m1 1 2 3 #不能是語法錯誤 
QUEUED 
127.0.0.1:6379> exec 
1) OK 
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value 
127.0.0.1:6379> get m1 
"55"

Redis不支持事務回滾(為什么呢)
1、大多數事務失敗是因為語法錯誤或者類型錯誤,這兩種錯誤,在開發(fā)階段都是可以預見的
2、Redis為了性能方面就忽略了事務回滾。 (回滾記錄歷史版本)

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

相關閱讀更多精彩內容

  • 本節(jié)來介紹一下Redis中的事務。 1.Oracle中的事務 Oracle中的事務,就是將一組DML操作打包執(zhí)行,...
    金字塔下的小蝸牛閱讀 157評論 0 0
  • 1、介紹 redis中的事務(transaction)是一組命令的集合,事務同命令一樣都是Redis最小的執(zhí)行單位...
    Geroge1226閱讀 272評論 0 1
  • redis中也能做到一些具備事務特性的操作,它可以一次執(zhí)行多個命令, 并且?guī)в幸韵氯齻€重要特征:(1)批量操作在發(fā)...
    張力的程序園閱讀 308評論 0 0
  • 事務: 事務提供了一種將多個命令請求打包,然后一次性按照順序的執(zhí)行多個命令的機制.并且在事務執(zhí)行期間,服務器不會中...
    王小帥_94閱讀 139評論 0 0
  • 提到事務大家一定都不陌生,在關系型數據庫MySql、Oracle中都存在事物,最常見的就是事物的提交(commit...
    郭之源閱讀 421評論 0 1

友情鏈接更多精彩內容