原文連接: https://www.loggly.com/blog/p...html
在前面的文章(ES vs Solr)中咱們提到, ES構建了Loggly的不少核心功能. 在把這項通用搜索技術用於咱們的日誌管理系統, 併爲超過5000多客戶提供準實時服務的過程當中, 咱們在技術上成長頗多. 按照咱們對開源社區的尊重, 在此但願能把咱們所學到的知識回饋到社區. node
本文將探討對ES擴展過程當中的性能有深遠影響的關鍵概念: cluster state
.segmentfault
ES的一個突出優勢是其無模型規則約束. 起初, 你能夠把一個包含任意字段數目的文檔添加到索引中, 而並不須要提早在ES中定義這些字段的類型. 能把這些字段添加到索引並隨後進行搜索是件讓人興奮的事情. 但這些字段的名稱, 類型以及它們被添加到的索引信息則會自動添加到ES的cluster state
信息中(假設你使用了默認的動態mapping設置. 固然像ES的其餘配置同樣, 你能夠調整或禁用該行爲).app
固然,這裏還有些祕密: 若是你向一個已存在的字段(例如integer)中試圖添加另一種類型(例如string)的字段值時, ES將會失敗. 同一個索引中的相同字段不能同時具備兩種不一樣類型. 這稱爲mapping衝突. ES的處理取決於涉及的具體類型. 例如:elasticsearch
若是向一個字符串類型中添加整數值, 則會進行強制類型轉換ide
若是向一個整數類型中添加字符串值, 則會遇到異常, ES拒絕接收該文檔.性能
因此關注下你的ES響應,尤爲在使用bulk作批量索引時.優化
像其餘倒排索引同樣, 當你搜索數據時, ES須要知道這些數據的元信息及其存儲位置. 當節點接收到查詢請求, 首先要作的就是你要查詢的對象在哪些分片上, 而後判斷這個索引上有哪些字段以及它們的類型.(你不能在一個字符串類型的字段上進行數字範圍查詢). 而這些信息都記錄在cluster state之中.ui
顧名思義, cluster state是全局性信息, 包含了整個羣集中全部分片的元信息(規則, 位置, 大小等信息), 並保持每一個每節的信息同步.日誌
在一個包含衆多節點的集羣中, ES是如何作到信息同步的呢? 原來ES的cluster state信息是由master節點維護的, 當它收到data節點的狀態更新變化後, 就把這些信息依次廣播到其餘節點, 僅此而已.
請記住: cluster state是你的羣集中每一個節點上的每一個索引包含的每一個分片的全部字段信息. 若是你有大量的字段, 例如把ES做爲大量易變且無固定規則文檔的存儲, 那麼cluster state將會變得龐大. 在Loggly服務中偏偏如此. 由於客戶發送給咱們的文檔格式隨意, 包含任意數據的惟一字段, 而且數量跨度較大. 咱們每秒處理數十萬次請求, 因此Loggly的cluster state可達數百兆大小.
也許警告聲已在你腦海中響起: "你是說當有任何變化時, ES會廣播數百兆的數據到不一樣節點?". 也許事實並不像你想像的那麼糟糕. 在cluster state管理方面, ES已經作了幾個優化:
從ES2.0以來, 只有變化的cluster state信息纔會被廣播. 相比之前的版本, 這帶來了巨大的性能提高.
在ES節點前傳遞信息以前, ES對cluster state作了效果顯明的壓縮.
ES在合併cluster state更新以及批量處理上至關明智, 特別是最近的ES版本中.(在後面的文章Pending Tasks會介紹前期版本中未作這些優化時的內部處理)
即使如此, 常常關注你的cluster state也是頗有必要的. 另外, 咱們發如今規模化運行ES集羣早期, 索引大量數據以前要作的第一件事, 就是爲ES的cluster state數據量設置上限, 以免超出ES處理能力而致使集羣故障. 關於cluster state更嚴重的問題--以及在Loggly, 咱們是如何解決cluster state問題的--將會在之後的文章出介紹, 但願能對你有所幫助.
下面是一個具備兩個節點的集羣, 其中包含了只有一條文檔的一個索引的cluster state信息. 固然這與咱們真實場景中的數據有很大區別, 由於在咱們的集羣中有不少機器和大量的索引節點以及超出你想象的mapping數量. 但這個例子已經足夠讓你瞭解cluster state所包含的信息了.
{ "cluster_name" : "elasticsearch", "version" : 11, "master_node" : "-mq1SRuuQoeEq-3S8SdHqw", "blocks" : { }, "nodes" : { "sIh5gQcFThCcz3SO6txvvQ" : { "name" : "Max", "transport_address" : "inet[/162.245.23.194:9301]", "attributes" : { } }, "-mq1SRuuQoeEq-3S8SdHqw" : { "name" : "Llyron", "transport_address" : "inet[/162.245.23.194:9300]", "attributes" : { } } }, "metadata" : { "templates" : { }, "indices" : { "blog" : { "state" : "open", "settings" : { "index" : { "uuid" : "UQMz5vbXSBqFU_8U3u4gYQ", "number_of_replicas" : "1", "number_of_shards" : "5", "version" : { "created" : "1030099" } } }, "mappings" : { "user" : { "properties" : { "name" : { "type" : "string" } } } }, "aliases" : [ ] } } }, "routing_table" : { "indices" : { "blog" : { "shards" : { "4" : [ { "state" : "STARTED", "primary" : true, "node" : "sIh5gQcFThCcz3SO6txvvQ", "relocating_node" : null, "shard" : 4, "index" : "blog" }, { "state" : "STARTED", "primary" : false, "node" : "-mq1SRuuQoeEq-3S8SdHqw", "relocating_node" : null, "shard" : 4, "index" : "blog" } ], "0" : [ { "state" : "STARTED", "primary" : true, "node" : "sIh5gQcFThCcz3SO6txvvQ", "relocating_node" : null, "shard" : 0, "index" : "blog" }, { "state" : "STARTED", "primary" : false, "node" : "-mq1SRuuQoeEq-3S8SdHqw", "relocating_node" : null, "shard" : 0, "index" : "blog" } ], "3" : [ { "state" : "STARTED", "primary" : false, "node" : "sIh5gQcFThCcz3SO6txvvQ", "relocating_node" : null, "shard" : 3, "index" : "blog" }, { "state" : "STARTED", "primary" : true, "node" : "-mq1SRuuQoeEq-3S8SdHqw", "relocating_node" : null, "shard" : 3, "index" : "blog" } ], "1" : [ { "state" : "STARTED", "primary" : false, "node" : "sIh5gQcFThCcz3SO6txvvQ", "relocating_node" : null, "shard" : 1, "index" : "blog" }, { "state" : "STARTED", "primary" : true, "node" : "-mq1SRuuQoeEq-3S8SdHqw", "relocating_node" : null, "shard" : 1, "index" : "blog" } ], "2" : [ { "state" : "STARTED", "primary" : true, "node" : "sIh5gQcFThCcz3SO6txvvQ", "relocating_node" : null, "shard" : 2, "index" : "blog" }, { "state" : "STARTED", "primary" : false, "node" : "-mq1SRuuQoeEq-3S8SdHqw", "relocating_node" : null, "shard" : 2, "index" : "blog" } ] } } } }, "routing_nodes" : { "unassigned" : [ ], "nodes" : { "sIh5gQcFThCcz3SO6txvvQ" : [ { "state" : "STARTED", "primary" : true, "node" : "sIh5gQcFThCcz3SO6txvvQ", "relocating_node" : null, "shard" : 4, "index" : "blog" }, { "state" : "STARTED", "primary" : true, "node" : "sIh5gQcFThCcz3SO6txvvQ", "relocating_node" : null, "shard" : 0, "index" : "blog" }, { "state" : "STARTED", "primary" : false, "node" : "sIh5gQcFThCcz3SO6txvvQ", "relocating_node" : null, "shard" : 3, "index" : "blog" }, { "state" : "STARTED", "primary" : false, "node" : "sIh5gQcFThCcz3SO6txvvQ", "relocating_node" : null, "shard" : 1, "index" : "blog" }, { "state" : "STARTED", "primary" : true, "node" : "sIh5gQcFThCcz3SO6txvvQ", "relocating_node" : null, "shard" : 2, "index" : "blog" } ], "-mq1SRuuQoeEq-3S8SdHqw" : [ { "state" : "STARTED", "primary" : false, "node" : "-mq1SRuuQoeEq-3S8SdHqw", "relocating_node" : null, "shard" : 4, "index" : "blog" }, { "state" : "STARTED", "primary" : false, "node" : "-mq1SRuuQoeEq-3S8SdHqw", "relocating_node" : null, "shard" : 0, "index" : "blog" }, { "state" : "STARTED", "primary" : true, "node" : "-mq1SRuuQoeEq-3S8SdHqw", "relocating_node" : null, "shard" : 3, "index" : "blog" }, { "state" : "STARTED", "primary" : true, "node" : "-mq1SRuuQoeEq-3S8SdHqw", "relocating_node" : null, "shard" : 1, "index" : "blog" }, { "state" : "STARTED", "primary" : false, "node" : "-mq1SRuuQoeEq-3S8SdHqw", "relocating_node" : null, "shard" : 2, "index" : "blog" } ] } }, "allocations" : [ ] }