最近在效能壓測時總是觸發系統主動throttling, 我們都知道throttling是系統自我保護的一種手段, 大方向上可以認為這是期望的結果. 如果止步於認為這是正常現象, 就會錯失很多精彩, 現象背後的邏輯是什麼? 理清了背後的邏輯, 是不是還可能發現優化的空間? 我們可以有乙個看似正確的邏輯推斷, 但最後的分析一定要落到實處.
測試物件是乙個典型的分布式塊儲存服務, 使用者請求發往leader節點, leader通過一致性協議將該請求**到2個replica上, 當系統達成多數派後, 也就是3節點有2個節點已經持久化完成(3-2), leader就可以返回客戶端成功, 在3節點都持久化完成後(3-3), 該請求的狀態機完全結束.
有多種場景可以觸發throttling, 比如為了控制系統中還未響應(沒有達成3-2)的請求數, 這種請求數太多的時候就會觸發throttling, 在壓測環境下這種情況很少發生, 經過一些簡單的分析, 觸發throttling的原因是有太多的請求已經達成3-2, 但是還未達成3-3. 這種throttling的必要性在於未完成3-3的請求還要繼續占有資源, 另外這種請求往往意味著2個replica處理能力不匹配, 如果不進行throttling, 那麼同步延遲可能會越來越大.
用較簡單的步驟/環境復現問題是分析中很重要的一步, 這裡將leader和2個replica放在同一臺機器上仍能復現出相同的問題, 這就很大程度上排除了很多環境的因素, 比如leader到2個replica上的rdma網路狀況是否不同. 為了進一步簡化問題, 我們把replica上的處理邏輯進一步簡化, 這樣2個replica的處理能力幾乎完全相同:
另外通過fio可以驗證, optane上的寫清求可能發生亂序, 也就是先發的請求完成時間卻更晚, 但這個概率非常小, 並且即使發生了亂序, 也是在少數幾個io之間, 不會出現大範圍的亂序.
我們將分布式儲存抽象成2條佇列:
這裡因為queue1和queue2的服務時間相差較大, 所以很容易想到請求會積壓在queue2上. 這裡需要注意的是怎麼衡量server的服務時間, 以replica server為例, 如果把服務時間算成leader發出請求到收到響應, 那是不對的, 因為這裡面還有排隊時間.
2個replica只要處理能力不一樣, 如果沒有外部的throttling等因素, 按照排隊論慢的那個replica必然會出現佇列堆積, 因為壓測時的上限是由快的replica決定的, 快的都已經打滿, 慢的必然堆積.
是否排隊主要取決於以下因素:
上面3個因素中, 服務達到時間是2個replica最可能的不同點.
現在很多系統為了降低延遲和提高吞吐,往往通過使用者態的polling來取代核心的通知機制, 乙個server可能是這個樣子:
while (1)
當rdma poll結束之後, 會繼續執行aio, others等等的poll函式. 因為是單執行緒的, 直至下次rdma poll之前, 這段時間內新的rdma請求並沒有取出, rdma接收端的receive window沒更新直接就導致了rdma傳送端必須停止傳送. 另一方面, server都是能夠同時處理多個請求的, 一次poll的請求如果不夠, 相當於浪費了server的處理能力. 解決方法本身相對簡單. 網絡卡多佇列
多佇列指例項規格支援的最大網絡卡佇列數。單個ecs例項vcpu處理網路中斷存在效能瓶頸時,您可以將例項中的網路中斷分散給不同的cpu處理。經測試,在相同的網路pps和網路頻寬的條件下,與1個佇列相比,2個佇列最多可提公升效能達50 到100 4個佇列的效能提公升更大。如果您使用的映象已預設開啟網絡卡...
python celery 多work多佇列
1.celery模組呼叫既然celery是乙個分布式的任務排程模組,那麼celery是如何和分布式掛鉤呢,celery可以支援多台不通的計算機執行不同的任務或者相同的任務。如果要說celery的分布式應用的話,就要提到celery的訊息路由機制,amqp協議。具體的可以檢視amqp的文件。簡單地說就...
多佇列塊層
在早些時期,高效能的儲存裝置的iops只能跑到幾百,而當今的高階裝置動輒可以跑到幾百萬。所以核心塊層的設計已經遠遠不能滿足當今的io處理需要。最近幾年,社群已經意識到必須針對ssd這些高速的裝置來重新設計一套新的機制。從2.6.10開始,通用塊層的基本結構就沒有太大的變化。linux裝置驅動模型為塊...