梁鑫:重構 - 在美股行情繫統的實踐
作者:梁鑫(資深架構師,多年雲原生,微服務架構經驗,開源 SIA 系列產品 owner)
1
引子
今年開始,由於工作內容調整。開始負責美股港股產品的研發。第一個面對的問題,就是當前產品股票行情信息嚴重延遲。股票行情信息延遲,客戶會看到的是錯誤的股價,這直接導致了產品的不可用,失去了客戶的信任。
股票行情是一種證券市場用語,指股票交易所內各只股票的漲幅變化及交易流通情況。
2
舊版美股行情繫統架構圖
從現狀的架構圖中可以看出,美股行情產品有以下若干問題
2.1
問題一,消息服務器選擇
相信很多朋友都對 rabbitmq 有所瞭解,很多公司都採用了 rabbitmq。它以傳輸速度快,可靠性高而被廣爲使用。在主流的開源消息服務器中,它是唯一可以傳輸速度達到微秒級的消息消息服務器。在實際傳輸中,即使使用集羣,它也並不是真正的分佈式隊列服務器。所以在消息順序上,它是保證的最好的。但 rabbitmq 也有自身的不足,最大的不足就是吞吐量太低。無法滿足海量股票行情信息的傳輸需求。
2.2
問題二,緩存服務器 Redis 的使用
Redis 緩存服務的性能,相信可以滿足大多數項目的需求。但如果降美股行情的數據量進行全量的寫入操作,即使是 redis,也 cover 不住。雖然 Redis 號稱能支持每秒 14 萬的讀操作,11 萬的寫操作。但這估計是理想的情況。在實際的生產環境中,我們的實際測試結果是達不到這個量級的。對於每秒超過十萬的股票行情信息,每條數據都進行 redis 寫操作,必然出現大量的寫入失敗,甚至頻繁出現 redis 鏈接異常。
2.3
問題三,線程池的使用
在現存的架構中,多線程設計有着明顯的問題。因爲 rabbitmq 的吞吐量不足,因此技術上把數百條消息合併成一條進行傳輸處理,這樣雖降低了消息吞吐量,不會導致消息大量堆積,但卻對實時的股票行情數據造成了人爲的延遲。即便進行了消息合併,但吞吐量還是過大,因此根據股票的名稱把若干股票的信息分組用不同的隊列進行傳輸。
每組股票都用一個線程池來處理。強行增大處理性能。當接到封裝的信息後,爲了保證能夠處理大量消息,還需要採用多線程方式,因爲股票行情需要有一定順序行,無序的線程處理導致了大量時序錯誤信息, 最終發現展示結果很難使人滿意。並且維護大量的線程池極度消耗資源,我們常規意義的線程配置,是計算有限 CPU 核數 + 1,IO 有限 CPU 核數 * 2。維護數百個線程池,其實是讓線程切換的工作佔據了大量的 CPU 時間,浪費了寶貴的 CPU 的資源。
2.4
問題四,系統無法進行水平擴展
如果判斷系統是一個好的集羣架構。往往需要滿足三點要求。
一是可以避免單點故障;
二是可以水平擴展;
三是能實現負載均衡。
現狀股票行情架構是完全不能滿足這三點需求。需要進行重構。
3
新版美股行情繫統架構圖
3.1
改進一,使用 kafka 替代 rabbitmq
美股行情信息吞吞量非常大,在開盤和收盤的高峯期甚至超過了每秒十萬條交易信息。如此之大的吞吐量,很明顯 rabbitmq 根本無法滿足需求,只有採用吞吐更大的 kafka 才能滿足需求。我們經常用下表來比對幾種主流消息服務器的差異。
3.2
改進二,降低 redis 的寫入次數
如何降低 redis 的寫入次數,只能是把原先寫入 redis 的操作變更成爲寫入內存。當股票行情信息通過 kafka 隊列服務器將消息流轉到股票計算節點時,計算節點把數據計算後寫入內存,同時定期將內存數據同步到 redis 中,這樣可以大大節省 redis 的寫操作,讓 redis 的性能能夠 cover 我們現在的需求。同時我們將性能較差的 redisTemplate 換成直接使用 jedis,通過我們的測試,兩者之間的性能差異接近三倍,並優化 redis 鏈接數,避免出現大量鏈接異常情況。
3.3
改進三,改進線程池的使用
現狀系統的線程池創建太多,讓寶貴的 CPU 資源浪費在了線程切換中。新的架構爲了解決這個問題,獲取每隻股票的 hashcode,然後用固定線程數取餘,每個餘數給一個固定的線程池,每個線程池保活一個線程,這樣就能保證每隻股票在同一節點進入一個線程處理,最大限度保證了處理股票行情信息的順序性。
3.4
改進四,支持水平擴展
通過對 kafka 同一個 topic 訂閱,然後不同 worker 接收不同的信息,這樣可以輕鬆讓計算節點進行水平擴展。當信息再往下一個節點流轉時,查詢節點通過不同 groupid 訂閱完整 topic,不需要再通過 redis,這樣查詢節點可以輕鬆進行水平擴展。支持了整體架構的水平擴展。
4
總結
美股行情的吞吐量,遠超過我之前所負責過的項目。如此高的併發,且不能延遲,還要最大限度的保證處理信息的順序性。對自己而言也是個不小的挑戰,在這個項目中我學到了很多東西。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/6_zkpnyzFtAV2tc0Mh67zw