1. 程式人生 > >Redis 設計與實現[2] -- 單機資料庫的實現

Redis 設計與實現[2] -- 單機資料庫的實現

1 鍵空間

set message "hello word"
rpush alphabet "a" "b" "c"
hset book name "Redis in action"
hset book author "Josian L. Carlson"
hset book publisher "Manning"

執行以上指令後,資料庫的鍵空間如下所示:

2 總結

  • Redis 伺服器的所有資料都是儲存在 redisServer.db 陣列中,而資料庫的數量則由 redisServer.dnum 屬性儲存
  • 客戶端通過修改目標資料庫指標,讓它指向 redisServer.db 陣列中的不同元素來切換資料庫
  • 資料庫主要由 dict 和 expires 兩個字典構成,其中 dict 字典負責儲存鍵值對,expires 字典則負責儲存鍵的過期時間
  • Redis 使用惰性刪除和定期刪除兩種策略來刪除過期的鍵:惰性刪除策略只在碰到過期鍵時才進行刪除操作,定時刪除策略則每隔一段時間主動查詢並刪除過期鍵

3 持久化

3.1 RDB

RDB 持久化功能所生成的 RDB 檔案是一個經過壓縮的二進位制檔案,通過該檔案可以還原生成 RDB 檔案時的資料庫狀態。

兩個指令可以用於生成 RDB 檔案:SAVE 和 BGSAVE

  • SAVE 指令會阻塞 Redis 伺服器程序,直到 RDB 檔案建立完畢為止,在伺服器程序阻塞期間,伺服器不能處理任何命令請求
  • BGSAVE 命令會派生出一個子程序,然後由子程序負責建立 RDB 檔案,伺服器程序繼續處理命令請求

RDB 檔案的載入工作是在伺服器啟動時自動執行的,只要 Redis 伺服器在啟動時檢測到 RDB 檔案存在,它就會自當載入 RDB 檔案。但是由於 AOF 檔案的更新頻率通常比 RDB 檔案要高,因此伺服器會優先使用 AOF 檔案來還原資料庫狀態。

對於一個空的 RDB 檔案,將由以下四個部分組成:

  • 五個位元組的 “REDIS” 字串
  • 四個位元組的版本號 (db_version)
  • 一個位元組的 EOF 常量
  • 八個位元組的校驗和(check_sum)

3.2 AOF

AOF 是通過儲存 Redis 伺服器所執行的寫命令來記錄資料庫的狀態,在讀取檔案還原資料的時只需要從 AOF 檔案中分析並依次讀取出每條寫命令

AOF 的持久化功能的實現可以分為命令追加,檔案寫入,檔案同步三個步驟

命令追加:當 AOF 持久化功能處於開啟狀態時,伺服器在執行完一個寫命令後,會以協議格式將被執行的寫命令追加到伺服器狀態的 aof_buf 緩衝區的末尾

檔案寫入:關於檔案的寫入和同步操作,可以使用以下虛擬碼來描述

def eventLoop():
	while True:
		# 處理檔案事件,接收命令請求以及傳送命令回覆
		# 處理命令請求時可能會有新內容被追加到 aof_buf 緩衝區中
		processFileEvents()
		
		# 處理時間事件
		processTimeEvents()
		
		# 考慮是否要將 aof_buf 中的內容寫入和儲存到 AOF 檔案裡面
		flushAppendOnlyFile()

flushAppendOnlyFile 函式的行為由伺服器配置的 appendfsync 選項的值來決定,各個不同值產生的行為不同:

always(將緩衝區所有內容寫入並同步到 AOF 檔案),(將所有內容寫入到 AOF 檔案並每間隔一秒同步一次),no(及那個內容寫入到 AOF 檔案,但是同步時間由作業系統決定)

由於 Redis 使用單執行緒來處理命令請求,如果服務直接呼叫 aof_rewrite 函式來重寫 aof 檔案,則服務期間無法處理客戶端發來的命令請求,因此,Redis 將 AOF 重寫程式放到子程序裡執行,其優點如下:

  • 子程序進行 AOF 重寫期間,伺服器程序可以繼續處理命令請求
  • 子程序帶有伺服器程序的資料副本,使用子程序而不是執行緒,可以在避免使用鎖的情況下,保證資料的安全性

AOF 後臺重寫的具體實現如下:

伺服器:

  • 執行客戶端發來的命令
  • 將執行後的寫命令追加到 AOF 緩衝區
  • 將執行後的寫命令追加到 AOF 重寫緩衝區

子程序在完成 AOF 重寫後,會向父程序傳送一個訊號,父程序接到該訊號後會呼叫一個訊號處理函式並執行以下工作:

  • 將 AOF 重寫緩衝區中的所有內容寫到新 AOF 檔案中
  • 對新的 AOF 檔案進行改名,原子地覆蓋現有的 AOF 檔案,完成新舊兩個 AOF 檔案的替換

4 客戶端和伺服器

4.1 客戶端

  • Redis 是一對多的伺服器程式,通過使用由 I/O 多路複用技術實現的檔案事件處理器,Redis 伺服器使用單執行緒單程序的方式來處理命令請求,並與多個客戶端進行網路通訊
  • 伺服器狀態結構使用 clients 連結串列連線起多個客戶端狀態,新新增的客戶端狀態會被放到連結串列的末尾

4.2 伺服器

伺服器的啟動:

  • 初始化伺服器狀態
  • 載入伺服器配置
  • 初始化伺服器資料結構fu
  • 還原資料結構
  • 執行事件迴圈

命令從傳送到完成:

  • 客戶端將命令請求傳送給伺服器
  • 伺服器讀取命令請求,並分析出命令引數
  • 命令執行器根據引數查詢命令的實現函式,然後執行實現函式並得出命令回覆
  • 伺服器將命令回覆返回給客戶端

 

文章來源:https://gongfukangee.github.io/2018/08/14/Redis-2/