Redis Server 運行原理圖
Redis 服務器中 Socket 網絡建立以及文件事件模型
一個 redis 單機,可以抗幾百上千的并發,這里的并發指的就是同時可以有幾百個 client 對這個 redis server 發起請求,都需要去建立網絡連接,同時間可能會有幾百個 redis client 通過 socket 和我們的 redis server socket 建立網絡連接
如果自己使用 java socket 編程,無論使用 nio、bio,一旦要是說一個 server 和一個 client 完成了一個網絡連接之后,就會多出來一個 socket,socket 是抽象出來通信的模型,通過一個 socket 就可以跟對方的 socket 形成一個連接
那么對于 redis server 而言,內部為了支撐并發訪問的大量的 redis client,redis server 內部就會有幾百個 socket,網絡連接同時在維持著
因此呢,在 bio 模式下,一個 socket 連接就對應了一個線程來監聽請求
在 nio 模式下,可以實現 IO 多路復用,一個線程就可以監聽多個 socket 的網絡事件
在 redis server 中,就是通過 FileEventHandler
進行多路復用
socket 中會產生一些網絡事件,accept(連接應答)、read(有數據可以讀的事件)、write(有數據可以寫的事件)、close(連接被關閉) 在 redis 中這些網絡事件
都被抽象為文件事件
基于隊列串行化的文件事件處理機制
針對 server 端的大量的 socket,不太可能每一個 socket 都使用一個線程來監聽,因為線程資源不夠,所以不會采用 bio 模式,因此解決方案就是針對大量的 socket,使用一個線程監聽 n 多個 socket,采用 IO 多路復用模式
當 server 端保持了大量的 redis client 的連接,可能在同一時間,大量的 redis client 并發的給 server 端發送大量的請求,redis server 內部大量的 socket 會突然同一時間產生大量的事件(例如 read 事件,write 事件)
對于這些網絡事件的處理,有兩種解決方案(Redis Server 中就采用了第一種,使用隊列進行串行化處理):
- 使用 queue 隊列,將接收到事件的 socket 放入 queue 中進行排隊,串行化進行處理
- 將有事件發生的 socket 分發給不同的線程,來進行并發的處理,開啟大量的多線程,多個線程并發的去處理不同的 socket 里面的事件
client 和 server 端建立連接的流程為:
我們會有一個專門的 socket 去監聽端口,用于監聽來自客戶端的連接請求,這個連接請求經過 IO 多路復用,由 連接應答處理器
進行處理,處理的操作其實也就是服務端和客戶端進行 TCP 三次握手建立連接,建立好連接之后服務端就會創建一個新的 socket,這個 socket 就是接收客戶端對應的事件
那么連接建立之后,客戶端對于服務端的一些讀寫請求就會通過 socket 進行請求,請求到達服務端之后,通過 IO 多路復用將任務分發給不同的事件處理器進行處理,如果是讀寫請求,就將讀寫的響應通過 socket 響應給客戶端
Redis 串行化單線程模型為什么能高并發?
首先 Redis 是通過 串行化 + 單線程
來應對高并發的
Redis 首先是基于內存操作,速度很快,并且當大量請求進入后,都放入隊列中,進行串行化處理,由單個線程直接基于內存進行操作,并且單線程的情況下也不需要加鎖以及線程上下文切換(多線程是很占用 CPU 資源的),核心就在于 Redis 通過單線程基于內存進行操作!