天天看點

Redis | 第4章 Redis中的資料庫《Redis設計與實作》

目錄

前言

1. Redis中的資料庫

2. 資料庫的鍵空間

3. 鍵的生成時間與過期時間

4. Redis中的過期鍵删除政策

5. AOF、RDB和複制功能對過期鍵的處理

5.1 生成 RDB 檔案

5.2 載入 RDB 檔案

5.3 AOF 檔案寫入

5.4 AOF 重寫

5.5 複制

6. 資料庫通知

最後

參考資料:《Redis設計與實作 第二版》;

第二部分為單機資料庫的實作,主要由以下子產品組成:資料庫、持久化、事件、用戶端與伺服器;

本篇将介紹 Redis 中的資料庫;

與本章相關的 Redis 指令總結在下篇文章,歡迎點選收藏,本篇将不再重複:

《Redis常用指令及示例總結(API)》:https://www.cnblogs.com/dlhjw/p/15639773.html

Redis伺服器的所有資料庫儲存在<code>redis.h/redisService</code>結構的db數組中:

<code>dbnum</code>屬性由伺服器配置的 database 選項決定,預設為 16;

Redis用戶端資料庫儲存在在<code>redisClient</code>結構的<code>db</code>屬性:

用戶端通過修改目标資料庫指針,讓它指向 redisService.db 數組中的不同元素;

可以通過 SELECT index 指令來切換資料庫;

Redis | 第4章 Redis中的資料庫《Redis設計與實作》

資料庫的定義在<code>redis.h/redisDb</code>結構中:

鍵空間的鍵是資料庫的鍵,每個鍵是一個字元串對象;

鍵空間的值是資料庫的值,每個值可以是字元串對象、清單對象、哈希表對象、集合對象和有序集合對象中的一種;

Redis | 第4章 Redis中的資料庫《Redis設計與實作》

資料庫鍵空間是一個字典,所有針對資料庫的操作都是通過鍵空間字典來操作的;

在對鍵空間進行讀寫操作時,Redis 還會進行一些維護操作:

讀取鍵後,會根據鍵是否存在更新伺服器的鍵空間命中 keyspace_hits 次數或鍵空間不命中 keyspace_misses 次數。通過 INFO stats 指令檢視屬性;

讀取鍵後,伺服器會更新鍵的 LRU(最後一次使用時間)。通過 ONBJECT idlettime [key] 指令檢視key的閑置時間;

伺服器在讀取鍵時發現鍵已經過期,會先删除這個過期鍵;

如果有用戶端使用 WATCH 指令監視某個鍵,伺服器對該鍵修改後會标記上髒 <code>dirty</code>,讓事務處理程式注意;

伺服器每修改一個鍵後,會對髒 <code>dirty</code> 鍵計數器值增 1,計數器會觸發伺服器的持久化以及複制操作;

鍵的時間相關設定指令參看《Redis常用指令及示例總結》1.3 生存時間的功能;

生存時間:

用戶端可以通過 EXPIRE 或 PEXPIRE 指令以秒或毫秒精度為資料庫中某個鍵設定生存時間(Time To Live,TTL)。經過指定時間後,伺服器自動删除生存時間為0的鍵;

可以通過 SETEX 指令在設定字元串鍵同時設定過期時間;

使用 TTL 或 PTTL 指令擷取鍵的剩餘生存時間;

過期時間:

用戶端設定過期時間的指令是 EXPIREAT 或 PEXPIREAT;

過期時間是一個 UNIX 時間戳;

EXPIRE、PEXPIRE 和 EXPIREAT 三個指令都會轉換成 PEXPIREAT 指令實作;

有三種删除過期鍵的政策:

定時删除:主動政策。對記憶體最友好,到期就釋放記憶體。缺點是對CPU事件不友好,當過期鍵比較多時,會占用一部分CPU時間;

惰性删除:被動政策。對CPU時間最友好。每次從鍵空間擷取鍵時,檢查取得的鍵是否過期,過期則删除。缺點是對記憶體不友好;

定期删除:主動政策。前兩種政策的整合與折中。每隔一段時間執行一次删除過期鍵操作,并通過限制删除操作執行的時長與頻率減少删除操作對CPU時間的影響。缺點是難以确定删除操作執行的時長和頻率;

惰性删除政策由 <code>db.c/expireIfNeeded</code> 函數實作,流程如下:

Redis | 第4章 Redis中的資料庫《Redis設計與實作》

定期删除政策由 <code>redis.c/activeExpireCycle</code> 函數實作,每當Redis的伺服器周期性操作 <code>redis.c/serverCron</code> 函數執行時,activeExpireCycle 函數會被調用。在規定的時間内,分多次周遊伺服器各個資料庫,從資料庫的 <code>expires</code> 字典中随機檢查一部分過期時間,删除其中過期鍵;

在執行 SAVE 或 BGSAVE 指令建立一個新的 RBG 檔案時,程式會對資料庫中的鍵進行檢查,已過期的鍵不會被儲存到新建立的 RDB 檔案中;

載入 RDB 檔案時:

若伺服器以主伺服器模式運作,過期鍵不載入;

若伺服器以從伺服器模式運作,所有鍵都會載入;

當伺服器以 AOF 持久化模式運作時,未被惰性删除和定期删除的過期鍵不會對 AOF 檔案産生影響;

當過期鍵被惰性删除或定期删除後,程式會向 AOF 檔案追加(append)一條 DEL 指令,顯示記錄該鍵已被删除;

與 RDB 檔案類似,在執行 AOF 重寫過程中,程式會對資料庫中的鍵進行檢查,已過期的鍵不會被儲存到重寫後的 AOF 檔案中;

當伺服器運作在複制模式下時,從伺服器的過期鍵删除動作由主伺服器控制;

Redis | 第4章 Redis中的資料庫《Redis設計與實作》
Redis | 第4章 Redis中的資料庫《Redis設計與實作》

資料庫通知是 Redis 2.8 版本新增的功能;

資料庫通知可以讓用戶端通過訂閱給定的頻道或模式,來獲知資料庫中鍵的變化,以及資料庫中指令的執行情況;

Redis 指令對資料庫進行修改後,伺服器會根據配置向用戶端發送資料庫通知;

通知的相關指令可以參考 《Redis常用指令及示例總結》7. Pub/Sub(釋出/訂閱);

兩類通知類型:

鍵空間通知 key-space notification:關注 “某個鍵執行了什麼指令”;SUBSCRIBE channel:message;

鍵事件通知 key-event notification:關注 “某個指令被什麼鍵執行了”;SUBSCRIBE channel:del;

伺服器配置的 <code>notify-keyspace-events</code> 選項決定伺服器所發送通知的類型:

AKE:發送所有類型的鍵空間和鍵事件通知;

AK:發送所有類型的鍵空間通知;

AE:發送所有類型的鍵事件通知;

K$:隻發送字元串有關的鍵空間通知;

EL:隻發送清單鍵有關的鍵事件通知;

發送資料庫通知的功能是由 <code>notify.c/notifyKeyspaceEvent</code> 函數實作;

新人制作,如有錯誤,歡迎指出,感激不盡!

歡迎關注公衆号,會分享一些更日常的東西!

如需轉載,請标注出處!

Redis | 第4章 Redis中的資料庫《Redis設計與實作》