Redis的處理速度之快相比大家都是見慣不怪的了,主要的原因時什么呢,主要時以下的三個原因:
1.單線程 避免了鎖 線程之間的互相競爭
2.多路復用
3.內存的讀取
下邊我們主要的分析下Redis中基於多路復用的模型,如果這個不了解,那么你不能說自己熟悉Redis了。
Redis Server跑在單進程單線程中,接收到的命令操作都是按照順序線性執行的,即便如此,它的讀寫性能依然能達到10W+的QPS,不得不說:Redis的設計十分優秀。
IO即為網絡I/O,多路即為多個TCP連接,復用即為共用一個線程或者進程,模型最大的優勢是系統開銷小,不必創建也不必維護過多的線程或進程。
IO多路復用是經典的Reactor設計模式,有時也稱為異步阻塞IO(異步指socket為non-blocking,堵塞指select堵塞),為常見的四種IO模型之一,
其他三種分別是:同步堵塞IO、同步非堵塞IO、異步(非堵塞)IO。
IO多路復用的核心是可以同時處理多個連接請求,為此使用了兩個系統調用,分別是:
select/poll/epoll--模型機制:可以監視多個描述符(fd),一旦某個描述符就緒(讀/寫/異常)就能通知程序進行相應的讀寫操作。讀寫操作都是自己負責的,也即是阻塞的,所以本質上都是同步(堵塞)IO。
Redis支持這三種機制,默認使用epoll機制。
我們來看一下epoll原理:
調用epoll_create:linux內核會在epoll文件系統創建一個file節點,同時創建一個eventpoll結構體,結構體中有兩個重要的成員:rbr是一棵紅黑樹,用於存放epoll_ctl注冊的socket和事件;rdllist是一條雙向鏈表,用於存放准備就緒的事件供epoll_wait調用。調用epoll_ctl:會檢測rbr中是否已經存在節點,有就返回,沒有則新增,同時會向內核注冊回調函數ep_poll_callback,當有事件中斷來臨時,調用回調函數向rdllist中插入數據,epoll_ctl也可以增刪改事件。調用epoll_wait:返回或者判斷rdllist中的數據即可。epoll兩種工作模式:LT--水平觸發 ET--邊緣觸發
LT:只要文件描述符還有數據可讀,每次 epoll_wait都會返回它的事件,提醒用戶程序去操作。
ET:檢測到有IO事件時,通過epoll_wait調用會得到有事件通知的文件描述符,對於每一個被通知的文件描述符,必須將該文件描述符一直讀到空,讓errno返回EAGAIN為止,否則下次的epoll_wait不會返回余下的數據,會丟掉事件。
ET比LT更加高效,因為ET只通知一次,而LT會通知多次,LT可能會充斥大量不關心的就緒文件描述符。

epoll總結:
使用紅黑樹而不是數組存放描述符和事件,增刪改查非常高效,輕易可處理大量並發連接。紅黑樹及雙向鏈表都在內核cache中,避免拷貝開銷。采用回調機制,事件的發生只需關注rdllist雙向鏈表即可。PS:如有任何問題或疑問,請留言告訴我。