ElasticSearch使用規(guī)范Beta版
本文轉(zhuǎn)載自微信公眾號(hào)「Redis開(kāi)發(fā)運(yùn)維實(shí)戰(zhàn)」,作者付磊。轉(zhuǎn)載本文請(qǐng)聯(lián)系Redis開(kāi)發(fā)運(yùn)維實(shí)戰(zhàn)公眾號(hào)。
ElasticSearch除了在日志場(chǎng)景(監(jiān)控、數(shù)據(jù)分析、debug)等場(chǎng)景大量使用以外,最近一年多在很多核心上的線上業(yè)務(wù)(譬如電商業(yè)務(wù))大量使用,目前接近了5000個(gè)節(jié)點(diǎn),目前在db-ranking(2020-11-24日),ElasticSearch在search-engine中常年第一:
對(duì)于MySQL、Redis這類(lèi)存儲(chǔ)緩存許多開(kāi)發(fā)同學(xué)多有很強(qiáng)的最佳實(shí)踐,但對(duì)于ElasticSearch的使用經(jīng)驗(yàn)相對(duì)模式。我個(gè)人經(jīng)驗(yàn)是ElasticSearch非常便于開(kāi)發(fā)(譬如支持dynamic mapping)但它相對(duì)脆弱:一方面是開(kāi)發(fā)同學(xué)對(duì)于其重視程度不夠(譬如沒(méi)有自己制定mapping)、另一方面它本身的一些設(shè)計(jì)(例如聚合計(jì)算都在JVM完成)導(dǎo)致其相對(duì)脆弱。
為此我們提供一份關(guān)于ElasticSearch的開(kāi)發(fā)規(guī)范幫助ElasticSearch使用者減少一些可能碰到的坑
一、容量規(guī)劃
1. 分片(shard)容量
- 非日志型(搜索型、線上業(yè)務(wù)型)的shard容量在10~30GB(建議在10G)
- 日志型的shard容量在30~100GB(建議30G)
- 單個(gè)shard的文檔個(gè)數(shù)不能超過(guò)21億左右(Integer.MAX_VALUE - 128)
注:一個(gè)shard就是一個(gè)lucene分片,ES底層基于lucene實(shí)現(xiàn)。
2. 索引(index)數(shù)量
- 大索引需要拆分:增強(qiáng)性能,風(fēng)險(xiǎn)分散。
反例:一個(gè)10T的索引,例如按date查詢(xún)、name查詢(xún)
正例:index_name拆成多個(gè)index_name_${date}
正例:index_name按hash拆分index_name_{1,2,3,...100..}
- 提示:索引和shard數(shù)并不是越多越好,對(duì)于批量讀寫(xiě)都會(huì)有性能下降,所以要綜合考慮性能和容量規(guī)劃,同時(shí)配合壓力測(cè)試,不存在真正的最優(yōu)解。
3. 節(jié)點(diǎn)、分片、索引
一個(gè)節(jié)點(diǎn)管理的shard數(shù)不要超過(guò)200個(gè)
4. 示意圖
(1) 集群
(2) 節(jié)點(diǎn):
(3) 索引:
(4) 分片(shard)
二、 索引mapping設(shè)計(jì)
大原則:不用默認(rèn)配置和動(dòng)態(tài)mapping、數(shù)據(jù)用途(類(lèi)型、分詞、存儲(chǔ)、排序)弄清,下面是一個(gè)標(biāo)準(zhǔn)mapping:
1. shard個(gè)數(shù)(number_of_shards):
參考一
2. refresh頻率(refresh_interval):
ES的定位是準(zhǔn)實(shí)時(shí)搜索引擎,該值默認(rèn)是1s,表示寫(xiě)入后1秒后可被搜索到,所以這里的值取決于業(yè)務(wù)對(duì)實(shí)時(shí)性的要求,注意這里并不是越小越好,刷新頻率高也意味著對(duì)ES的開(kāi)銷(xiāo)也大,通常業(yè)務(wù)類(lèi)型在1-5s,日志型在30s-120s,如果集中導(dǎo)入數(shù)據(jù)可將其設(shè)置為-1,ES會(huì)自動(dòng)完成數(shù)據(jù)刷新(注意完成后更改回來(lái),否則后續(xù)會(huì)出現(xiàn)搜索不到數(shù)據(jù))
3. 使用別名(aliases):不要過(guò)度依賴(lài)別名功能
正例:
- 索引名:index_name_v1
- 別名:index_name
未來(lái)重建index_name_v2索引,對(duì)于業(yè)務(wù)來(lái)說(shuō)只需要換別名。
4. type個(gè)數(shù)
1個(gè)就夠了,從ES6開(kāi)始只支持一個(gè)type,這個(gè)type比較雞肋,后面的版本可能會(huì)去掉。
如果一定用:針對(duì)已經(jīng)使用多個(gè)type的場(chǎng)景,一定要保證不同type下字段盡量保持一致,否則會(huì)加大數(shù)據(jù)稀疏性,存儲(chǔ)與查詢(xún)性能受影響
5. 慢日志(slowlog):
一定要配置,默認(rèn)不記錄慢查詢(xún),kcc提供了grafana、kibana查詢(xún)功能。
6. 副本(number_of_replicas)
1個(gè)就夠用,副本多寫(xiě)入壓力不可忽視。極端情況下:譬如批量導(dǎo)入數(shù)據(jù),可以將其調(diào)整為0.
7. 字段設(shè)計(jì)
(1) text和keyword的用途必須分清:分詞和關(guān)鍵詞(確定字段是否需要分詞)
(2) 確定字段是否需要獨(dú)立存儲(chǔ)
(3) 字段類(lèi)型不支持修改,必須謹(jǐn)慎。
(4) 對(duì)不需要進(jìn)行聚合/排序的字段禁用doc_values
- text 類(lèi)型作用:分詞,用于搜索。
- 適用于:email 內(nèi)容、某產(chǎn)品的描述等需要分詞全文檢索的字段;
- 不適用:排序或聚合(Significant Terms 聚合例外)
- keyword 類(lèi)型:無(wú)需分詞、整段完整精確匹配。
- 適用于:email 地址、住址、狀態(tài)碼、分類(lèi) tags。
(5) 不要在text做模糊搜索:
8. 設(shè)置合理的routing key(默認(rèn)是id)
id不均衡:集群容量和訪問(wèn)不均衡,對(duì)于分布式存儲(chǔ)是致命的。
9. 關(guān)閉_all
ES6.0已經(jīng)去掉,對(duì)容量(索引過(guò)大)和性能(性能下降)都有影響。
10. 避免大寬表:
ES默認(rèn)最大1000,但建議不要超過(guò)100.
11. text類(lèi)型的字段不要使用聚合查詢(xún)。
text類(lèi)型fileddata會(huì)加大對(duì)內(nèi)存的占用,如果有需求使用,建議使用keyword
12.聚合查詢(xún)避免使用過(guò)多嵌套,
聚合查詢(xún)的中間結(jié)果和最終結(jié)果都會(huì)在內(nèi)存中進(jìn)行,嵌套過(guò)多,會(huì)導(dǎo)致內(nèi)存耗盡
比如以下聚合就嵌套了3層,country、city和salary的結(jié)果都會(huì)保存在內(nèi)存中,如果唯一值較多,就會(huì)導(dǎo)致內(nèi)存耗盡
- {
- "aggs":{
- "country":{
- "terms":{
- "filed":"country",
- "size":10
- },
- "aggs":{
- "city":{
- "terms":{
- "filed":"city",
- "size":20
- },
- "aggs":{
- "salary":{
- "terms":{
- "filed":"salary",
- "size":20
- }
- }
- }
- }
- }
- }
- }
- }
三、違規(guī)操作
1. 原則:不要忽略設(shè)計(jì),快就是慢,壞的索引設(shè)計(jì)后患無(wú)窮.
2. 拒絕大聚合 :ES計(jì)算都在JVM內(nèi)存中完成。
3. 拒絕模糊查詢(xún):es一大殺手
- {
- "query":{
- "wildcard":{
- "title.keyword":"*張三*"
- }
- }
- }
4. 拒絕深度分頁(yè)
ES獲取數(shù)據(jù)時(shí),每次默認(rèn)最多獲取10000條,獲取更多需要分頁(yè),但存在深度分頁(yè)問(wèn)題,一定不要使用from/Size方式,建議使用scroll或者searchAfter方式。scroll會(huì)把上一次查詢(xún)結(jié)果緩存一定時(shí)間(通過(guò)配置scroll=1m實(shí)現(xiàn)),所以在使用scroll時(shí)一定要保證search結(jié)果集不要太大。
5. 基數(shù)查詢(xún)
盡量不要用基數(shù)查詢(xún)?nèi)ゲ樵?xún)?nèi)ブ睾蟮臄?shù)據(jù)量大小(kibana中界面上顯示是Unique Count,Distinct Count等),即少用如下的查詢(xún):
- "aggregations": {
- "cardinality": {
- "field": "userId"
- }
- }
6. 禁止查詢(xún) indexName-*
7. 避免使用script、update_by_query、delete_by_query,對(duì)線上性能影響較大。
四、常見(jiàn)問(wèn)題
1. 一個(gè)索引的shard數(shù)一旦確定不能改變
2. ES不支持事務(wù)ACID特性。
3. reindex:
reindex可以實(shí)現(xiàn)索引的shard變更,但代價(jià)非常大:速度慢、對(duì)性能有影響,所以好的設(shè)計(jì)和規(guī)劃更重要
五、grafana使用規(guī)范
1.查詢(xún)范圍不要太大,建議在3h以?xún)?nèi)
如下查詢(xún)7d,數(shù)據(jù)量巨大,嚴(yán)重影響集群查詢(xún)性能
2. 拒絕多層嵌套,不要超過(guò)2層
如下圖中進(jìn)行了4層嵌套,每層嵌套的結(jié)果都緩存在內(nèi)存中,導(dǎo)致內(nèi)存崩潰
3. 拒絕分時(shí)查詢(xún)
分位查詢(xún)相當(dāng)于一種分桶聚合方式,分的桶越多,帶來(lái)的CPU計(jì)算量越大
4. 拒絕TOP>100查詢(xún)
top查詢(xún)是在聚合的基礎(chǔ)上再進(jìn)行排序,如果top太大,cpu的計(jì)算量和耗費(fèi)的內(nèi)存都會(huì)導(dǎo)致查詢(xún)瓶頸
5. 拒絕正則匹配查詢(xún)