原文连接: 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" : [ ] }