基於ElasticSearch的標簽系統的架構治理
1. 背景
原有標簽系統重度依賴elasticsearch,支持了公司70+接入方使用。支持了幾個業務條線的客戶分析及API服務。
整個Elasticsearch 集群共計存儲了10T+的數據(無副本模式)。
整個ElasticSearch 集群涉及了幾個場景的使用:
-
數據寫入(寬表信息從Hive同步到ES)
-
用戶通過平台進行客群的數量分析以及畫像分析(統計某些維度的數據量)
-
API 服務能力, 對外提供客戶維度的畫像(通過search/get)
-
API 服務能力, 對外提供客群拉取的能力(通過_scroll實現)
我們遇到的問題:
-
集群在數據寫入的情況下,因為使用bulk 的方式 load,導致集群的search能力和 _aggs 能力性能急遽下降,導致了API服務的不穩定,甚至是不可用。
-
集群在_scroll 情況和用戶畫像的情況下, 內存急速消耗,導致長時間的GC,進而影響API服務的可用性和業務使用
-
索引SHARD 分配不合理,極其容易導致 _search 導致的負載過高,甚至 shard 丟失,進而Elasticsearch 集群變紅,導致服務不可用。
-
Elasticsearch 的寫入只能進行限速的導入,從而導致數據的時效無法達到業務的要求。單一大索引,導入時間在40小時+, 從而導致業務時效口碑較差。
-
若干大索引同時寫入過程中,集群負載過高,導致集群直接飄紅,無法服務。因為若干導數作業的時序性無法保證,所以集群的穩定性只能靠人為自行監控排查。因為事件經常在半夜,苦不堪言。
2. 分析
集群飄紅
集群飄紅,是多因素導致的。
ElasticSearch集群飄紅的原因有很多。總的來說,可以分成3類。
1. IO過高
IO過高一般有兩種,一種是iowait多高,這種情況下需要更好的ssd硬盤。即便是SSD硬盤的情況下,我們也同樣碰到了IO過高。(公司內網不方便截圖)。當然這種IO過高,定位了原因是文件系統在做其他讀寫,進行了限速寫入就恢復了。(在HDD硬盤上,這種IOwait 會更多)
另外一種是 ES進程內的文檔插入/更新參數不合理導致的IO過高。如bulk的byteSize設置不合理,refreshInterval 設置成1s 導致的Segment Merge 問題,以及Replica設置成3導致的副本分發IO問題(translog)。
2. 流量過大
流量過大 ,主要是上游未做保護的流量穿透。比如_search 高峰可達30w/s。這種請求的堆積,正常情況下,只會堆積請求,但與寫入請求同時發生時,容易引起FGC,進而導致節點脫離。
3. GC 導致的節點脫離
GC 算法需要優化, 在JDK11 的新GC算法前, CMS和G1的表現算是比較差的。CMS經常會GC時間過長,導致節點的健康檢查無法及時通過,進而被集群判定為掛了,導致集群飄紅,影響業務。
3. 解決方案
從上述各場景定性的分析,按照場景和資源消耗情況進行整理出來大致的方案。
為啥不定量?因為No Measurement! 而且在資源不穩定的情況下,各種數字已經失真了。
因此改進方案分成4路分別改進:
-
Hive2es 工具改進,以減少對ElasticSearch 負載壓力為根本優化目標。提升速度時效。
-
增加新的ES集群,物理隔離若干大索引。可以有效隔離彼此的業務影響。
-
對原有依賴ElasticSearch的scroll 方案進行架構變更以及整體設計。根據業務用例,我重新設計了異步取批的數據服務。
-
對單個用戶的search 接口重新使用get實現。 (在並發高的情況下,比如_searchById 並發高達16w/s時,任務會堆積,從而導致接口會變慢)
4.成果&收益
重點產出成果有三個:
-
Hive2ES 工具。 參考DiDi 的 fastindex 實現。可以把原來40h+的導數任務並行到2h。同時對Elasticsearch的負載由原來的Cpu&io 變成了純IO影響。 后續會單獨來描述這一內容
-
異步取批數據服務。 可以穩定的提供取批功能,原來平均取批時間從20min到5min。並且穩定高效,支持斷點續傳
-
畫像服務產品。 獨立的畫像數據服務。提供高性能的key value 查找服務,支持定制化DSL定義,可以跨集群/跨索引/跨接口的提供服務。