[译]为什么ElasticSearch应用开发者需要了解cluster state

标签: elasticsearch | 发表时间:2017-03-24 01:07 | 作者:牧曦之晨
出处:https://segmentfault.com/blogs

在前面的文章( ES vs Solr)中我们提到, ES构建了Loggly的很多核心功能. 在把这项通用搜索技术用于我们的日志管理系统, 并为超过5000多客户提供准实时服务的过程中, 我们在技术上成长颇多. 按照我们对开源社区的尊重, 在此希望能把我们所学到的知识回馈到社区.

本文将探讨对ES扩展过程中的性能有深远影响的关键概念: cluster state.

什么是cluster state

ES的一个突出优点是其无模型规则约束. 起初, 你可以把一个包含任意字段数目的文档添加到索引中, 而并不需要提前在ES中定义这些字段的类型. 能把这些字段添加到索引并随后进行搜索是件让人兴奋的事情. 但这些字段的名称, 类型以及它们被添加到的索引信息则会自动添加到ES的 cluster state信息中(假设你使用了默认的 动态mapping设置. 当然像ES的其他配置一样, 你可以调整或禁用该行为).

当然,这里还有些秘密: 如果你向一个已存在的字段(例如integer)中试图添加另外一种类型(例如string)的字段值时, ES将会失败. 同一个索引中的相同字段不能同时具有两种不同类型. 这称为 mapping冲突. ES的处理取决于涉及的具体类型. 例如:

  • 如果向一个字符串类型中添加整数值, 则会进行强制类型转换

  • 如果向一个整数类型中添加字符串值, 则会遇到异常, ES拒绝接收该文档.

所以关注下你的ES响应,尤其在使用bulk做批量索引时.

cluster state是你的重要参考

像其他倒排索引一样, 当你搜索数据时, ES需要知道这些数据的元信息及其存储位置. 当节点接收到查询请求, 首先要做的就是你要查询的对象在哪些分片上, 然后判断这个索引上有哪些字段以及它们的类型.(你不能在一个字符串类型的字段上进行数字范围查询). 而这些信息都记录在cluster state之中.

顾名思义, cluster state是全局性信息, 包含了整个群集中所有分片的元信息(规则, 位置, 大小等信息), 并保持每个每节的信息同步.

在一个包含众多节点的集群中, ES是如何做到信息同步的呢? 原来ES的cluster state信息是由master节点维护的, 当它收到data节点的状态更新变化后, 就把这些信息依次广播到其他节点, 仅此而已.

假如你的cluster state每2½分钟更新300磅

请记住: 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示例

下面是一个具有两个节点的集群, 其中包含了只有一条文档的一个索引的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" : [ ]
}

相关 [elasticsearch 应用 开发] 推荐:

[译]为什么ElasticSearch应用开发者需要了解cluster state

- - SegmentFault 最新的文章
在前面的文章( ES vs Solr)中我们提到, ES构建了Loggly的很多核心功能. 在把这项通用搜索技术用于我们的日志管理系统, 并为超过5000多客户提供准实时服务的过程中, 我们在技术上成长颇多. 按照我们对开源社区的尊重, 在此希望能把我们所学到的知识回馈到社区. 本文将探讨对ES扩展过程中的性能有深远影响的关键概念: cluster state..

从原理到应用,Elasticsearch详解

- - SegmentFault 最新的文章
Elasticsearch(简称ES)是一个分布式、可扩展、实时的搜索与数据分析引擎. ES不仅仅只是全文搜索,还支持结构化搜索、数据分析、复杂的语言处理、地理位置和对象间关联关系等. ES的底层依赖Lucene,Lucene可以说是当下最先进、高性能、全功能的搜索引擎库. 但是Lucene仅仅只是一个库.

Elasticsearch开发人员最佳实战指南

- -
几个月以来,我一直在记录自己开发Elasticsearch应用程序的最佳实践. 本文梳理的内容试图传达Java的某些思想,我相信其同样适用于其他编程语言. 我尝试尽量避免重复教程和Elasticsearch官方文档中已经介绍的内容. 本文梳理的内容都是从线上实践问题和个人总结的经验汇总得来的. 文章从以下几个维度展开讲解:.

Elasticsearch 开发实战常用命令清单

- -
Elasticsearch 具有一组丰富的易于理解的 REST API,这些 API  均可如下几种方式通过 HTTP 调用进行访问. 开发实战环节,我推荐使用:kibana Dev-tools. 本文结合多年实战经验和网络资源,梳理出开发环节最重要的命令清单,希望对你有帮助. 1、Elasticsearch REST URL 拆解.

Elasticsearch深度应用(下) - 女友在高考 - 博客园

- -
query then fetch(默认搜索方式). 找到所有匹配的文档,并使用本地的Term/Document Frequery信息进行打分. 返回关于结果的元数据到请求节点. 注意,实际文档还没有发送,只是分数. 来自所有shard的分数合并起来,并在请求节点上进行排序,文档被按照查询要去进行选择.

Elasticsearch深度应用(上) - 女友在高考 - 博客园

- -
众所周知,Elasticsearch存储的基本单元是shard,ES中一个index可能分为多个shard,事实上每个shard都是一个Lucece的Index,并且每个Lucece Index由多个Segment组成,每个Segment事实上是一些倒排索引的集合,每次创建一个新的Document,都会归属一个新的Segment,而不会去修改原来的Segment.

[译] 使用 Docker 和 Elasticsearch 搭建全文本搜索引擎应用

- - IT瘾-dev
作者简介:Patrick Triest是一位全栈工程师,数据爱好者,持续学习者,洁癖编程者. 作者github地址为 https://github.com/triestpa,本文地址参见 https://blog.patricktriest.com. 本文源码可以在GitHub repository 中找到 - https://github.com/triestpa/guttenberg-search.

Elasticsearch 在各大互联网公司大量真实的应用案例

- -
国内现在有大量的公司都在使用 Elasticsearch,包括携程、滴滴、今日头条、饿了么、360安全、小米、vivo等诸多知名公司. 除了搜索之外,结合Kibana、Logstash、Beats,Elastic Stack还被广泛运用在大数据近实时分析领域,包括日志分析、指标监控、信息安全等多个领域.

[译]elasticsearch mapping

- - an74520的专栏
es的mapping设置很关键,mapping设置不到位可能导致索引重建. 请看下面各个类型介绍^_^. 每一个JSON字段可以被映射到一个特定的核心类型. JSON本身已经为我们提供了一些输入,支持 string,  integer/ long,  float/ double,  boolean, and  null..

Elasticsearch as Database - taowen - SegmentFault

- -
【北京上地】滴滴出行基础平台部招聘 Elasticsearch 与 Mysql binlog databus 开发工程师. 内推简历投递给: [email protected]. 推销Elasticsearch. 时间序列数据库的秘密(1)—— 介绍. 时间序列数据库的秘密(2)——索引.