reids設計與實現---單機數據庫的實現
1服務器中的數據庫
/* Redis database representation. There are multiple databases identified
* by integers from 0 (the default database) up to the max configured
* database. The database number is the 'id' field in the structure. */
typedef struct redisDb {
// 數據庫鍵空間,保存着數據庫中的所有鍵值對
dict *dict; /* The keyspace for this DB */
// 鍵的過期時間,字典的鍵爲鍵,字典的值爲過期事件 UNIX 時間戳
dict *expires; /* Timeout of keys with a timeout set */
// 正處於阻塞狀態的鍵
dict *blocking_keys; /* Keys with clients waiting for data (BLPOP) */
// 可以解除阻塞的鍵
dict *ready_keys; /* Blocked keys that received a PUSH */
// 正在被 WATCH 命令監視的鍵
dict *watched_keys; /* WATCHED keys for MULTI/EXEC CAS */
struct evictionPoolEntry *eviction_pool; /* Eviction pool of keys */
// 數據庫號碼
int id; /* Database ID */
// 數據庫的鍵的平均 TTL ,統計信息
long long avg_ttl; /* Average TTL, just for stats */
} redisDb;
```
2 數據庫的鍵空間
數據庫的鍵空間是一個字典
3 鍵的過期處理
1 鍵的過期時間
雖然有多種不同單位和不同形式的設置命令,但實際上EXPIRE、PEXPIRE、EXPIREAT三個命令都是使PEXPIREAT命令來實現的:無論客戶端執行的是以上四個命令中的哪一個,經過轉換之後,最終的執行效果都和執PEXPIREAT命令一樣
2 過期鍵刪除策略
3 AOF、RDB、和複製功能對過期鍵的處理
P111
4 RDB的持久化
# RDB持久化
Redis提供了RDB持久化功能,這個功能可以將Redis在內存中的數據庫狀態保存到磁盤裏面,避免數據意外丟失
RDB持久化功能所生成的RDB文件是一個經過壓縮的二進制文件,通過該文件可以還原生成RDB文件時的數據庫狀態
## RDB文件的創建與載入
SAVE命令爲阻塞Redis服務器進程,直到RDB文件創建完畢爲止,在服務器進程阻塞期間,服務器不能處理任何命令請求
BGSAVE命令會派生出一個子進程,然後由子進程負責創建RDB文件,服務器進程(父進程)繼續處理命令請求
5 AOF持久化
# AOF持久化
與RDB持久化通過保存數據庫中的鍵值對來記錄數據庫狀態不同,AOF持久化是通過保存Redis服務器所執行的寫命令來記錄數據庫狀態的。
## 命令追加
當AOF持久化功能處於打開狀態時,服務器在執行完一個寫命令之後,會以協議格式化將被執行的寫命令追加到服務器狀態的aof_buf緩衝區的末尾
AOF文件的載入與數據還原
AOF重寫
## AOF重寫
爲了解決AOF文件體積膨脹的問題,Redis提供了AOF文件重寫(rewrite)功能。通過該功能,Redis服務器可以創建一個新的AOF文件來替代現有的AOF文件,新舊兩個AOF文件所保存的數據庫狀態相同,但新AOF文件不會包含任何浪費空間的冗餘命令,所以AOF文件的體積通常會比舊AOF文件的體積小得多
這個功能是通過讀取服務器當前的數據庫狀態來實現的在子進程中進行
爲了解決這種數據不一致問題,Redis服務器設置了一個AOF重寫緩衝區,這個緩衝區在服務器創建子進程之後開始使用,當Redis服務器執行完一個寫命令之後,它會同時將這個寫命令發送給AOF緩衝區和AOF重寫緩衝區
在整個AOF重寫過程中,只有信號處理函數執行時會對服務器進程(父進程)造成阻塞。
6 事件
# 事件
文件事件:Redis服務器通過套接字與客戶端(或者其他Redis服務器)進行連接,而文件事件就是服務器對套接字操作的抽象
時間事件:Redis服務器中的一些操作(比如serverCron函數)需要在給定的時間點執行,而時間事件就是服務器對這類定時操作的抽象
文件事件
事件的調度與執行
7 客戶端
套接字
名字
標誌
輸入緩衝區
輸出緩衝區
身份驗證
時間
客戶端的創建 1創建普通客戶端 2Lua腳本的僞客戶端 3AOF文件的僞客戶端
8 服務端
## 命令請求的執行過程
1. 當用戶在客戶端中鍵入一個命令請求時,客戶端會將這個命令請求轉換成協議格式,然後通過連接到服務器的套接字,將協議格式的命令請求發送給服務器
2. 當客戶端與服務器之間的連接套接字因爲客戶端的寫入而變得可讀時,服務器將調用命令請求處理器來執行以下操作(輸入緩衝區、argv、argc)
3. 命令執行器要做的第一件事就是根據客戶端狀態的argv[0]參數,在命令表中查找參數所指定的命令,並將找到的命令保存到客戶端狀態的cmd屬性裏面
4. 執行預備
5. 調用命令的實現函數
6. 執行後續工作
7. 將命令回覆發送給客戶端,客戶端接收並打印命令回覆
命令請求的執行過程
1 命令執行器 查找命令實現
2 命令執行器 執行預備操作
3 命令執行器 調用命令的實現函數
4 命令執行器 執行後續工作
5 將命令回覆發送給客戶端
6 客戶端接收並打印命令回覆
serverCron函數
1 更新服務器時間緩存
2 更新LRU時鐘
3 更新服務器每秒執行命令次數
4 更新服務器內存峯值記錄
5 處理SIGTERM
6 管理客戶端資源
7 管理數據庫資源
8 執行被延遲的BGREWRITEAOF
9 檢查持久化操作的運行狀態
10將AOF緩衝區中的內容寫入AOF文件
11 關閉異步客戶端
12 增加cronloops計數器的值
初始化服務器
1 初始化服務器狀態結構
2 載入裝置選項
3 初始化服務器數據結構
4 還原數據庫狀態
5 執行事件循環