優化
es的安裝和配置是非常輕量級的,為滿足多種不同的應用場景,底層提供多種數據結構支持,並做了大量的默認配置優化,部分配置針對具體的用戶使用場景可能是冗余的,甚至可能造成性能的下降,需要根據實際業務場景做適當取舍,我們結合自身使用場景做了如下優化(文章中有疏漏或不正確的地方也歡迎點評指正)。
一、環境配置
sudo swapoff -a
# 禁用swapping,開啟服務器虛擬內存交換功能會對es產生致命的打擊
vm.max_map_count
# 在/etc/sysctl.conf文件中找到該參數,修改為655300后 執行sysctl -p,不然啟動時會報值太小
二、內存優化
常用的配置在兩個文件里,分別是 elasticsearch.yml 和 jvm.options(配置內存)
jvm.options主要是進行內存相關配置,elasticsearch默認給的1g,官方建議分配給es的內存不要超出系統內存的50%,預留一半給Lucene,因為Lucene會緩存segment數據提升檢索性能;內存配置不要超過32g,如果你的服務器內存沒有遠遠超過64g,那么不建議將es的jvm內存設置為32g,因為超過32g后每個jvm對象指針的長度會翻倍,導致內存與cpu的開銷增大。
-Xms10g
-Xmx10g
三、基礎配置
修改配置文件elasticsearch.yml
cluster.name: elasticsearch
集群名稱,es服務會通過廣播方式自動連接在同一網段下的es服務,通過多播方式進行通信,同一網段下可以有多個集群,通過集群名稱這個屬性來區分不同的集群。
node.name: "test"
當前配置所在機器的節點名,你不設置就默認隨機指定一個name列表中名字,該name列表在es的jar包中config文件夾里name.txt文件中,其中有很多作者添加的有趣名字。
node.master: true
指定該節點是否有資格被選舉成為node(注意這里只是設置成有資格, 不代表該node一定就是master),默認是true,es是默認集群中的第一台機器為master,如果這台機掛了就會重新選舉master。
node.data: true
指定該節點是否存儲索引數據,默認為true。
index.number_of_shards: 5
設置默認索引分片個數,默認為5片。
index.number_of_replicas: 1
設置默認索引副本個數,默認為1個副本。如果采用默認設置,而你集群只配置了一台機器,那么集群的健康度為yellow,也就是所有的數據都是可用的,但是某些復制沒有被分配。
path.conf: /path/to/conf
設置配置文件的存儲路徑,默認是es根目錄下的config文件夾。
path.data: /path/to/data
設置索引數據的存儲路徑,默認是es根目錄下的data文件夾,可以設置多個存儲路徑,用逗號隔開,例:path.data: /path/to/data1,/path/to/data2
path.work: /path/to/work
設置臨時文件的存儲路徑,默認是es根目錄下的work文件夾。
path.logs: /path/to/logs
設置日志文件的存儲路徑,默認是es根目錄下的logs文件夾
path.plugins: /path/to/plugins
設置插件的存放路徑,默認是es根目錄下的plugins文件夾, 插件在es里面普遍使用,用來增強原系統核心功能。
bootstrap.mlockall: true
設置為true來鎖住內存不進行swapping。因為當jvm開始swapping時es的效率 會降低,所以要保證它不swap,可以把ES_MIN_MEM和ES_MAX_MEM兩個環境變量設置成同一個值,並且保證機器有足夠的內存分配給es。 同時也要允許elasticsearch的進程可以鎖住內存,linux下啟動es之前可以通過`ulimit -l unlimited`命令設置。
network.bind_host: 192.168.0.1
設置綁定的ip地址,可以是ipv4或ipv6的,默認為127.0.0.1。
network.publish_host: 192.168.0.1
設置其它節點和該節點交互的ip地址,如果不設置它會自動判斷,值必須是個真實的ip地址。
network.host: 192.168.0.1
這個參數是用來同時設置bind_host和publish_host上面兩個參數。
transport.tcp.port: 9300
設置節點之間交互的tcp端口,默認是9300。
transport.tcp.compress: true
設置是否壓縮tcp傳輸時的數據,默認為false,不壓縮。
http.port: 9200
設置對外服務的http端口,默認為9200。
http.max_content_length: 100mb
設置內容的最大容量,默認100mb
http.enabled: false
是否使用http協議對外提供服務,默認為true,開啟。
gateway.type: local
gateway的類型,默認為local即為本地文件系統,可以設置為本地文件系統,分布式文件系統,hadoop的HDFS,和amazon的s3服務器等。
gateway.recover_after_nodes: 1
設置集群中N個節點啟動時進行數據恢復,默認為1。
gateway.recover_after_time: 5m
設置初始化數據恢復進程的超時時間,默認是5分鍾。
gateway.expected_nodes: 2
設置這個集群中節點的數量,默認為2,一旦這N個節點啟動,就會立即進行數據恢復。
cluster.routing.allocation.node_initial_primaries_recoveries: 4
初始化數據恢復時,並發恢復線程的個數,默認為4。
cluster.routing.allocation.node_concurrent_recoveries: 2
添加刪除節點或負載均衡時並發恢復線程的個數,默認為4。
indices.recovery.max_size_per_sec: 0
設置數據恢復時限制的帶寬,如入100mb,默認為0,即無限制。
indices.recovery.concurrent_streams: 5
設置這個參數來限制從其它分片恢復數據時最大同時打開並發流的個數,默認為5。
discovery.zen.minimum_master_nodes: 1
設置這個參數來保證集群中的節點可以知道其它N個有master資格的節點。默認為1,對於大的集群來說,可以設置大一點的值(2-4)
discovery.zen.ping.timeout: 3s
設置集群中自動發現其它節點時ping連接超時時間,默認為3秒,對於比較差的網絡環境可以高點的值來防止自動發現時出錯。
discovery.zen.ping.multicast.enabled: false
設置是否打開多播發現節點,默認是true。
discovery.zen.ping.unicast.hosts: ["host1", "host2:port", "host3[portX-portY]"]
設置集群中master節點的初始列表,可以通過這些節點來自動發現新加入集群的節點。
三、集群優化
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系統上,通過運行以下命令臨時禁用交換: sudo swapoff -a 1 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.3控制返回字段和結果 和mysql查詢一樣,業務開發中,select * 操作幾乎是不必須的。 同理,ES中,_source 返回全部字段也是非必須的。 要通過_source 控制字段的返回,只返回業務相關的字段。 網頁正文content,網頁快照html_content類似字段的批量返回,可能就是業務上的設計缺陷。 顯然,摘要字段應該提前寫入,而不是查詢content后再截取處理。 5.4 分頁深度查詢和遍歷 分頁查詢使用:from+size; 遍歷使用:scroll; 並行遍歷使用:scroll+slice。 斟酌集合業務選型使用。 5.5 聚合Size的合理設置 聚合結果是不精確的。除非你設置size為2的32次冪-1,否則聚合的結果是取每個分片的Top size元素后綜合排序后的值。 實際業務場景要求精確反饋結果的要注意。 盡量不要獲取全量聚合結果——從業務層面取TopN聚合結果值是非常合理的。因為的確排序靠后的結果值意義不大。 5.6 聚合分頁合理實現 聚合結果展示的時,勢必面臨聚合后分頁的問題,而ES官方基於性能原因不支持聚合后分頁。 如果需要聚合后分頁,需要自開發實現。包含但不限於: 方案一:每次取聚合結果,拿到內存中分頁返回。 方案二:scroll結合scroll after集合redis實現。
