如何應對高併發??

Redis是如何基於單線程來應對多線程併發訪問呢?

從存儲角度

Redis所有數據都在內存中,所有運算也是在內存運算,速度相對來說比較快,雖然對那些時間複雜度爲O(n)級別的指令會導致Redis卡頓,但對於其他指令來說,還行。

從網絡角度

非阻塞IO + 事件輪詢(多路複用)技術

第一:這裏Redis用到了非阻塞IO,所謂的非阻塞IO,說白了就是當應用服務器與Redis服務器建立起連接之後,Redis通過在套接字的Non_Blocking選項建立起非阻塞IO模式,該模式下read方法能讀多少讀多少,write方法能寫多少寫多少,read/write完全不受阻塞,read方法能讀多少取決於內核爲套接字分配的讀緩衝區內部的數據字節數,write方法能寫多少取決於內核爲套接字分配的寫緩衝區的空閒空間字節數。讀方法和寫方法都會通過返回值來告知程序實際讀寫了多少字節。

第二:通過非阻塞IO技術解決了網絡讀取與寫入,那如何確保read與write執行的完整性??這裏使用事件輪詢(多路複用)技術,藉助操作系統提供的API來使用。就拿該API最古老的select函數來說,該函數需要3個參數:read_fds讀描述符列表、write_fds寫描述符列表、timeout,函數返回值則是對應的可讀可寫事件。

當沒有任何事件到來時則最多等待timeout時間,線程處於阻塞狀態;一旦期間有任何事件到來,就可以立即返回。時間過了之後還是沒有任何事件到來,也會立即返回。拿到事件後,Redis線程就可以繼續挨個處理相應的事件,處理完了繼續輪詢。

read_fds:Redis會爲每個客戶端套接字都關聯一個指令隊列。客戶端的指令通過隊列來排隊進行順序處理,先到先服務。

write_fds:Redis 同樣也會爲每個客戶端套接字關聯一個響應隊列。Redis 服務器通過響應隊列來將指令的返回結果回覆給客戶端。如果隊列爲空,那麼意味着連接暫時處於空閒狀態,不需要去獲取寫事件,也就是可以將當前的客戶端描述符從write_fds裏面移出來。等到隊列有數據了,再將描述符放進去。避免select系統調用立即返回寫事件,結果發現沒什麼數據可以寫。出這種情況的線程會飆高 CPU。

發佈了167 篇原創文章 · 獲贊 10 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章