FAQ
1、为什么一个分片只能存放 Integer.MAX_VALUE – 128 = 2,147,483,519 个 docs?
索引
一般意义上的索引是一种基于文档(数据)生成、建立的,用于快速定位指定文档的工具。
而 ElasticSearch 对索引的定义有所不同,ElasticSearch 中的索引对应 MySQL 中的 Database ,也就说 ElasticSearch 中的索引更像是一种数据存储集合,即用于存储文档。
ElasticSearch 中的数据根据业务以索引为单位进行划分,Type(类型) 就像 MySQL 中的 Table 一样,用于区分同一业务中不同的数据集合,如下图:
当然上图并不是指 ElasticSearch 中就真的这么存储数据,而是大概的表现方式。
不过在 6.x 版本后,就废弃了 Type ,因为设计者发现 ElasticSearch 这种与关系型数据类比的设计方式有缺陷。在关系型数据库中,每个数据表都是相互独立的,即在不同表中相同的数据域是互不关联的。而 ElasticSearch 底层所用的 Lucene 并没有关系型数据中的这种特性,在 ElasticSearch 同一个索引中,不同映射类型但是名称相同的数据域在 Lucene 中是同一个数据域,即作为同一类数据存放在一起。
ElasticSearch 6.x 版本废弃掉 Type 后,建议的是每个类型(业务)的数据单独放在一个索引中,这样其实回归到一般意义上的索引定义,索引定位文档。如下图:
上图也是一种大概的表现方式,不代表 ElasticSearch 以这种方式处理文档。
P.S.:如果 ElasticSearch 还是使用 5.x 或以下版本,建议每个索引只设置一个类型,做到一个索引存储一种数据。
分片
单个节点由于物理机硬件限制,存储的文档是有限的,如果一个索引包含海量文档,则不能在单个节点存储。ES 提供分片机制,同一个索引可以存储在不同分片(数据容器)中。
分片分为主分片 (primary shard) 以及从分片 (replica shard)。主分片会被尽可能平均地 (rebalance) 分配在不同的节点上(例如你有 2 个节点,4 个主分片(不考虑备份),那么每个节点会分到 2 个分片,后来你增加了 2 个节点,那么你这 4 个节点上都会有 1 个分片,这个过程叫 relocation,ES 感知后自动完成)。从分片只是主分片的一个副本,它用于提供数据的冗余副本,从分片和主分片不会出现在同一个节点上(防止单点故障),默认情况下一个索引创建 5 个主分片,每个主分片会有一个从分片 (5 primary + 5 replica = 10 个分片)。如果你只有一个节点,那么 5 个 replica 都无法被分配 (unassigned),此时 cluster status 会变成 Yellow。
分片是独立的,对于一个 Search Request 的行为,每个分片都会执行这个 Request。每个分片都是一个 Lucene Index,所以一个分片只能存放 Integer.MAX_VALUE – 128 = 2,147,483,519 个 docs。
replica 的作用主要包括:
1、 容灾:primary 分片丢失,replica 分片就会被顶上去成为新的主分片,同时根据这个新的主分片创建新的 replica,集群数据安然无恙;
2、 提高查询性能:replica 和 primary 分片的数据是相同的,所以对于一个 query 既可以查主分片也可以查从分片,在合适的范围内多个 replica 性能会更优(但要考虑资源占用也会提升 [cpu/disk/heap]),另外 Index Request 只能发生在主分片上,replica 不能执行 Index Request。
注意:对于一个索引,除非重建索引否则不能调整主分片的数目 (number_of_shards),但可以随时调整 replica 的数目 (number_of_replicas)。
节点
一个 ES 节点就是一个运行的 ES 实例,可以实现数据存储并且搜索的功能。每个节点都有一个唯一的名称作为身份标识,如果没有设置名称,默认使用 UUID 作为名称。最好给每个节点都定义上有意义的名称,在集群中区分出各个节点。
一个机器可以有多个实例,所以并不能说一台机器就是一个 node,大多数情况下每个 node 运行在一个独立的环境或虚拟机上。
节点类型
master 节点: 集群中的一个节点会被选为 master 节点,它将负责管理集群范畴的变更,例如创建或删除索引,添加节点到集群或从集群中删除节点。master 节点无需参与文档层面的变更和搜索,这意味着仅有一个 master 节点并不会因流量增长而成为瓶颈。任意一个节点都可以成为 master 节点。
data 节点: 持有数据和倒排索引。默认情况下,每个节点都可以通过设定配置文件 elasticsearch.yml 中的 node.data 属性为 true (默认) 成为数据节点。如果需要一个专门的主节点 (一个节点既可以是 master 节点,同时也可以是 data 节点),应将其 node.data 属性设置为 false。
client 节点: 如果将 node.master 属性和 node.data 属性都设置为 false,那么该节点就是一个客户端节点,扮演一个负载均衡的角色,将到来的请求路由到集群中的各个节点。
集群
节点通过设置集群名称,在同一网络中发现具有相同集群名称的节点,组成集群。每个集群都有一个 cluster name 作为标识,默认的集群名称为 elasticsearch。如果在同一网络中只有一个节点,则这个节点成为一个单节点集群。
集群状态
Green:所有主分片和从分片都准备就绪(分配成功),即使有一台机器挂了(假设一台机器一个实例),数据都不会丢失,但会变成 Yellow 状态。
Yellow:所有主分片准备就绪,但存在至少一个主分片(假设是 A)对应的从分片没有就绪,此时集群属于警告状态,意味着集群高可用和容灾能力下降,如果刚好 A 所在的机器挂了,而从分片还处于未就绪状态,那么 A 的数据就会丢失(查询结果不完整),此时集群进入 Red 状态。
Red:至少有一个主分片没有就绪(直接原因是找不到对应的从分片成为新的主分片),此时查询的结果会出现数据丢失(不完整)。
总结
1、 从 ES 6.x 版本开始,已不建议在索引中设置多个类型。正确的结构:一个集群中有多个索引,一个索引中仅设置一种类型;
2、 一个节点运行在一个独立的环境或虚拟机上,一个节点可以包含多个分片,一个索引由多个分片组成;
3、 索引的主分片被尽可能平均的分配给各个节点;
4、 主分片与对应的从分片不能存储于同一个节点上。
参考阅读