分佈式系統的本質——隊列

所有分佈式系統或者說高性能分佈式系統的本質只有兩個字——隊列

簡單吧,換句話說,只要掌握了隊列,就掌握了分佈式系統構件方式。所有的分佈式系統,不管規模大小,都是不同類型隊列的堆砌而已。

那麼隊列是什麼?它既簡單又複雜,在各個層次的描述並不一致。例如,我們從一個網站舉例:

從宏觀上來說它包含一個web服務器的消息處理隊列,http消息到達服務器後是要排隊處理的,這就是一個fifo隊列;更進一步,如果這個網站的業務比較複雜,需要分佈式部署,還需要像rabbitmq,kafka這樣的隊列服務器來分擔應用層的壓力,這也是一種高級的隊列形式,提供的算法就不只是fifo可能還有廣播,主題等特性。

我們進一步往下,下面就是操作系統了,操作系統跟隊列有啥關係?或者跟併發有啥關係?可以說,一個系統的併發能力很大程度取決於os的設計。從網絡協議棧的處理到進程線程的調度,到cpu cache相關的鎖同步都直接或者間接跟os關係,畢竟程序寫了千萬條,最終在os才能執行。

os的隊列有哪些呢?

tcp協議的三次握手,在服務器等待客戶端最後一次握手回覆之前會吧socket結構放入一個隊列,回覆一個,就從中移除一個,形成所謂的連接套接字對象,這個隊列也會影響性能,有的半連接攻擊也會利用。epoll機制中如果把紅黑樹看做一個隊列的話也算一個,這個機制對高性能至關重要。同時,在linux內核中,網絡協議的讀寫並不直接寫入設備,而是有隊列做緩衝,用於屏蔽緩慢的io與超快的cpu內存讀寫性能差距,不至於網絡設備被堵死。而,這些隊列都是ring-buffer,即循環隊列,這樣更能發揮cpu的緩存能力(cache line),同時,數組鏈表組成的隊列性能也會優於鏈表。

到了進程管理模塊,每個進程都要執行自己的代碼,一個os幾百上千個進程,怎麼執行?排隊唄!在linux進程調度模塊中,每個核心會為不同優先級的任務建立隊列,以及一顆時間片紅黑樹,調度算法根據擁擠程度,優先級把合適的任務放入cpu運行。而,隊列中的優先級隊列,或者堆是做優先級運算的非常合適的動態數據結構。

同樣,在磁盤io,內核虛擬文件系統與驅動程序之間也有隊列,來解決速度與擁塞。在進程通信,管道這些內核對象中也大量使用隊列來做消息存儲與路由,以達到進程通信的目的,這跟rabbit,kafka的理念如出一轍。

另外,在編程語言中,很多鎖對象也是用隊列來實現,如java的reentrylock系列同步機制,就是將等待的線程對象放入一個隊列中排隊來實現的。

所以,在分佈式環境中,隊列從上到下都廣泛使用,掌握好隊列對構件好的分佈式系統至關重要!


分享到:


相關文章: