《Redis設計與實現》2.單機數據庫的實現

一、數據庫

  1. redis的key過期時間設置:EXPIRE設置ttl秒,PEXPIRE設置ttl毫秒,EXPIREAT設置過期時間戳秒,PEXPIREAT設置過期時間戳毫秒。
  2. 保存過期時間:redis過期時間存放於expires字典中,其中都是轉爲PEXPIREAT命令存儲的。
  3. 刪除過期時間:PERSIST key
  4. 過期鍵刪除策略:redis採用惰性刪除+定期刪除
    1. 定時刪除:設置過期時間的同時,創建定時器,定時器在鍵過期時立即執行刪除操作(內存友好,但CPU不友好,暫未實現)
    2. 惰性刪除:獲取key時,哦按段是否過期,過期則刪除。
    3. 定期刪除:每隔一段時間,對數據庫檢查一次,刪除過期鍵。
  • 惰性刪除如下
  • 定期刪除如下
5.過期鍵在RDB、AOF、複製中的處理
    RDB中的過期鍵處理:
  • SAVE或BGSAVE創建RDB,不會將過期key保存到RDB文件中。
  • master載入RDB文件,會過濾掉過期的key;slave載入RDB文件,全部載入,不過濾過期key。
    AOF中的過期鍵處理:
  • 保存時不做任何處理。
  • 在惰性刪除或者定期刪除時,會在AOF文件追加刪除命令。
  • BGREWRITEAOF重寫時,會檢查過期key,過期的key不會寫到AOF中。
    複製模式過期鍵處理:
  • 從服務器不處理過期key,而是等主服務器發送DEL命令。
  • GET key訪問從服務器,key過期,依然返回key的值。
6.數據庫通知
notify-keyspace-event:
  • AKE:鍵空間通知、鍵事件通知
  • AK:鍵空間通知
  • AE:鍵事件通知
  • K$:和字符串鍵有關的鍵空間通知
  • E1:和列表鍵有關的鍵事件通知
 

二、RDB持久化

  1. RDB文件的創建與載入
    1. 創建:SAVE   BGSAVE
    2. 載入:開啓了AOF,優先使用AOF恢復;否則使用RDB恢復。
  2. 自動間隔性保存
    1. save 900 1 、save 300 10 、 save 60 10000,900秒之內至少1次修改,300秒內至少10次修改,60秒內至少10000次修改,滿足其一自動執行BGSAVE
    2. dirty計數器與lastsave屬性
      1. dirty:上次SAVE後多少次修改
      2. lastsave:上一次SAVE的時間
  3. RDB文件結構
    1. REDIS|db_version|databases|EOF|check_sum,例如”REDIS”|”0006”|EOF|2826376271
      1. REDIS就是常量REDIS五個字符
      2. db_version一個整數,版本號,例如0006
      3. databases一個或多個數據庫,也可爲空,結構SELECTDB|db_number|key_value_pairs
        1. SELECTDB:常量
        2. db_number:數據庫號,用於SELECT db_number切換數據庫
        3. key_value_pairs:EXOIRETIME_MS|ms|TYPE|key|value,在開啓壓縮後,大於20字節的字符串value對象會被壓縮。
      4. EOF1字節,代表文件正文內容結束
      5. check_sum8字節,校驗和
    2. 分析RDB文件
      1. R E D I S 0 0 0 6 377 334 263 C 360 Z 334 362 V
        1. R E D I S 常量;0006 版本;337 EOF常量;334 263 C 360 Z 334 362 V:8字節校驗和。
      2. R E D I S 0 0 0 6 376 \0 \0 003 M S G 005 H E L L O 337 207 Z = 304 F T L 343
        • R E D I S 常量;0006 版本;336 SELECTDB常量;\0 數據庫號;\0 TYPE常量;003 key長度;MSG key值;005 value長度;HELLO value值;337 EOF常量;207 Z = 304 F T L 343 8字節校驗和。

三、AOF持久化

  1. AOF持久化實現:命令追加、文件寫入、文件同步
    1. 命令追加:服務器執行完一個命令,會將該命令追加到aof_buf緩衝區。
    2. 文件寫入與同步:Redis運行一個循環,會將aof_buf的內容寫入文件,並判斷是否需要同步文件,參數appendfsync設置。
      1. 寫入與同步:操作系統寫入文件並不是直接寫入文件,而是寫入緩衝區,待達到一定量或者時間或者主動同步,纔會真正寫入文件。
      2. always:每次寫入後同步AOF文件。
      3. everysec:每次寫入後判斷上次同步距離時間,超過1s則執行AOF文件同步。
      4. no:每次寫完後不同步,等待操作系統自己同步。
  2. AOF文件的載入與數據還原
    1. 讀取AOF文件還原數據庫
      1. 創建一個僞客戶端
      2. 從AOF文件讀取一條命令
      3. 使用僞客戶端執行命令
      4. 重複2、3直到AOF的所有命令均執行完畢
  3. AOF重寫(文件過大,重寫會大大減少文件的大小)aof_write
    1. 創建一個新的AOF文件
    2. 以當前數據庫狀態爲準,生成命令並寫入AOF文件
    3. 命令過長,則拆分,依賴參數REDIS_AOF_REWRITEITEMS_PER_CMD,最大64的元素。
    4. 後臺重寫:BGREWRITEAOF,使用子進程處理AOF重寫,父進程可以繼續處理命令請求,子進程擁有服務器進程的數據副本,避免鎖。
    5. 開啓子進程處理AOF同時,也開啓一個AOF重寫緩衝區,當AOF重寫完畢後,會將AOF重寫緩衝區的內容寫到新的AOF文件,然後重命名替換老的AOF文件。

四、事件

  1. 文件事件
                1. 處理器構成,如圖
                2. I/O多路複用實現:底層使用select、epoll、evport、kqueue實現。
                3.常見文件處理器
                    1.連接應答處理器
                    2.命令請求處理器
                    3.命令回覆處理器
                一次完整的事件:
    • Redis服務器正常運行,服務器的監聽套接字的AE_READABLE事件處於監聽下,並對應連接應答處理器;
    • 當一個Redis客戶端像服務器發起連接,監聽套接字將產生AE_READABLE事件,觸發連接應答處理器執行,處理器會對客戶端應答,並創建客戶端套接字、客戶端狀態,並將客戶端套接字的AE_READABLE事件與命令請求處理器關聯;
    • 客戶端向服務器發送命令請求,客戶端套接字產生AE_READABLE事件,觸發命令請求處理器執行,執行命令產生命令回覆,服務器將客戶端套接字的AE_WRITABLE事件與命令回覆處理器關聯;
    • 客戶端讀取命令回覆時,客戶端套接字產生AE_WRITABLE事件,觸發命令回覆執行,將命令回覆寫入套接字,刪除客戶端套接字的AE_WRITABLE與命令回覆處理器的關聯。
  1. 時間事件(定時事件與週期事件)
 

五、客戶端

PUBSUB與SCRIPT LOAD命令會導致數據庫狀態或者客戶端狀態變化,所以也會寫入AOF文件。

六、服務端

命令執行器:
  1. 查找命令的實現:命令表查找
  2. 執行預備操作:檢查cmd指針、參數、身份驗證、內存佔用、BGSAVE、訂閱模式判斷、是否正在載入數據、客戶端是否阻塞與lua、是否開啓了事務、是否有監視器
  3. 調用命令實現函數
  4. 執行後續工作:慢查詢日誌記錄、cmd命令計數器修改calls、AOF緩衝、slave複製
  5. 回覆客戶端
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章