資料內(nèi)容:
Redis 服務(wù)器中 Socket 網(wǎng)絡(luò)建立以及文件事件模型
一個(gè) redis 單機(jī),可以抗幾百上千的并發(fā),這里的并發(fā)指的就是同時(shí)可以有幾百個(gè) client 對(duì)這個(gè) redis server 發(fā)起請(qǐng)
求,都需要去建立網(wǎng)絡(luò)連接,同時(shí)間可能會(huì)有幾百個(gè) redis client 通過(guò) socket 和我們的 redis server socket 建立網(wǎng)絡(luò)
連接
如果自己使用 java socket 編程,無(wú)論使用 nio、bio,一旦要是說(shuō)一個(gè) server 和一個(gè) client 完成了一個(gè)網(wǎng)絡(luò)連接之
后,就會(huì)多出來(lái)一個(gè) socket,socket 是抽象出來(lái)通信的模型,通過(guò)一個(gè) socket 就可以跟對(duì)方的 socket 形成一個(gè)連
接
那么對(duì)于 redis server 而言,內(nèi)部為了支撐并發(fā)訪(fǎng)問(wèn)的大量的 redis client,redis server 內(nèi)部就會(huì)有幾百個(gè) socket,
網(wǎng)絡(luò)連接同時(shí)在維持著
因此呢,在 bio 模式下,一個(gè) socket 連接就對(duì)應(yīng)了一個(gè)線(xiàn)程來(lái)監(jiān)聽(tīng)請(qǐng)求
在 nio 模式下,可以實(shí)現(xiàn) IO 多路復(fù)用,一個(gè)線(xiàn)程就可以監(jiān)聽(tīng)多個(gè) socket 的網(wǎng)絡(luò)事件
在 redis server 中,就是通過(guò) FileEventHandler 進(jìn)行多路復(fù)用
socket 中會(huì)產(chǎn)生一些網(wǎng)絡(luò)事件,accept(連接應(yīng)答)、read(有數(shù)據(jù)可以讀的事件)、write(有數(shù)據(jù)可以寫(xiě)的事
件)、close(連接被關(guān)閉) 在 redis 中這些 網(wǎng)絡(luò)事件 都被抽象為 文件事件
基于隊(duì)列串行化的文件事件處理機(jī)制
針對(duì) server 端的大量的 socket,不太可能每一個(gè) socket 都使用一個(gè)線(xiàn)程來(lái)監(jiān)聽(tīng),因?yàn)榫€(xiàn)程資源不夠,所以不會(huì)采
用 bio 模式,因此解決方案就是針對(duì)大量的 socket,使用一個(gè)線(xiàn)程監(jiān)聽(tīng) n 多個(gè) socket,采用 IO 多路復(fù)用模式
當(dāng) server 端保持了大量的 redis client 的連接,可能在同一時(shí)間,大量的 redis client 并發(fā)的給 server 端發(fā)送大量的
請(qǐng)求,redis server 內(nèi)部大量的 socket 會(huì)突然同一時(shí)間產(chǎn)生大量的事件(例如 read 事件,write 事件)
對(duì)于這些網(wǎng)絡(luò)事件的處理,有兩種解決方案(Redis Server 中就采用了第一種,使用隊(duì)列進(jìn)行串行化處理):
使用 queue 隊(duì)列,將接收到事件的 socket 放入 queue 中進(jìn)行排隊(duì),串行化進(jìn)行處理
將有事件發(fā)生的 socket 分發(fā)給不同的線(xiàn)程,來(lái)進(jìn)行并發(fā)的處理,開(kāi)啟大量的多線(xiàn)程,多個(gè)線(xiàn)程并發(fā)的去處理
不同的 socket 里面的事件
client 和 server 端建立連接的流程為:
我們會(huì)有一個(gè)專(zhuān)門(mén)的 socket 去監(jiān)聽(tīng)端口,用于監(jiān)聽(tīng)來(lái)自客戶(hù)端的連接請(qǐng)求,這個(gè)連接請(qǐng)求經(jīng)過(guò) IO 多路復(fù)用,由 連
接應(yīng)答處理器 進(jìn)行處理,處理的操作其實(shí)也就是服務(wù)端和客戶(hù)端進(jìn)行 TCP 三次握手建立連接,建立好連接之后服務(wù)
端就會(huì)創(chuàng)建一個(gè)新的 socket,這個(gè) socket 就是接收客戶(hù)端對(duì)應(yīng)的事件
那么連接建立之后,客戶(hù)端對(duì)于服務(wù)端的一些讀寫(xiě)請(qǐng)求就會(huì)通過(guò) socket 進(jìn)行請(qǐng)求,請(qǐng)求到達(dá)服務(wù)端之后,通過(guò) IO
多路復(fù)用將任務(wù)分發(fā)給不同的事件處理器進(jìn)行處理,如果是讀寫(xiě)請(qǐng)求,就將讀寫(xiě)的響應(yīng)通過(guò) socket 響應(yīng)給客戶(hù)端
Redis 串行化單線(xiàn)程模型為什么能高并發(fā)?
Redis 串行化單線(xiàn)程模型為什么能高并發(fā)?
首先 Redis 是通過(guò) 串行化 + 單線(xiàn)程 來(lái)應(yīng)對(duì)高并發(fā)的
Redis 首先是基于內(nèi)存操作,速度很快,并且當(dāng)大量請(qǐng)求進(jìn)入后,都放入隊(duì)列中,進(jìn)行串行化處理,由單個(gè)線(xiàn)程直
接基于內(nèi)存進(jìn)行操作,并且單線(xiàn)程的情況下也不需要加鎖以及線(xiàn)程上下文切換(多線(xiàn)程是很占用 CPU 資源的),
核心就在于 Redis 通過(guò)單線(xiàn)程基于內(nèi)存進(jìn)行操作!
Redis 內(nèi)核級(jí)請(qǐng)求處理流程
Redis Server 其實(shí)就是 Linux 服務(wù)器中的一個(gè)進(jìn)程
主要還是下圖的流程
1. 應(yīng)用先和 server 端建立 TCP 連接
2. 建立連接之后,server 端就會(huì)有一個(gè)與該客戶(hù)端通信的 socket,客戶(hù)端的讀寫(xiě)請(qǐng)求發(fā)送到服務(wù)端的 socket
3. 那么通過(guò) IO 多路復(fù)用,收到讀寫(xiě)請(qǐng)求的 socket 會(huì)到隊(duì)列中排隊(duì)等待處理
4. 由文件事件分發(fā)器將事件分發(fā)給對(duì)應(yīng)的命令請(qǐng)求處理器
5. server 端內(nèi)部也是有一個(gè) Redis Client 的,由這個(gè) Client 來(lái)處理對(duì)數(shù)據(jù)的操作,這個(gè) Client 有一個(gè)輸入緩沖區(qū)
和輸出緩沖區(qū),先將讀寫(xiě)命令寫(xiě)入輸入緩沖區(qū)
6. 再去找到對(duì)應(yīng)的 Redis Command 也就是查找到對(duì)應(yīng)的命令
7. 之后就去操作內(nèi)存中的數(shù)據(jù)
8. 操作后將操作結(jié)果寫(xiě)入輸出緩沖區(qū)中
9. 最終命令請(qǐng)求處理器將輸出緩沖區(qū)中的響應(yīng)結(jié)果通過(guò) Socket 發(fā)送給客戶(hù)端