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