目錄
- 前言
- 《Redis常用命令及示例總結(API)》:https://www.cnblogs.com/dlhjw/p/15639773.html
- 1. 發布訂閱
- 1.1 頻道的訂閱與退訂
- 1.2 模式的訂閱與退訂
- 1.3 發送訊息
- 1.4 查看訂閱訊息
- 2. 事務
- 2.1 事務的實作
- 2.2 WATCH 命令的實作
- 2.3 事務的 ACID 性質
- 最后
前言
參考資料:《Redis設計與實作 第二版》;
第三部分為獨立功能的實作,主要由以下模塊組成:發布訂閱、事務、Lua 腳本、排序、二進制位陣列、慢查詢日志、監視器;
本篇將介紹 Redis 的發布訂閱與事務,Redis 提供了頻道與模式的訂閱與退訂,支持對頻道發送訊息,Redis 的事務機制支持一次性、按順序執行多個命令,以及事務的 ACID 性質;
與本章相關的 Redis 命令總結在下篇文章,歡迎點擊收藏,本篇將不再重復:
《Redis常用命令及示例總結(API)》:https://www.cnblogs.com/dlhjw/p/15639773.html
1. 發布訂閱
1.1 頻道的訂閱與退訂
-
客戶端使用 SUBSCRIBE 命令訂閱某個或某些頻道;
-
客戶端使用 UNSUBSCRIBE 命令退訂頻道;
-
Redis 將所有頻道的訂閱關系保存在服務器狀態的
pubsub_challens字典里:struct redisService{ //... //保存所有頻道的訂閱關系 dict *pubsub_channels; };

- 頻道訂閱的情況:
- 頻道已有其他訂閱者,則將客戶端添加到訂閱者鏈表末端;
- 反之,字典里沒有該頻道,則創建一個鍵值對項;
- 頻道退訂的情況:
- 找到頻道對應鏈表,洗掉客戶端資訊;
- 若洗掉后鏈表長度為0,則洗掉鍵;

1.2 模式的訂閱與退訂
-
客戶端使用 PSUBSCRIBE 命令訂閱某個或某些模式;
-
客戶端使用 PUNSUBSCRIBE 命令退訂模式;
-
Redis 將所有模式的訂閱關系保存在服務器狀態的
pubsub_patterns鏈表里:struct redisServer{ //... //保存所有模式訂閱關系,記錄被訂閱的模式 list *pubsub_patterns; }; -
pubsub_patterns鏈表保存的結構體如下:typedef struct pubsubPattern{ //訂閱模式的客戶端 redisClient *client; //被訂閱的模式 robj *pattern; } pubsubPattern;

- 客戶端在訂閱模式時,會創建一個
pubsubPattern結構體,并添加到鏈表尾部; - 客戶端在退訂模式時,遍歷鏈表洗掉對應模式;

1.3 發送訊息
- 客戶端執行 PUBLISH channel message 命令將 message 訊息發送給 channel 頻道,然后服務器將訊息發送給頻道與模式訂閱者;
- 將訊息發送給頻道訂閱者:
- 在
pubsub_channels字典里找到頻道channel的所有訂閱者名單(鏈表),然后將訊息發送給名單上的所有客戶端;
- 在
- 將訊息發送給模式訂閱者:
- 遍歷
pubsub_patterns鏈表,查找與channel頻道相匹配的模式,然后將訊息發送給訂閱了這些模式的客戶端;
- 遍歷


1.4 查看訂閱訊息
- 客戶端使用 PUBSUB 命令查看頻道或模式的相關資訊;
- PUBSUB CHANNELS [pattern] 命令用于回傳服務器當前被訂閱的頻道;
- PUBSUB NUMSUB [channel ...] 命令接受任意多個頻道作為輸入引數,回傳這些頻道的訂閱者數量,通過查詢
pubsub_channels字典中對應頻道鍵的鏈表值的長度; - PUBSUB NUMPAT 命令用于回傳服務器當前被訂閱模式的數量,通過查詢
pubsub_patterns鏈表的長度;
2. 事務
- 事務提供一種將多個命令打包,然后一次性、按順序執行多個命令的機制;
- 并且在事務執行期間,服務器不會中斷事務而改去執行其他客戶端的命令請求;
2.1 事務的實作
- 事務開始:
- 使用 MULTI 命令;
- 通過修改客戶端狀態中
flags屬性為 REDIS_MULTI 實作;
- 命令入隊:
- 當客戶端切換到事務模式時,會根據命令不同采取不同的操作;
- 與事務相關的命令有:EXEC、DISCARD、WATCH、MULTI;

- 事務佇列:
-
Redis 客戶端里有事務狀態屬性
mstate:typedef struct redisClient{ //... //事務狀態 multiState mstate; } redisClient; -
multiState事務狀態結構,包含事務佇列與計數器:typedef struct multiState{ //事務佇列,FIFO排序 multiCmd *commands; //已入隊命令計數 int count; } multiState;
-

- 執行事務:
- 處于事務狀態的客戶端向服務器發送 EXEC 命令時,會執行事務;
- 服務器遍歷客戶端的事務佇列,執行佇列中保存的所有命令,將執行結果回傳給客戶端;
2.2 WATCH 命令的實作
-
WATCH 命令是一個樂觀鎖;
-
在執行 EXEC 命令前:監視任意數量的資料庫建;
-
在執行 EXEC 命令時:檢查被監視的鍵是否至少有一個已經被修改,是則拒絕執行事務,回傳錯誤;
-
Redis 資料庫保存一個
watched_keys字典:typedef struct redisDb{ //... // 字典,鍵表示被 WATCH 命令監視的資料庫鍵;值為鏈表,記錄監視該鍵的客戶 端 dict *watched_keys; } redisDb; -
所有對資料庫進行修改的命令,在執行后都會呼叫
multi.c/touchWatchKey函式對watched_keys字典進行檢查:- 如果有客戶端監視被修改的鍵,則將客戶端的 REDIS_DIRTY_CAS 標識打開,表示客戶端的事務安全性被破壞;
-
服務器接收到 EXEC 命令時,會根據客戶端是否打開 REDIS_DIRTY_CAS 標識決定是否執行事務:
- 如果打開,說明本次提交不安全,服務器會拒絕執行客戶端提交的事務;
- 否則說明事務安全,可以提交;

2.3 事務的 ACID 性質
- Redis 資料庫的事務具有原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、耐久性(Durability);
- 原子性:
- 事務佇列要么全部執行,要么一個都不執行;
- Redis 不支持事務回滾機制(rollback),事務佇列中某個命令在執行期間出現錯誤,后續事務也會繼續執行;
- 一致性:
- 一致指:資料符合資料庫本身的定義和要求,沒有包含非法或無效的錯誤資料;
- 資料庫在執行事務之前是一致的,在執行事務之后,無論事務是否成功,資料庫也應該是一致的;
- Redis 的一致性有:入隊錯誤、執行錯誤、服務器停機;
- 隔離性:
- 資料庫中多個事務并發執行,各個事務之間不會互相影響,并且與串行執行的結果相同;
- 原因:Redis 使用單執行緒方式執行事務以及事務佇列中的命令,且服務器保證在事務執行期間不會對事務中斷;
- 耐久性:
-
當一個事務執行完畢,執行事務所得的結果會被保存到永久性存盤介質;
-
Redis 的事務耐久性由持久化模式支持:
服務器的持久化模式 事務的耐久性 說明 無持久化模式 不具有 RDB 持久化模式 不具有 服務器只會在特定條件下執行 BGSAVE AOF 持久化模式,且 appendfsync的值為always具有 程式總在執行命令后呼叫同步函式 AOF 持久化模式,且 appendfsync的值為everysec不具有 程式每秒同步一次命令資料到硬碟 AOF 持久化模式,且 appendfsync的值為no不具有 同步操作由作業系統決定 服務器打開了 no-appendfsync-on-rewrite選項不具有 該選項打開時,服務器在執行 BGSAVE 或 BGREWRITEAOF 命令時,會暫時停止對 AOF 檔案進行同步(盡可能減少 I/O 阻塞) -
不管 Redis 在上面模式下運行,在事務最后加上 SAVE 命令總可以保證事務的耐久性,但因為效率低,不具有實用性;
-
最后

轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/374463.html
標籤:其他
上一篇:Oracle資料庫入門(二)
