在上一章中我們對es-search的基本架構及核心概念有了一個基本的認識,這裡我們開始搭建一個叢集。
目錄
1. 叢集中的節點角色
Ingest Node
如何配置設定?
如何避免腦裂問題?
2. 分片及副本
3. 叢集健康及監控
3.1 cat API
3.2 Cluster API
3.2.1 _cluster
3.2.2 _nodes
3.2.3 _remote
3.2.4 _tasks
3.3 X-Pack
4. 擴容
5. 故障轉移
6. Thread Pool
1. 叢集中的節點角色
每當啟動ElasticSearch執行個體時,都會啟動一個節點。連接配接的節點集合稱為叢集。如果您運作的是單個ElasticSearch節點,那麼您擁有一個由一個節點組成的叢集。
叢集中的每個節點預設都可以處理HTTP 和Transport流量。Transport專門用于節點和 Java
TransportClient
之間的通信;HTTP層僅由外部REST用戶端使用。
Master Node | 将node.master設定為true的節點。使其有資格被選為控制叢集的主節點。 |
Data Node | 将node.data設定為true的節點。資料節點儲存資料并執行與資料相關的操作,如CRUD、搜尋和聚合。 |
Ingest node | 将node.intrupt設定為true的節點。攝取節點能夠将 ingest pipeline應用于文檔,以便在索引前轉換和豐富文檔。對于大吞吐下,使用專用的攝取節點并将主節點和資料節點标記為 node.ingest: false 是有意義的。 |
Tribe node | 部落節點,通過 tribe.* 配置,是一種特殊類型的協調節點,可以連接配接到多個叢集,并在所有連接配接的叢集上執行搜尋和其他操作。 |
預設情況下,節點是一個Master節點和一個Data節點,并且它可以通過攝取管道預處理文檔。這對于小型叢集非常友善,但是随着叢集的增長,考慮将專用的Master節點與專用的Data節點分離變得非常重要。Indexing 和 searching 資料是CPU、記憶體和I/O密集型工作,這會給節點的資源帶來壓力。為了確定主節點穩定且不受壓力,在更大的叢集中,最好在專用的符合主節點條件的節點和專用的資料節點之間劃分角色。
盡管主節點也可以充當協調節點,并将搜尋和索引請求從用戶端路由到資料節點,但最好不要為此目的使用專用的主節點。主合格節點的工作越少,對于叢集的穩定性就越重要。
node.master: true //預設是true
node.data: false //預設是true(啟用node.data role)
node.ingest: false //預設是true(啟用node.ingest role)
search.remote.connect: false //預設是true(啟用cross-cluster search)
當叢集的節點數量較大時(比如超過30個節點),叢集的管理工作會變得複雜很多。此時應該建立專有master節點,這些節點隻負責叢集管理,不存儲資料,不承擔資料讀寫壓力;其他節點則僅負責資料讀寫,不負責叢集管理的工作。這樣把叢集管理和資料的寫入/查詢分離,互不影響,防止因讀寫壓力過大造成叢集整體不穩定。 将專有master節點和資料節點的分離,需要修改ES的配置檔案,然後滾動重新開機各個節點。
當index/shard數量過多(在一個20個節點的叢集裡,建立了4w+個shard),導緻建立一個index需要60s+才能完成,可以考慮從以下幾方面改進:
- 降低資料量較小的index的shard數量
- 把一些有關聯的index合并成一個index
- 資料按某個次元做拆分,寫入多個叢集
Ingest Node
ingest node是5.0新增的特性,它用來在真正對文檔進行索引之前做預處理。所有的節點都是預設支援ingest的,任何節點都可以處理ingest請求,也可以建立一個專門的Ingest nodes。它産生的價值在于,對文檔進行索引之前對檔案進行預處理,通過定義包含了多個process的pipeline來實作。每個process(ES内置的資料處理器)實作了對文檔的某種轉換,如移除某個字段,重命名某個字段等。
Ingest APIs |
Put Pipeline API,新增或更新pipeline |
Get Pipeline API, 擷取pipeline |
Delete Pipeline API,删除pipeline |
Simulate Pipeline API,模拟對pipeline的調用 |
Processors,内置的非常多 |
Convert Processor,将現有字段的值轉換為其他類型,例如将字元串轉換為整數。如果字段值是數組,則将轉換所有成員。 |
Date Processor,分析字段中的日期,然後使用日期或時間戳作為文檔的時間戳。預設情況下,日期處理器将解析的日期添加為一個名為@timestamp的新字段 |
Remove Processor,删除現有字段。如果一個字段不存在,将引發異常 |
Rename Processor,重命名現有字段。如果字段不存在或新名稱已被使用,将引發異常 |
Grok Processor,從文檔中的單個文本字段中提取結構化字段。它非常适合于syslog日志、apache和其他Web伺服器日志、mysql日志,而且一般來說,任何日志格式都是為人類而非計算機消耗編寫的。相信用過Logstash的同學一定不會陌生。 {//源文檔 "message": "55.3.244.1 GET /index.html 15824 0.043" } {//管道定義 "description" : "...", "processors": [ { "grok": { "field": "message", "patterns": ["%{IP:client} %{WORD:method} %{URIPATHPARAM:request} %{NUMBER:bytes} %{NUMBER:duration}"] } } ] } {//處理後的文檔 "message": "55.3.244.1 GET /index.html 15824 0.043", "client": "55.3.244.1", "method": "GET", "request": "/index.html", "bytes": 15824, "duration": "0.043" } |
如何配置設定?
- 小規模叢集(資料量級幾千萬到數十億級别),不需嚴格區分
- 中大規模叢集(十個以上節點),應考慮單獨的角色充當。特别并發查詢量大,查詢的合并量大,可以增加獨立的協調節點。角色分開的好處是分工分開,不互影響。如不會因協調角色負載過高而影響資料節點的能力。
如何避免腦裂問題?
一個叢集中隻有一個A主節點,A主節點因為需要處理的東西太多或者網絡過于繁忙,進而導緻其他從節點ping不通A主節點,這樣其他從節點就會認為A主節點不可用了,就會重新選出一個新的主節點B。過了一會A主節點恢複正常了,這樣就出現了兩個主節點,導緻一部分資料來源于A主節點,另外一部分資料來源于B主節點,出現資料不一緻問題,這就是腦裂。
盡量避免腦裂,需要添加最小數量的主節點配置:discovery.zen.minimum_master_nodes: (有master資格節點數/2) + 1,它控制的是,選舉主節點時需要看到最少多少個具有master資格的活節點,才能進行選舉。官方的推薦值是(N/2)+1,其中N是具有master資格的節點的數量。一般Master 和 dataNode 角色分開,配置奇數個master,如3 。
discovery.zen.ping.multicast.enabled: false | 關閉多點傳播發現機制,預設是關閉的 |
discovery.zen.ping.unicast.hosts: ["master1", "master2", "master3"] | 配置單點傳播發現的主節點ip位址,其他從節點要加入進來,就得去詢問單點傳播發現機制裡面配置的主節點我要加入到叢集裡面了,主節點同意以後才能加入,然後主節點再通知叢集中的其他節點有新節點加入 |
discovery.zen.ping_timeout: 30(預設值是3秒) | 其他節點ping主節點多久時間沒有響應就認為主節點不可用了 |
discovery.zen.minimum_master_nodes: 2 | 選舉主節點時需要看到最少多少個具有master資格的活節點,才能進行選舉 |
2. 分片及副本
索引在被建立時預設情況下會被配置設定5個主分片(每個分片一個副本),更多用法。
分片(shard):一個ES的index由多個shard組成,每個shard承載index的一部分資料。分片數指定後不可變,除非重索引。每個分片本質上就是一個Lucene索引, 是以會消耗相應的檔案句柄, 記憶體和CPU資源。
副本(replica):index也可以設定副本數(numberofreplicas),也就是同一個shard有多少個備份。對于查詢壓力較大的index,可以考慮提高副本數(numberofreplicas),通過多個副本均攤查詢壓力。副本分片數可以随時修改。
shard數量(numberofshards)設定過多或過低都會引發一些問題:shard數量過多,則批量寫入/查詢請求被分割為過多的子寫入/查詢,導緻該index的寫入、查詢拒絕率上升;對于資料量較大的inex,當其shard數量過小時,無法充分利用節點資源,造成機器資源使用率不高或不均衡,影響寫入/查詢的效率。
多少分片才算合理?
ElasticSearch推薦的最大JVM堆空間是30~32G, 是以把你的分片最大容量限制為30GB, 然後再對分片數量做合理估算。例如, 你認為你的資料能達到200GB, 推薦你最多配置設定7到8個分片。在開始階段, 一個好的方案是根據你的節點數量按照1.5~3倍的原則來建立分片。
對于基于日期的索引需求, 并且對索引資料的搜尋場景非常少。也許這些索引量将達到成百上千, 但每個索引的資料量隻有1GB甚至更小. 對于這種類似場景, 建議隻需要為索引配置設定1個分片。
應該設定幾個副本?
副本的用途是備份資料保證高可用資料不丢失,高并發的時候參與資料查詢。一般一個分片有1-2個副本即可保證高可用。副本多浪費存儲空間、占用資源、影響性能。
為保證高可用,副本數設定為2即可。要求叢集至少要有3個節點,來分開存放主分片、副本。如發現并發量大時,查詢性能會下降,可增加副本數,來提升并發查詢能力。
注意:新增副本時主節點會自動協調,然後拷貝資料到新增的副本節點
有推薦設定?
- 對于資料量較小(100GB以下)的index,往往寫入壓力查詢壓力相對較低,一般設定3~5個shard,numberofreplicas設定為1即可(也就是一主一從,共兩副本)
- 對于資料量較大(100GB以上)的index:
- 一般把單個shard的資料量控制在(20GB~50GB)
- 讓index壓力分攤至多個節點:可通過index.routing.allocation.totalshardsper_node參數,強制限定一個節點上該index的shard數量,讓shard盡量配置設定到不同節點上
- 綜合考慮整個index的shard數量,如果shard數量(不包括副本)超過50個,就很可能引發拒絕率上升的問題,此時可考慮把該index拆分為多個獨立的index,分攤資料量,同時配合routing使用,降低每個查詢需要通路的shard數量。
3. 叢集健康及監控
為了簡單,可以搭建一個空叢集,進入elasticsearch-5.5.2\bin,啟動elasticsearch.bat。
3.1 cat API
JSON非常适合計算機。所有cat指令都接受一個查詢字元串參數help,以檢視它們提供的所有頭和資訊,并且/_cat指令單獨列出了所有可用的指令。
_cat
基本參數
verbose: 顯示列名, 請求參數為v
示例: curl http://localhost:9200/_cat/health?v
help: 顯示目前指令的各列含義, 請求參數為help. 某些指令部分列預設不顯示,可通過help該指令可顯示的所有列
示例: curl http://localhost:9200/_cat/master?help
bytes: 數值列還原為原始值. 如diskSize, 預設轉為以kb/mb/gb表示, 打開後還原為原始值
示例: curl http://localhost:9200/_cat/indices?bytes=b
header: 顯示指定列的資訊, 請求參數為h
示例: curl http://localhost:9200/_cat/indices?h=i,tm(顯示叢集各索引的記憶體使用)
/_cat/allocation | 檢視單節點的shard配置設定整體情況 |
/_cat/shards /_cat/shards/{index} | 檢視各shard的詳細情況,包括shard的分布, 目前狀态, doc數量, 磁盤占用情況, shard的通路情況, |
/_cat/master | 檢視叢集中的master節點 |
/_cat/nodes | 檢視叢集各個節點的目前狀态, 包括節點的實體參數(包括os/jdk版本, uptime, 目前mem/disk/fd使用情況等), 請求通路情況(如search/index成功和失敗的次數)等詳細資訊 |
/_cat/indices /_cat/indices/{index} | 檢視叢集中所有index的詳細資訊,包括index狀态,shard個數(primary/replica),doc個數等 |
/_cat/segments /_cat/segments/{index} | 檢視各index的segment詳細資訊,包括segment名, 所屬shard, 記憶體/磁盤占用大小, 是否刷盤, 是否merge為compound檔案等 |
/_cat/count /_cat/count/{index} | 檢視目前叢集的doc數量 |
/_cat/recovery /_cat/recovery/{index} | 檢視叢集内每個shard的recovery過程. 調整replica,恢複snapshot或者節點啟動都會觸發shard的recover. |
/_cat/health | 檢視叢集目前狀态, 包括data節點個數,primary shard個數等基本資訊,status字段訓示着目前叢集在總體上是否工作正常。它的三種顔色含義如下: "unassigned_shards": 3,表示沒有被配置設定到任何節點的副本數(同一個節點上既儲存原始資料又儲存副本是沒有意義的,因為一旦失去了,我們也将丢失該節點上的所有副本資料)
|
/_cat/pending_tasks | 檢視目前叢集的pending task |
/_cat/aliases /_cat/aliases/{alias} | 所有alias資訊,包括alias對應的index, 路由配置等 |
/_cat/thread_pool | 檢視叢集各節點内部不同類型的threadpool的統計資訊, 覆寫了es對外所有請求的threadpool(活躍線程數和任務隊列大小以及拒絕數量) |
/_cat/plugins | 檢視叢集各個節點上的plugin資訊 |
/_cat/fielddata /_cat/fielddata/{fields} | 檢視叢集fielddata記憶體占用情況 |
3.2 Cluster API
大多數叢集級API允許指定要在哪個節點上執行(例如,擷取節點的節點狀态)。節點可以使用其内部節點ID、節點名稱、位址、自定義屬性或僅接收請求的本地節點在API中辨別。
3.2.1 _cluster
Cluster Health | 它允許獲得叢集運作狀況的非常簡單的狀态 GET /_cluster/health GET /_cluster/health?wait_for_status=yellow&timeout=50s GET /_cluster/health/twitter?level=shards |
Cluster State | 它允許擷取整個叢集的全面狀态資訊,metrics包含version、master_node、nodes、routing_table、metadata、blocks。 GET /_cluster/state/{metrics}/{indices} GET /_cluster/state GET /_cluster/state/metadata,routing_table/foo,bar GET /_cluster/state/blocks |
Cluster Stats | 它允許從叢集範圍的角度檢索統計資訊。API傳回基本索引度量(shard數、存儲大小、記憶體使用情況)和有關構成叢集的目前節點的資訊(number、roles、作業系統、JVM版本、記憶體使用情況、CPU和已安裝插件) GET /_cluster/stats?human&pretty |
Pending cluster tasks | 它傳回尚未執行的任何叢集級别更改(例如,建立索引、更新映射、配置設定或失敗碎片)的清單。 GET /_cluster/pending_tasks |
Cluster Reroute | 它允許手動更改叢集中單個分片的配置設定。例如,可以顯式地将分片從一個節點移動到另一個節點,可以取消配置設定,并且可以顯式地将未配置設定的分片配置設定給特定的節點 |
Cluster Update Settings | 允許更新群集範圍内的特定設定。更新的設定可以是持久的(在重新啟動時應用),也可以是暫時的(在是以的群集重新啟動後将失效) PUT /_cluster/settings { "persistent" : { "indices.recovery.max_bytes_per_sec" : "50mb" } } |
Cluster Allocation Explain API | 它目的是為叢集中的shard配置設定提供解釋。對于未配置設定的分片,explain api提供了未配置設定分片的原因的解釋。對于配置設定的分片,explain api提供了一個解釋,解釋為什麼分片保留在其目前節點上,并且沒有移動或重新平衡到另一個節點。當試圖診斷分片未配置設定的原因,或者當您可能希望分片繼續保留在目前節點上時,此API非常有用。 GET /_cluster/allocation/explain { "index": "myindex", "shard": 0, "primary": true } |
3.2.2 _nodes
Nodes Info | 它允許檢索一個或多個(或全部)群集節點資訊 GET /_nodes GET /_nodes/nodeId1,nodeId2 GET /_nodes/plugins GET /_nodes/ingest |
Nodes Stats | 它允許檢索一個或多個(或全部)群集節點統計資訊 GET /_nodes/stats GET /_nodes/nodeId1,nodeId2/stats GET /_nodes/stats/indices GET /_nodes/stats/os,process GET /_nodes/10.0.0.1/stats/process GET /_nodes/stats/indices/fielddata?fields=field1,field2 GET /_nodes/stats?groups=_all GET /_nodes/stats/indices?groups=foo,bar |
Nodes Feature Usage | 它允許檢索有關每個節點功能使用情況的資訊 GET _nodes/usage GET _nodes/nodeId1,nodeId2/usage |
Nodes hot_threads | 允許擷取群集中每個節點上目前熱線程的API GET /_nodes/hot_threads GET /_nodes/{nodesIds}/hot_threads |
3.2.3 _remote
Remote Cluster Info允許檢索所有配置的遠端叢集資訊。此指令傳回由配置的遠端叢集别名鍵控的連接配接和端點資訊。
GET /_remote/info
3.2.4 _tasks
Task Management API 允許檢索有關目前在群集中一個或多個節點上執行的任務的資訊。這個API是新增的,應該仍然被視為beta特性。API可能會以不向後相容的方式更改。
GET _tasks
GET _tasks?nodes=nodeId1,nodeId2
GET _tasks?nodes=nodeId1,nodeId2&actions=cluster:*
3.3 X-Pack
ElasticSearch是X-pack監控的核心。在所有情況下,x-pack監視文檔都隻是普通的JSON文檔,它是通過在某個輪詢間隔(預設為10秒)監視每個彈性堆棧元件而建構的,然後将這些文檔索引到監視叢集中。考慮到x-pack是收費的,這裡就不展開講。
4. 擴容
水準擴容,添加并啟動新節點即可,擴容允許每個節點上存在一個分片。上面講過也可以通過增加副本來擴容。
5. 故障轉移
cluster.name:隻要它和第一個節點有同樣的 cluster.name 配置,它就會自動發現叢集并加入到其中。但是在不同機器上啟動節點的時候,為了加入到同一叢集,你需要配置一個可連接配接到的單點傳播主機清單。 詳細資訊請檢視最好使用單點傳播代替多點傳播。當第二個節點加入到叢集後,3個副本分片将會配置設定到這個節點上,每個主分片對應一個副本分片(2個節點中任何一個節點出現問題時,資料都完好無損),cluster-health中status值為green,表示都在正常運作。
比如我們關閉主節點,意味着失去主分片1和2,此時叢集狀态red。而Node 2和Node 3上對應的副本分片提升為主分片,此時叢集的狀态将變為為yellow,當缺失的副本分片配置設定完成(還是9個)叢集的狀态會變為green。
6. Thread Pool
一個節點包含多個線程池,以改進如何在一個節點中管理線程記憶體消耗。其中許多池還具有與其關聯的隊列,這些隊列允許挂起的請求被保留而不是丢棄。
generic | 對于一般操作(例如背景節點發現)。線程池類型是scaling |
index | 用于index/delete操作。線程池類型固定為可用處理器的大小,隊列大小為200。此池的最大大小為available_processors+1。 |
search | 用于count/search/suggest操作。線程池類型是fixed_auto_queue_size,大小為int(available_processors*3)/2)+1,初始隊列_大小為1000。 |
get | 用于get操作。線程池類型固定為available_processors,隊列大小為1000。 |
bulk | 用于bulk操作。線程池類型固定為available_processors,隊列大小為200。此池的最大大小為available_processors+1。 |
snapshot | 用于snapshot/restore操作。線程池類型是 ,保持活動狀态為5m,最大值為min(5,available_processors/2)。 |
warmer | 用于segment warm-up(段預熱)操作。線程池類型是 ,保持活動狀态為5m,最大值為min(5,available_processors/2)。 |
refresh | 用于refresh操作。線程池類型是 ,保持活動狀态為5m,最大值為min(10,available_processors/2)。 |
listener | 主要用于當偵聽器線程設定為true時Java用戶端執行操作。線程池類型是 最大值min(10,available_processors/2)。 |
thread_pool:
index:
size: 30
queue_size: 1000
總結,叢集主要是面向運維人員,但開發者也有有一定的了解。下一篇将對索引及Mapping管理展開介紹,非常值得深入。