Redis 內核級請求處理流程
Redis Server 其實就是 Linux 服務器中的一個進程
主要還是下圖的流程
- 應用先和 server 端建立 TCP 連接
- 建立連接之后,server 端就會有一個與該客戶端通信的 socket,客戶端的讀寫請求發送到服務端的 socket
- 那么通過 IO 多路復用,收到讀寫請求的 socket 會到隊列中排隊等待處理
- 由文件事件分發器將事件分發給對應的命令請求處理器
- server 端內部也是有一個 Redis Client 的,由這個 Client 來處理對數據的操作,這個 Client 有一個輸入緩沖區和輸出緩沖區,先將讀寫命令寫入輸入緩沖區
- 再去找到對應的 Redis Command 也就是查找到對應的命令
- 之后就去操作內存中的數據
- 操作后將操作結果寫入輸出緩沖區中
- 最終命令請求處理器將輸出緩沖區中的響應結果通過 Socket 發送給客戶端
Redis 數據傳輸協議
參考文章:https://redis.com.cn/topics/protocol.html
Redis客戶端和服務器端通信使用名為 RESP (REdis Serialization Protocol) 的協議。雖然這個協議是專門為Redis設計的,它也可以用在其它 client-server 通信模式的軟件上。
該協議用于 Redis 客戶端和服務端之間進行通信
RESP 協議格式:
- 單行字符串(Simple Strings): 響應的首字節是
+
- 錯誤(Errors): 響應的首字節是
-
- 整型(Integers): 響應的首字節是
:
- 多行字符串(Bulk Strings): 響應的首字節是
$
- 數組(Arrays):響應的首字節是
*
RESP 協議的每一個部分都是以 \r\n
結束,也就是換行結束
AOF 持久化文件中存儲的數據也是 RESP 協議的數據格式。
RESP 協議優點:
-
實現簡單,容易解析
redis 的 set key value 命令轉為 RESP 協議數據如下: *3 $3 SET $3 key $5 value
-
RESP 是二進制安全的,因為使用了前綴長度來傳輸大量數據,因此不需要去檢查內容中是否存在特殊字符
Redis 內核中的請求數據結構
Redis 協議說明文檔:http://www.redis.cn/topics/protocol.html
# *3 表示有 3 個命令字符串
# $3 表示長度
# \r\n 也就是換行操作
*3\r\n$3\r\nSET\r\n$3\r\nkey\r\j$5\r\nvalue\r\n# 把\r\n翻譯成換行,數據就為下邊這個樣子
*3
$3
SET
$3
key
$5
value
對于 set key value
命令來說,通過協議組織成上邊的數據,那么從 client 端發送到 server 需要序列化成字節數據流,之后再通過 socket 進行傳輸,server 端收到字節流數據之后,會進行反序列化,將字節流數據轉為了 *3\r\n$3\r\nSET\r\n$3\r\nkey\r\j$5\r\nvalue\r\n
,這個數據就會被放到 server 端的 RedisClient 的輸入緩沖區中
那么這個協議數據在 server 中的 Redis Client 中,就會被解析成 argv 的一個參數,也就是具體的命令,如下圖:
那么在 argv 中就解析出來了真正需要執行的命令了,下一步就要執行對應的命令了
Redis 內核中命令函數的查找
在 Redis Server 中將所有的命令都放在了一個命令查找表
中,那么在上邊的 argv 中拿到了命令的名稱,就可以去命令查找表中去查找對應的 RedisCommand,在 Redis Client 的輸入緩沖區中有一個變量 cmd
就會去指向該命令所對應的 RedisCommand,之后就可以真正的去調用命令函數,來操作 Redis 中的內存數據結構,之后將操作的結果還是按照 Redis 的協議給放入到 Redis Client 的輸出緩沖區中,之后就可以通過 Socket 將結果返回給客戶端了
Redis Server 啟動流程分析
Redis 我們作為緩存使用比較多
其實 Redis 本質上是一個基于內存的 Nosql 數據存儲服務,只是因為 Redis 是基于內存進行操作,比較快,所以我們用來做緩存
那么 Redis Server 基于內存操作,如果 Redis 重啟之后,內存中的數據就會丟失,所以 Redis 還需要進行持久化的一個操作
那么持久化就分為了 RDB 和 AOF,RDB 的話是周期性將內存中的全量數據都給復制到磁盤中(存儲文件為壓縮的二進制文件),適合做數據的冷備份,放到其他服務器的磁盤上去,如果當前服務器磁盤損壞,就可以從其他服務器讀取該 RDB 文件,恢復 Redis 中的內存數據
一般使用 AOF 來做數據的持久化,用 RDB 做一個周期性的冷備份
AOF 將內存數據同步到磁盤中,一般采用每秒同步一次,如果同步頻率過高,就會導致 Redis 性能退化,當 Redis 突然宕機,可能會丟失 1s 內的內存數據,那么在 redis-server 進程重啟時,就會把磁盤存儲的 aof 文件的數據給讀取到內存中,還原 Redis 上次運行時的內存情況
Redis 為什么需要分布式集群模式?
單臺 Redis 瓶頸在哪里?
在于內存,每一臺機器的內存是有限的,所以如果數據量很大的情況下,一臺 Redis 就不夠用了,因此需要分布式集群模式
在分布式集群模式中,就可以讓每一個節點存儲一部分的數據,來降低內存容量對于 Redis 的影響
Redis 分布式集群模式下內核中的數據結構
Redis Server 在分布式模式下,需要存儲哪些內容的?
主要是存儲集群的狀態(state)以及集群中的節點(nodes),以及當前節點的一個角色(myself)