公号:码农充电站pro
主页:https://codeshellme.github.iohtml
ES 是一个分布式的集群,具备高可用性和可扩展性:node
ES 集群git
ES 集群中能够有一个或多个节点,ES 经过集群名字来区分不一样的集群,集群名能够经过 cluster.name
进行设置,默认为 "elasticsearch"。github
ES 的一个节点就是一个 Java 进程,因此一台机器能够运行一个或多个节点,生产环境建议一台机器只运行一个节点。算法
每一个节点启动以后,都会分配一个 UID
,并保存在 data
目录下。shell
每一个节点都有节点名字,节点名可经过 node.name
设置。缓存
Master 节点的职责:网络
集群的状态包括:架构
全部的节点有保存了集群的状态信息,但只有主节点可以修改集群状态。app
在 ES 集群中,只有 Master-eligible 节点能够被选举为 Master 节点。
每一个节点启动后默认就是 Master-eligible 节点,能够经过设置 node.master
为 false
来禁止成为 Master-eligible 节点。
默认状况下,集群中的第一个节点启动后,会将本身选举为 Master 节点。
集群中的每一个节点都保存了集群的状态,但只有 Master 节点可以修改集群的状态信息。
用于保存 ES 数据的节点,就是 Data 节点,它对数据扩展起到了相当重要的做用。
Coordinating 节点叫作协调节点,它负责接收 Client 的请求,将请求分发到合适的节点,并最终汇总结果返回给 Client。
在 ES 中,全部的节点都是 Coordinating 节点。
Ingest 节点用于对数据预处理,经过添加一些 processors 来完成特定的处理。
Ingest 节点是在 ES 5.0 后引入的一种节点类型,能够达到必定的 Logstash 的功能。
默认状况下,全部的节点都是 Ingest 节点。
理论上,一个节点能够扮演过多个角色,但生产环境中,建议设置单一角色。
节点的类型能够经过下面参数进行配置:
节点类型 | 配置参数 | 默认值 |
---|---|---|
Master-eligible | node.master | true |
Data Node | node.data | true |
Ingest Node | node.ingest | true |
Coordinating Node | 无 | 设置上面 3 个都为 false |
咱们能够经过下面的 API 来查看整个集群的健康状态:
集群有 3 种级别的健康状态:
green
:全部的主分片与副本分片都正常。yellow
:全部的主分片都正常,某些副本分片不正常。red
:部分主分片不正常。咱们也能够经过 Kibana 中的索引管理,来查看每一个索引的健康状态:
索引的状态级别与集群的状态级别一致。
脑裂问题是分布式系统中的经典问题。
脑裂问题指的是,当出现网络故障时,一些节点没法与另外一些节点链接,这时这两大部分节点会各自为主;当网络恢复时,也没法恢复成一个总体。
如何避免脑裂问题
要限定一个选举条件,设置 Quorum(仲裁):
只有当 Master eligible 节点数大于 Quorum 时,才能进行选举。
在 ES 7.0 以前,为了不脑裂问题,须要手动设置 discovery.zen.minimum_master_nodes
为 Quorum。
在 ES 7.0 以后,ES 会本身处理脑裂问题,不须要用户处理。
ES 中的分片(Shard)用于存储数据,是存储的最小单元。
分片有两种:主分片(Primary Shard)和副本分片(Replica Shard),副本分片是主分片的拷贝。
主分片用于数据水平扩展的问题,主分片数在索引建立时指定,以后不容许修改。
副本分片用于解决数据高可用的问题,副本分片数能够动态调整。
分片数能够经过索引的 setting
进行设置,好比:
PUT /index_name { "settings" : { "number_of_shards" : 3, "number_of_replicas" : 1 } }
其中 number_of_shards
表示主分片数,number_of_replicas
表示每一个主分片的副本分片数。
若是一个集群有 3 个数据节点,某个索引有 3 个主分片,1 一个副本分片,那么它的节点分布会像下面这样:
其中蓝色框为主分片,白色框为副本分片。
ES 在分配主副分片时,会将副本分片与主分片应该在不一样的节点上。
主分片和副本分片分别分布到不一样的数据节点上,这样的话,若是有某个数据节点宕机,也不会影响整个系统的使用。
ES 7.0 开始,默认的主分片数为 1,默认的副本分片数为 0。在生产环境中,副本分片数至少为 1。
分片数设置不合理引起的问题:
根据这样的配置(3 个主分片,1 个副本分片),若是只有一个节点,则会致使副本分片没法分配(ES 会将主副分片分配在不一样的节点上),集群状态为 yellow。
若是此时增长一个数据节点,那么副本分片就得以分配,集群具有了故障转移能力,集群状态转为 green。
若是此时再增长一个数据节点,那么主节点会从新分配分片的分布。同时,集群的总体能力也获得了提高。
若是此时有一个节点发生故障,好比主节点发生了故障:
此时集群的状态会变为 yellow,而后会从新选举主节点(假设选举了 Node2 为主节点),而且原来的 Node1 节点上的 p0 和 R1 分片,会被分配到 Node2 和 Node3 上。
集群调整完毕后,会从新恢复到 green 状态。
ES 中的一个分片对应了 Lucene 中的一个 Index。
在 Lucene 中,单个倒排索引文件称为 Segment。
Segment 是不可变的,当有新的文档写入时,会生成新的 Segment(放在文件系统缓存中)。
多个 Segment 汇总在一块儿称为 Lucene 中的 Index,也就是 ES 中的分片。
ES 的文档在写入时,会先放在 Index Buffer
(内存) 中,当 Index Buffer 的空间被占用到必定程度/时间周期后,会 Refresh 到 Segment 中,Index Buffer 则会被清空。
Refresh 的刷新频率能够经过 index.refresh_interval 参数进行设置,默认为 1 秒。
或者当 Index Buffer 被占用到 JVM 的 10%(默认值),也会触发 Refresh。
当文档被 Refresh 到 Segment 后,就能够被 ES 检索到了。
写入文档时,会先放在 Index Buffer
中,而 Index Buffer 是在内存中,为了防止内存意外(好比断电)丢失,在写入 Index Buffer 的同时,也会写到 Transaction log(磁盘)中。
一个 Transaction log 默认是 512M。
ES 的 Flush 会触发如下操做:
Flush 操做默认 30 分钟调用一次,或者当 Transaction log 满(默认 512 M)时也会触发 Flush。
当愈来愈多的 Segment 被写入到磁盘后,磁盘上的 Segment 会变得不少,ES 会按期 Merge 这些 Segment。
文档的删除操做并不会立刻被真正的删除,而是会写入 del 文件中,Merge 操做也会删除该文件。
Merge 操做能够由 ES 自动触发,也能够手动强制 Merge,语法以下:
POST index_name/_forcemerge
文档会均匀分布在分片上,充分利用硬件资源,避免资源利用不均。
文档到分片的路由算法:
shard_index = hash(_routing) % number_of_primary_shards
_routing
值为文档 id。_routing
的值也能够自行指定。正是由于文档的路由算法是基于主分片数来计算的,因此主分片数一旦肯定之后,就不能修改。
_routing 的设置语法以下:
POST index_name/_doc/doc_id/routing=xxx { # 文档数据 }
文档的 Write 操做(插入,更新,删除)的流程:
ES 的搜索过程分两个阶段:
From + Size
个排好序的文档 ID 和排序值(score),给 Coordinating 节点。From + Size
个文档的 ID。Multi Get
的方式,到相应的分片获取具体的文档信息,并返回给用户。这两个阶段合称为 Query Then Fetch。
(本节完。)
推荐阅读:
欢迎关注做者公众号,获取更多技术干货。