前言
- 為什麼es查詢和聚合都這麼快?底層是如何實現的?
- 資料在es叢集中如何儲存的?如何做到自動分散式的?
- 為什麼es的主分片數設定了之後就不能調整,而副本分片數可以調整?
- 如何優化索引方式和查詢方式,有效利用快取,提高查詢效率?
- 如果保證不停服的情況下,平滑升級或擴容?
- 如何優化查詢效率?
相信看完Elasticsearch權威指南這本書,所有疑問都將得到解答
一. 基本概念
1. 分片
- 最小級別的工作單元,儲存索引中一部分資料。是一個Lucene例項,本身就是一個完整的搜尋引擎。但是應用程式不會直接與分片通訊。
- 可以想象成容器,節點間資料遷移以分片為單位
- 分為主分片和副分片(主分片的副本)
- 索引建立的時候,主分片的數量就固定了,但是副本分片數量可調整
- 預設一個索引分配5個主分片
- 主分片所在節點掛掉後,重新選舉主節點,並將副分片升級為主分片
- 故障節點重新啟動後,會同步故障期間未同步到到資料
2. 文件
- 根物件序列化成json物件
- 每次對文件的操作(包括修改,刪除),_version都會加一
- 文件是不可修改的。update是先刪除,再新建一個新的
- 刪除的文件並不會被立即移除,只是標記為刪除。之後後臺再清理
- 自己設定文件的版本:新增version_type=external引數
3. 衝突解決
- 通過版本號實現樂觀鎖解決衝突問題
4. 文件後設資料
- _index 文件儲存的地方
- _type 文件代表的物件的類(7.x的版本將去掉_type)
- _id 文件的唯一標識。可手動設定也可自動生成(22位長)
5. 叢集架構圖
兩個節點,三個主分片,一個副分片的效果圖
擴充套件到三個節點到效果圖
6. 叢集狀態
叢集狀態是一個資料結構,叢集狀態存在每個客戶端中。儲存以下資訊
- 級別設定
- 叢集節點
- 索引以及相關的對映,別名等資訊
- 索引的分片,以及分配的節點
叢集狀態-status
- green:所有主分片和副分片都已經分配
- yellow:所有主分片都已分配,至少有一個副本分片沒有分配
- red:至少一個主分片(或全部副分片)缺失
二. 叢集工作原理
1. 資料是如何在分散式系統儲存的
- 文件通過路由存放到分片
- 通過以下演算法得出該文件儲存時的分片編號
shard = hash(routing) % number_of_primary_shards 複製程式碼
- routing是任意字串,預設是_id
- 主分片的數量不可改變,否則之前的路由失效,文件就找不到了
- 自定義路由可以保證有關聯性的文件被儲存在同一個分片
2. 主分片和複製分片如何互動?
- 請求能夠被髮送給任意節點
- 每個節點都有能力處理任意請求
- 每個節點都知道任意文件所在節點(儲存的叢集狀態),並轉發請求
- 傳送請求時最好迴圈每個節點以負載均衡
2.1 write操作(新建、刪除、索引)
順序步驟
- 客戶端傳送請求(新建,刪除,索引)到node1節點
- 節點使用hash演算法得出分片編號0,因為分片0在節點3,將請求轉發到節點3
- node3成功儲存資料到主分片,如果成功,轉發請求到node1和node2到副節點
- 所有複製節點成功,傳送成功回覆到請求節點1,節點1再返回給客戶端
可調的引數
- replication:預設為sync,主分片得到複製分片成功響應才返回。async表示請求在主分片執行成功就返回,依舊轉發請求到副分片,不過不知道成功與否
- consistency:主分片嘗試寫入時,需要規定數量(quorum)或過半的分片可用。可為one,all,quorum(預設)。quorum只有在number_of_replicas大於1時才生效
int((primary[總是1] + number_of_replicas) /2 + 1) 複製程式碼
- timeout:分片不足時,等待時間。預設1min
2.2 read操作
- 客戶端傳送get請求到node1
- 節點使用hash演算法,得到文件所屬到主分片為0分片
- 找到分片0的副分片所在節點為node1,node2,node3
- 通過某種策略選定某個副分片節點,比如node2
- node2返回文件給node1
- 然後node1返回給客戶端
2.3 update操作
順序步驟
- 客戶端給node1傳送更新請求
- 通過雜湊演算法得到主分片位置,轉發請求到node3
- node3檢索出文件,修改_source欄位到json文件,然後重建索引。如果有其他程式修改了文件,它以retry_on_conflict設定的次數重複這一步,都未成功則放棄
- node3更新成功則傳送整個新文件(並不是修改請求)到node1和node2的複製節點重建索引,都成功則返回給node1,再返回給客戶端
2.4 多文件模式
mget 多文件read
- 客戶端傳送mget請求給node1
- node1為每個分片構建一個請求,並轉發到對應分片所在節點
- 當所有回覆被接收,node1組合這些響應,返回給客戶端
bulk 多文件write
- 客戶端向node1傳送請求
- node1為每個分片構建批量請求,然後轉發到這些主分片上
- 主分片按序執行,每一個完成時,傳送到副分片上
- 所有操作都完成後節點整理響應返回給客戶端
3. 索引是如何建立的
3.1 基本概念
- 對映(mapping):用於欄位確認,每個欄位匹配為確認的資料型別
- 分析(analysis):全文文字分詞,以建立倒排索引
- 倒排索引:由文件中單詞的唯一列表和單詞在文件中的位置組成,用於快速檢索結果而設計
3.2 分析(analysis)
分析的過程
- 分析由分析器(analyzer)完成
- 分析過程先標記一段文字為單獨的詞(item)
- 然後標準化(比如全部轉為小寫)item,以提高搜尋性
- 分析的詳情可通過_analyze API檢視
分析器包括的元件
es提供很多可用直接使用的元件,可自定義組合使用
- 字元過濾器(character filter):字串先經過這做一些過濾操作
- 分詞器(tokenizer):將文字切分為單詞,比如空格,逗號等。中文可用專門的分詞器
- 標記過濾器(token filter):修改詞語,比如轉小寫,去掉語氣詞,增加同義詞
內建的分析器
- 標準分析器:預設使用這個。標準切分,去掉大部分符號,最後轉為小寫
- 空格分析器:按空格切分,不轉換為小寫
- 語言分析器:根據特定語言的特性做分析
查詢方式
- 欄位查詢:精確匹配,查詢前不會將被查詢的字串分析
- 全文查詢:查詢前會先用分析器分析要查詢的字串
手動指定分析器
- 當往es中加入字串時,es會自動用標準分析器做分詞,但是可能某些字元就是普通的id,標籤等欄位,不需要做分析,可手動指定對映
建立索引時查詢分析器的順序
- mapping檔案中指定欄位的analyzer
- 文件本身的_analyzer欄位
- mapping檔案中指定型別的預設analyzer
- mapping檔案中全域性預設的analyzer
- 節點級別預設的analyzer
- 標準analyzer
查詢索引時查詢分析器的順序
- 查詢引數中的analyzer
- mapping檔案中指定欄位的analyzer
- mapping檔案中指定型別的analyzer
- mapping檔案中全域性預設的analyzer
- 節點級別預設的analyzer
- standard analyzer
3.3 對映
作用
定義欄位型別,欄位的資料型別以及被es處理的方式。
支援的欄位型別
型別 | 表示的資料型別 |
---|---|
String | string |
Whole Number | byte short integer long |
Floating point | float double |
Boolean | boolean |
Date | date |
新的欄位如果沒有配置對映,es會自動猜測欄位型別
自定義欄位對映可實現的功能
- 區分全文字串(需要分詞)和精確字串(不需要分詞)
- 使用特定語言的分析器
- 優化部分匹配欄位
- 指定自定義日期格式
對映包含的引數
- properties:列出了可能包含的每個欄位的對映
- 後設資料欄位:_type, _id, _source
- dynamic:確定欄位新增時的策略(_source會一直儲存)
- ture 自動新增
- false 忽略欄位
- strict 丟擲異常
- 設定項:如analyzer
- 其他設定
自定義欄位對映注意點
- 要對映的欄位引數為type, 除了string外,很少需要對映其他type
- string欄位的index欄位,控制字串以什麼方式被索引。
值 含義 analyzed 分詞索引 not_analyzed 不分詞索引 no 不索引 - string欄位選擇anlyzed為index時,analyzer指定分析器。如:simple, english, whitespace
- 更新對映只能新增欄位,不能修改已經被新增的欄位。否則會導致出錯索引不到
文件欄位的屬性
- type
- index
- analyzer
- ip
- geo_point
- geo_shape
後設資料_source欄位
- 作用: 用於儲存原始json欄位
- 為什麼需要
- 搜尋結果能得到完整文件
- 缺少它,部分更新請求不起作用
- 更新對映檔案時,可直接取內容
- 更易排查錯誤
- 怎麼禁用:enabled:false
- 使用:搜尋時可以通過_source指定只返回哪些列
後設資料_all欄位
- 查詢不知道指定哪個欄位時,使用_all。也可禁用。使用_all時,會將其他所有欄位的值作為一個大的字串進行索引
動態模版
dynamic_templates 設定通過欄位名或型別動態匹配不同的對映
- match_mapping_type 模版使用的資料型別
- match 模版使用的欄位名
- path 模版使用的欄位全路徑(巢狀json)
三. 結構化查詢語言
1. 過濾
概述
文件的欄位是否包含特定值,比查詢更快,結果可快取
原則上全文索引或者需要其他相關性評分的使用查詢語句,其他情況都用過濾。
重要的過濾語句
- term:精確匹配
- terms:多個條件的精確匹配
- range:範圍過濾
- exists:是否包含指定欄位
- missing:沒有某個欄位
- bool:合併多個過濾查詢結果
- must:and
- must_not:not
- shoud:or
過濾順序
- 過濾順序對效能有很大影響
- 更詳細的過濾條件應該放在最前,以便排除更多的文件
- 被快取的過濾應該放到不會快取的過濾前面(快取參考後面章節)
2. 查詢
簡述
每個文件的欄位與特定欄位的匹配程度如何,比過濾慢,結果不可快取
重要的查詢語句
- math_all:查詢所有文件
- match:標準查詢,全文和精確都支援
match指定多個值時,內部分詞後會執行多個match並放入bool查詢。預設為or。可通過operator引數改為“and”
- multi_match:同時搜尋多個欄位,支援萬用字元
- bool:同bool過濾,多的是要計算_score
3. 相關性排序
排序方式
-
_score:預設排序方式,預設倒序
-
欄位排序:_score不需要計算,預設正序
-
多級排序:可指定多個欄位。先用第一個欄位排序,第一個相同時排第二個
-
字串引數排序:
被分析的欄位進行強制排序會消耗大量記憶體
相關性簡介
相似度演算法:TF/IDF(檢索詞詞頻/反向文件頻率)
- TF: 詞頻,出現在當前文件次數越多,相關性越大
- IDF:反轉文件頻率,所有文件數與出現這個詞的檔案數百分比,詞出現頻率越大,IDF越小
- 由於效能問題,每個分片只會計算該分片內的IDF,而不是所有文件
- boost引數可以設定權重
4. 分散式搜尋的執行方式
概述
搜尋包括查詢多個分片,並將多個分片元資訊合併,然後再根據後設資料獲取真正資料兩個步驟。
查詢多個索引和查詢一個索引完全一致,無非是多查了幾個分片。擴充套件的時候,可以不用將舊資料遷移到新索引,直接新建索引,然後查詢兩個索引,或者別名索引即可
查詢(query)
-
客戶端傳送search給node3,建立一個from+size的空優先順序佇列
-
廣播請求到每個分片,每個分片在本地執行查詢,並放到一個大小為from+size的本地優先順序佇列裡
-
每個節點返回查詢結果(id和_score)給node3,node3將結果全域性排序
- 多個請求會輪詢所有的分片副本以負載均衡,提高系統吞吐率
- 多索引的工作機制和單索引類似,只不過多了些分片
- 深度分頁會導致排序過程非常繁重,佔用巨大cpu和寬頻
取回(fetch)
- 協調節點辨別出哪些文件需要取回,並向相應分片傳送請求
- 每個分片載入文件,並做相關處理(比如高亮),然後返回給協調節點
- 協調節點將資料返回給客戶端
搜尋選項(可選引數)
- preference:控制使用哪個分片或節點處理請求
- timeout:協調節點等待多久就放棄其他節點的結果
- routing:限制只搜尋哪些分片,對於大規模系統很有用
- search_type:query_then_fetch為預設的搜尋型別
- count:當不需要結果,只需要數量時
- query_and_fetch:查詢並且取回
- dfs_query_and_fetch,dfs_query_then_fetch
- scan:掃描,和scroll一起使用。可高效取回大量資料。禁用排序實現
掃描和滾屏
scroll
類似傳統資料庫的遊標,搜尋的是查詢時的索引快照,查詢結束之前的修改不會感知到
scan
不排序,只要有結果就返回
四. 分片內部原理
1. 索引動態更新原理
1.1 倒排索引-保證文件可被搜尋
1.2 倒排索引的內容是不可變的
1.3 不可變的同時動態新增段
查詢的時候,所有段依次查詢,然後聚合結果,通過這種方式,新文件以最小代價加入文件
- 新的文件首先寫入記憶體區的索引快取
- buffer中包括新的段包含的倒排索引,段名等
- buffer被提交
- 新段被開啟,文件可被索引
- 記憶體快取被清除,等待新文件
1.4 刪除和更新
因為段不可變,更新和刪除操作並不是真的刪除,是通過新增.del檔案和新建段檔案,查詢返回前將標記為del的檔案從結果中刪除
1.5 近實時搜尋
因為從buffer刷入磁碟代價很大。es允許一旦一個檔案被快取,就可以設定段開啟,檔案可以被搜尋到
1.6 重新整理
每個分片預設每秒開啟一個新段,所以新的改動需要1s後才能看到。可以設定refresh_interval減少重新整理的頻率
1.7 持久化變更
新增緩衝buffer的同時,通過新增事務日誌(預設512M),保證資料被完整持久化。每次flush(每30分鐘,或事務日誌過大)到磁碟時,段被全部提交,清空事務日誌
1.8 合併段
通過每秒自動重新整理段,不用多久段資料就劇增。每個段消耗計算機資源,且每次查詢都要依次檢查每個段,段越多查詢越慢。es後臺合併段解決該問題。 合併大的段會消耗io和cpu資源。
1.9 Optimize API
強制合併段。對於資料不再變動的索引很有效,對資料還在動態增長的索引不要使用。
2. 快取
概述
- 快取針對過濾查詢
- 核心是一個位元組集儲存哪些文件符合過濾條件
- 快取的位元組集是增量更新的
- 每個過濾器都是獨立快取的,且可複用
- 大部分枝葉過濾器(如term)會被快取,而組合過濾器(如bool)不會被快取
不可被快取的情況
- 指令碼過濾器,指令碼對es是不透明的
- Geo(地址)過濾器,不太會被重用
- 日期範圍精確到毫秒不會被快取,整數會被快取
過濾時間範圍的使用建議
- 對於時間精確到毫秒的查詢,可拆分為日期+日期時間兩個過濾條件,前者會被快取,且順序不要改變
五. 全文檢索
1. 全文檢索包括兩個方面
- 相關度(Relevance):TF/IDF,地理位置相近度,模糊相似度或其他演算法
- 分析(Analysis):分詞,建立倒排索引
2. 全文查詢分類
- 低階查詢:term查詢。沒有分析階段,會精確匹配特定短語
- 全文檢索:match,query_string等查詢。有分析階段。
- date,integer型別:精確查詢
- not_analyzed的string型別:分析查詢詞語(比如轉小寫),執行單個短語查詢
- analyzed的string型別:先解析查詢語句,生成短語列表。查詢後再合併查詢結果
六. 聚合
1. 基本概念
桶(buckets)
滿足特定條件的文件的集合。類似於sql裡面的group by
指標(metrics)
對桶內的文件進行統計計算。類似sql裡面的count,sum,max等統計方法
2. 近似聚合
2.1 概述
- 分散式演算法三個因子模型同時只能選擇滿足兩項:精確,實時,大資料
- ea選擇大資料和實時。會提供準確但不是100%精確的結果,以犧牲一點小的估算錯誤作為代價,換來告訴的執行效率和極小的記憶體消耗
- 兩個近似演算法:cardinality, percentiles
2.2 cardinality 基數度量
- 類似sql的distinct
- 是一個近似演算法。基於HyperLogLot++(HLL)演算法的。HLL先對輸入做雜湊運算,根據hash運算的記過中的bits做概率估算得到基數。HLL 論文
- 演算法特性
- 可配置精度:引數為precision_threshold (精度更高=跟多記憶體)
- precision_threshold範圍為0-4000,資料結構使用記憶體為:precision_threshold * 8
- 設定為100時,可保證百萬級別的資料量誤差維持5%以內
- 小的資料集精度非常高
- 可配置使用的固定記憶體量
- 優化:預先計算hash值,不過效能的瓶頸由聚合時轉移到索引時(必須重新建索引,新增hash欄位),需要根據業務場景來確定。
2.3 percentiles 百分位數度量
- 展現了以某個具體百分比執行觀察到的數值,通常用於找出異常。
- 也是一個近似演算法。使用TDigest演算法
- 演算法特性
- 極端百分比的情況下,資料更準確。比如1%或99%。這由資料結構決定。
- 小資料集精度非常準確
3. significant_terms
- sigterms和其他聚合不同,用於發現資料集中醫學異常指標
- 通過統計資料並對比正常資料找到可能有異常頻次的指標
4. 聚合的資料結構
4.1 Doc Values
-
聚合,排序使用Doc Values的資料結構
-
將文件對映到他們包含的詞項
-
在索引時和倒排索引同時生成。基於segment且不可變。
-
Doc values資料存放到磁碟中,不是由jvm管理。
-
採用列式儲存,資料整齊排布,便於壓縮
-
不支援analyzed欄位
-
除了analyzed的字串,預設所有欄位都開啟doc values。如果你永遠不會對某些欄位進行聚合,排序操作,可以禁用doc values。可以節省磁碟空間和索引速度
4.2 Fielddata
- anaylzed的字串,使用Fielddata這種資料結構支援聚合,fielddata儲存在記憶體堆中,舊版本沒有doc values時是用的fielddata
- anaylzed的過程會消耗極大記憶體,且生成大量token,對聚合很不友好
- fieldata會一直存在記憶體中,直到被驅逐或節點崩潰。注意觀察它的大小。
- dielddata不會在建索引時存在,是查詢時建立的
- indices.fielddata.cache.size:百分比或實際大小。 控制為 fielddata 分配的堆空間大小。每次聚合查詢時,分析欄位會載入到Fielddata中,如果查詢結果中 fielddata 大小超過了指定的大小 ,其他的值將會被回收從而獲得空間。
- 如果沒有足夠空間可以將 fielddata 保留在記憶體中,Elasticsearch 就會時刻從磁碟過載資料,並回收其他資料以獲得更多空間。記憶體的回收機制會導致重度磁碟I/O,並且在記憶體中生成很多垃圾,這些垃圾必須在晚些時候被回收掉。
- 監控filddata: GET /_stats/fielddata?fields=*
5. 聚合優化
- 針對大量資料的巢狀聚合查詢,效率極低。預設的查詢方式為深度優先。
- 可以使用廣度優先處理聚合數量遠遠小於總組數的情況。引數為collect_mode: breadth_first
七. 地理位置
1. 設定欄位型別為地理位置
地理座標點不能被動態對映欄位檢測,需要顯式申明對應欄位型別(type引數)為geo_point
2. geo_point格式
- 字串: "40.715, -74.011", 維度在前,精度在後
- 陣列: [40.715, -74.011], 維度在前,精度在後
- 物件: {"lat": 40.715, "lon": -74.011}
3. 過濾方式
- geo_bounding_box :: 落在指定矩形框中的座標點
- geo_distance :: 給定距離內的點
- geo_distance_range :: 距離範圍內的點
- geo_polygon :: 落在多邊形中的點
4. 使用注意
- 地理座標過濾器使用代價很高,它會將所有文件的地理位置資訊載入記憶體,然後計算。使用時謹慎,或放到過濾的最後
- bool過濾器預設會將地理資訊過濾排到最後
- 預設是不被快取的
- 每個經緯度組合需要16自己的記憶體,可設定壓縮格式,減少精度,減少記憶體
- 合理設定精度:geohash_prefix和geohash_precision兩個引數。再結合geohash過濾器可高效查詢
5. geohash
- 把世界分為4*8=32個單元的各自,每一個格子用一個字母或數字標識。這些單元有被繼續分解成32個更小的單元,不斷重複
- 長度越長,精度越高
- 有同一字首的geohash,位置靠的近,共同字首越長,距離越近
- 剛好相鄰的位置也有可能geohash完全不同
6. 地理位置聚合
- geo_distance 距離聚合:將文件以指定中心店為圓心的圓環分組
- geohash_grid網格聚合:將文件按geohash單元分組,以便在地圖上呈現
- geo_bounds: 邊界聚合:包含座標點的矩形框
7. 地理形狀(geo_shape)
- 地理形狀是通過一個個geohash單元畫出來的
八. 資料建模
1. 關聯關係
關聯關係的處理,使用扁平化的儲存,將資料冗餘到同一個索引,提高查詢效率
2. 巢狀物件
設計
內部儲存
普通對json含有陣列時,內部儲存會被扁平化,導致邏輯關係丟失。需改為nested關係,而不是預設的object。巢狀物件內部會被索引為分離的隱藏文件
查詢
使用特殊的nested查詢或nested過濾
排序
3. 父子關係
原理
- 和nested差不多,區別是nested是儲存在同一個文件中,而父子關係是完全不同的文件
- 父子文件需儲存在同一個分片中
- 父子關係對映儲存在doc-values的資料結構中,完全存在記憶體
- 適合父文件少,子文件多的情況
優勢
- 更新父文件時,不用更新子文件索引
- 建立刪除修改子文件時,不影響父文件和其他文件
劣勢
- 查詢速度比巢狀型別慢5-10倍
- 不適合父文件多的情況
設計父子關係
- 指定某一文件type為另一文件type的parent
- 建立父文件時,和普通文件沒區別
- 建立子文件時,必須通過parent指定父文件id。作用是建立關聯關係並保證分配到同一個分片(使用父文件id做hash計算)
- 儘量少使用父子關係,僅父文件比較少的時候
4. 擴容設計
擴容思路
- 首先檢視是否有低效率的查詢可以優化
- 是否缺少足夠的記憶體
- 是否開啟了swap
- 已經建立好的索引,不可修改分片數,可通過重新索引,將舊資料遷移到新索引中
- 搜尋效能取決於最慢節點的響應時間,合理設定分片使之負載均衡
- 因為單索引和多索引沒有區別,可通過設定多索引以擴容
分片數量設定
- 基於現有的資料量和定期的增長量,預估資料總量
- 基於現有的硬體資訊,設定單個分片,0個副本,找到單個分片在當前硬體條件下能支援的最大文件數
- 用總數量/單個分片的最大數,大致可估算出分片數
基於時間的資料流場景優化
- 按時間切分索引
- 舊資料不會被改變,使用optimize api進行段合併。
- 大多數索引會有大概 50–150 個段,哪怕它們存有 TB 級別的數十億條文件。段數量過大表明合併出現了問題(比如,合併速度跟不上段的建立)
- 不過段合併消耗掉你節點上全部的I/O資源,從而有可能使叢集失去響應。 如果你想要對索引執行
optimize
,你需要先把索引移到一個安全的節點,再執行。- 為了不影響正常索引,段合併後臺限制磁碟讀寫速率為20MB/s,可根據實際情況調整,比如SSD盤,引數為indices.store.throttle.max_bytes_per_sec。甚至在沒有查詢時,設定為none,即沒有限制,合併完再改回去。
- 並且,對還在寫資料的索引進行優化(Optimize)操作將會是一個糟糕的想法, 因為優化操作將消耗節點上大量 I/O 並對現有索引造成衝擊
- 我們可以臨時移除副本分片,進行優化,然後再恢復副本分片
- 去除副本之前,可通過snapshot restore api備份資料
- 更舊的不會被使用的資料,關閉索引。關閉後除了磁碟,不會佔用其他資源。flush(清空事務日誌)->close(關閉索引)
- 資料歸檔:snapshot restore api將資料儲存到hdfs或其他地方
基於使用者的資料流場景
- 指定路由:保證同類資料會分發到同一分片。查詢時也傳入路由引數,確保只查詢特定的分片,多分片查詢帶來的效能損耗
- 使用別名,指定特定的名字對應特定的路由值和過濾器。以達到多個名稱共享一個索引的效果。看起來像多個索引一樣。
- 當某個分片資料量劇增到需要單獨建索引時,使用_alias操作:指定action的remove和add引數,實現平滑遷移。
九. 管理,監控
1. 重要的引數配置
- cluster.name
- node.name
- path.data
- path.logs
- path.plugins
- discovery.zen.minum_master_nodes: 最小主節點數,防止腦裂(多個主節點)
- discover.zen.ping.unicast.hosts: 叢集單播列表
- gateway.recover_after_nodes 至少多少個節點,叢集才可用
- gateway.expected_node 叢集期待有多少個節點
- gateway.recover_fater_time 等待多久才進行資料恢復
- logger.discovery 日誌級別
- index.search.slowlog.threshold.query.warn : "10s" 查詢慢與10s的輸出warn日誌
- index.search.slowlog.threshold.fetch.debug: "500ms" 查詢慢與500ms的輸出debug日誌
- index.indexing.slowlog.threshold.index.info: "5s 查詢慢與5s的輸出info日誌
- index.unassigned.node_left.delayed_timeout 修改延時分片時間
- cluster.routing.allocation.enable" : "none" 禁止分片分配
2. 不要修改的配置
- 不要更改垃圾回收器,預設使用CMS。不要更換為新一代的G1
- 執行緒數量,預設為cpu核數。IO操作是由Lucene執行緒完成,不是es。
3. 堆記憶體的配置
- 預設為1G,實際生產環境必須修改
- 保證Xms和Xmx一樣,防止執行時改變堆記憶體大小,這非常消耗資源
- 記憶體分片不要超過本機記憶體的一半。因為Lucene本身也會需要記憶體和快取。
- 如果不需要對分詞做聚合運算,可降低堆記憶體。堆記憶體越小,Elasticsearch(更快的 GC)和 Lucene(更多的記憶體用於快取)的效能越好。
- 記憶體不要超過32G。每個物件的指標都變長了,就會使用更多的 CPU 記憶體頻寬,也就是說你實際上失去了更多的記憶體。果你想保證其安全可靠,設定堆記憶體為 31 GB 是一個安全的選擇
- 如果記憶體很大,可以考慮給一個機器分配多個es例項,但總的堆記憶體還是不要超過一半。同時配置cluster.routing.allocation.same_shard.host: true。防止同一個分片(主副)在一個機器上
- 設定bootstrap.mlockall: true,鎖住記憶體,不讓發生記憶體swapping
4. 運維及優化
- 日誌檔案預設存放在安裝目錄下的logs檔案裡,"logger.discovery" : "DEBUG"可設定日誌級別
- 可以設定輸出慢查詢日誌
- 如果不需要實時準確,把index.refresh_interval改到30s,做大批量倒入時,把這個值設為-1,倒入完畢後重新設定回來
- 大批量倒入時,index.number_of_replicas設為0,關閉副本,提高效率
- 儘量使用es自動生成的id,避免版本查詢影響效率。如果使用自己的id,使用壓縮效能良好的,避免使用太過隨機的id
- 延遲分片:防止節點掉線然後又重啟導致的大量資料遷移問題。因為掉線的節點上的資料可能會因為失效而全部被刪除,然後重新複製。引數為index.unassigned.node_left.delayed_timeout
5. 滾動重啟
- 保證不停叢集功能的情況下逐一對每個節點進行升級或維護
- 先停止索引新的資料
- 禁止分片分配。cluster.routing.allocation.enable" : "none"
- 關閉單個節點,並執行升級維護
- 啟動節點,並等待加入叢集
- 重啟分片分配。cluster.routing.allocation.enable" : "all"
- 對其他節點重複以上步驟
- 恢復索引更新資料