1、集群規划優化實踐
1.1 基於目標數據量規划集群
在業務初期,經常被問到的問題,要幾個節點的集群,內存、CPU要多大,要不要SSD?
最主要的考慮點是:你的目標存儲數據量
是多大?可以針對目標數據量反推節點多少。
1.2 要留出容量Buffer
注意:Elasticsearch有三個警戒水位線,磁盤使用率達到85%、90%、95%。
不同警戒水位線會有不同的應急處理策略。
這點,磁盤容量選型中要規划在內。控制在85%之下
是合理的。
當然,也可以通過配置做調整。
1.3 ES集群各節點盡量不要和其他業務功能復用一台機器。
除非內存非常大。
舉例:普通服務器,安裝了ES+Mysql+redis,業務數據量大了之后,勢必會出現內存不足等問題。
1.4 磁盤盡量選擇SSD
Elasticsearch官方文檔肯定推薦SSD
,考慮到成本的原因。需要結合業務場景,如果業務對寫入、檢索速率有較高的速率要求,建議使用SSD磁盤。
阿里的業務場景,SSD磁盤比機械硬盤的速率提升了5倍。但要因業務場景而異。
1.5 內存配置要合理
官方建議:堆內存的大小是官方建議是:Min(32GB,機器內存大小/2)。
Medcl和wood大叔都有明確說過,不必要設置32/31GB那么大,建議:熱數據設置:26GB,冷數據:31GB
。
總體內存大小沒有具體要求,但肯定是內容越大,檢索性能越好。
經驗值供參考:每天200GB+增量數據的業務場景,服務器至少要64GB內存。除了JVM之外的預留內存要充足,否則也會經常OOM。
1.6 CPU核數不要太小
CPU核數是和ESThread pool關聯的。和寫入、檢索性能都有關聯。
建議:16核+
。
1.7 超大量級的業務場景,可以考慮跨集群檢索
除非業務量級非常大,例如:滴滴、攜程的PB+的業務場景,否則基本不太需要跨集群檢索。
1.8 集群節點個數無需奇數
ES內部維護集群通信,不是基於zookeeper的分發部署機制,所以,無需奇數
。
但是discovery.zen.minimum_master_nodes的值要設置為:候選主節點的個數/2+1,才能有效避免腦裂。
1.9 節點類型優化分配
集群節點數:<=3,建議:所有節點的master:true, data:true。既是主節點也是路由節點。 集群節點數:>3, 根據業務場景需要,建議:逐步獨立出Master節點和協調/路由節點。
1.10 建議冷熱數據分離
熱數據存儲SSD
和普通歷史數據存儲機械磁盤,物理上提高檢索效率。
2、索引優化實踐
Mysql等關系型數據庫要分庫、分表。Elasticserach的話也要做好充分的考慮。
2.1 設置多少個索引?
建議根據業務場景進行存儲。
不同通道類型的數據要分索引存儲
。舉例:知乎采集信息存儲到知乎索引;APP采集信息存儲到APP索引。
2.2 設置多少分片?
建議根據數據量衡量。
經驗值:建議每個分片大小不要超過30GB
。
2.3 分片數設置?
建議根據集群節點的個數規模,分片個數建議>=集群節點的個數。
5節點的集群,5個分片就比較合理。
注意:除非reindex操作,分片數是不可以修改
的。
2.4副本數設置?
除非你對系統的健壯性有異常高的要求,比如:銀行系統。可以考慮2個副本以上。否則,1個副本足夠。
注意:副本數是可以通過配置隨時修改
的。
2.5不要再在一個索引下創建多個type
即便你是5.X版本,考慮到未來版本升級等后續的可擴展性。
建議:一個索引對應一個type。6.x默認對應_doc,5.x你就直接對應type統一為doc。
2.6 按照日期規划索引
隨着業務量的增加,單一索引和數據量激增給的矛盾凸顯。按照日期規划索引是必然選擇。
好處1:可以實現歷史數據秒刪。很對歷史索引delete即可。注意:一個索引的話需要借助delete_by_query+force_merge操作,慢且刪除不徹底。
好處2:便於冷熱數據分開管理,檢索最近幾天的數據,直接物理上指定對應日期的索引,速度快的一逼!
操作參考:模板使用+rollover API使用
。
2.7 務必使用別名
ES不像mysql方面的更改索引名稱。使用別名就是一個相對靈活的選擇。
3、數據模型優化實踐
3.1 不要使用默認的Mapping
默認Mapping的字段類型是系統自動識別
的。其中:string類型默認分成:text和keyword兩種類型。如果你的業務中不需要分詞、檢索,僅需要精確匹配,僅設置為keyword即可。
根據業務需要選擇合適的類型,有利於節省空間和提升精度,如:浮點型的選擇。
3.2 Mapping各字段的選型流
3.3 選擇合理的分詞器
常見的開源中文分詞器包括:ik分詞器、ansj分詞器、hanlp分詞器、結巴分詞器、海量分詞器、“ElasticSearch最全分詞器比較及使用方法” 搜索可查看對比效果。
如果選擇ik,建議使用ik_max_word。因為:粗粒度的分詞結果基本包含細粒度ik_smart的結果。
3.4 date、long、還是keyword
根據業務需要,如果需要基於時間軸做分析,必須date類型;如果僅需要秒級返回,建議使用keyword
。
4、數據寫入優化實踐
4.1 要不要秒級響應?
Elasticsearch近實時的本質是:最快1s寫入的數據可以被查詢到。
如果refresh_interval
設置為1s,勢必會產生大量的segment,檢索性能會受到影響。
所以,非實時的場景可以調大,設置為30s,甚至-1。
4.2 減少副本,提升寫入性能。
寫入前,副本數設置為0,寫入后,副本數設置為原來值。
4.3 能批量就不單條寫入
批量接口為bulk,批量的大小要結合隊列的大小,而隊列大小和線程池大小、機器的cpu核數。
4.4 禁用swap
在Linux系統上,通過運行以下命令臨時禁用交換:
1sudo swapoff -a
5、檢索聚合優化實戰
5.1 禁用 wildcard模糊匹配
數據量級達到TB+甚至更高之后,wildcard在多字段組合的情況下很容易出現卡死,甚至導致集群節點崩潰宕機
的情況。
后果不堪設想。
替代方案:
方案一:針對精確度要求高的方案:兩套分詞器結合,standard和ik結合,使用match_phrase檢索。
方案二:針對精確度要求不高的替代方案:建議ik分詞,通過match_phrase和slop結合查詢。
5.2極小的概率使用match匹配
中文match匹配顯然結果是不准確
的。很大的業務場景會使用短語匹配“match_phrase”。
match_phrase結合合理的分詞詞典、詞庫,會使得搜索結果精確度更高,避免噪音數據。
5.3 結合業務場景,大量使用filter過濾器
對於不需要使用計算相關度評分的場景,無疑filter緩存機制
會使得檢索更快。
舉例:過濾某郵編號碼。
5.4控制返回字段和結果
和mysql查詢一樣,業務開發中,select * 操作幾乎是不必須的。
同理,ES中,_source 返回全部字段也是非必須的。
要通過_source 控制字段
的返回,只返回業務相關的字段。
網頁正文content,網頁快照html_content類似字段的批量返回,可能就是業務上的設計缺陷。
顯然,摘要字段應該提前寫入,而不是查詢content后再截取處理。
5.5 分頁深度查詢和遍歷
分頁查詢使用:from+size;
遍歷使用:scroll;
並行遍歷使用:scroll+slice
。
斟酌集合業務選型使用。
5.6 聚合Size的合理設置
聚合結果是不精確的。除非你設置size為2的32次冪-1,否則聚合的結果是取每個分片的Top size元素后綜合排序后的值。
實際業務場景要求精確反饋結果的要注意。盡量不要獲取全量聚合結果
——從業務層面取TopN聚合結果值是非常合理的。因為的確排序靠后的結果值意義不大。
5.7 聚合分頁合理實現
聚合結果展示的時,勢必面臨聚合后分頁的問題,而ES官方基於性能原因不支持聚合后分頁。
如果需要聚合后分頁
,需要自開發實現。包含但不限於:
方案一:每次取聚合結果,拿到內存中分頁返回。
方案二:scroll結合scroll after集合redis實現。
6、業務優化
讓Elasticsearch做它擅長的事情,很顯然,它更擅長基於倒排索引進行搜索。
業務層面,用戶想最快速度看到自己想要的結果,中間的“字段處理、格式化、標准化”等一堆操作,用戶是不關注的。
為了讓Elasticsearch更高效的檢索,建議:
1)要做足“前戲”
字段抽取、傾向性分析、分類/聚類、相關性判定放在寫入ES之前的ETL階段;
2)“睡服”產品經理
產品經理基於各種奇葩業務場景可能會提各種無理需求。
作為技術人員,要“通知以情曉之以理”,給產品經理講解明白搜索引擎的原理、Elasticsearch的原理,哪些能做,哪些真的“臣妾做不到
”。
7、小結
實際業務開發中,公司一般要求又想馬兒不吃草,又想馬兒飛快跑
。
對於Elasticsearch開發也是,硬件資源不足(cpu、內存、磁盤都爆滿)幾乎沒有辦法提升性能的。
除了檢索聚合,讓Elasticsearch做N多相關、不相干的工作,然后得出結論“Elastic也就那樣慢,沒有想像的快”。