elasticsearch (二) 集群读写原理

寵の児 提交于 2020-04-27 10:30:19

参考资料

ES角色配置要求

  • master
    这里的master是指节点具备竞选master节点的node,如果这个节点不是data node,则它只会进行master节点竞选、客户端请求路由的功能,所以对内存/IO/CPU的需求一般。
  • data node
    data node是干活的节点,负责数据的读写,索引的查询、聚合等功能对内存、IO、CPU要求较高。
  • 客户端节点 客户端节点和master节点功能类似,基本上是用来路由请求,对内存、IO、CPU要求一般。

为什么要有master

在分布式系统中,master的作用基本都是用做对关键数据写一致性的,在ES中也是如此。
在ES cluster中,索引的创建和删除,必须通过master来进行。master指定哪个索引的哪个分片、副本在哪台机器上,并将这些关键信息分发给集群内的机器。这样客户端连接任意一台机器,进行读写索引请求时,就知道应该路由到哪台具体的机器上。
试想一下,如果没有master节点,并发创建同一个索引,假设同时有多台机器进行同一个索引分片和副本的分配,那就会产生混乱。

master具体作用

  • 负责跟踪集群的所有节点。
  • 负责索引的创建和删除。
  • 负责吧集群中的节点、索引、分片、副本等信息同步给各个节点。

master选举

什么时候选举

  • 当集群初始化的时候。
  • master候选节点会定时ping其他候选节点,当一定数量的候选节点无法ping通则发起选举。(一定数量是指:选举票数) 。

选举算法

Gossip算法,有兴趣可以了解下 Gossip算法

选举要注意的问题

避免脑裂问题的产生,有效选举票数必须大于:N/2+1(N是具备选举资格的节点数)。
具体参数: discovery.zen.minimum_master_nodes。

分片和副本的指定与修改

分片

索引的分片数在创建索引时指定,且无法修改。
原因是写入索引的过程中,负载均衡算法是根据document_id进行hash取余,将具体的请求路由到分片对应的机器上,如果在副本变更的过程中对集群进行读写,则会出现路由不正确的情况。

副本

副本是可以随时更改的。

连接集群、读写LB

在es cluster中,任何一个节点,都是一个协调节点(Coordinating Node),在上面“master 作用”中描述,master会将集群中节点、分片和副本的信息同步给集群内所有的机器,所以客户端可以连接任意一个或者N个协调节点对集群进行访问。
如果我们连接信息中写多个节点的地址,则在客户端就形成了一个Load balance;当然也可以让集群维护一个VIP提供客户端访问。

一次写入的过程

当客户端发起一次数据写入请求,会经历什么?

  • 找到分片位置 由于集群内任何一台机器都由master节点同步了集群中的信息。所以任何一个节点都可以根据固定的路由算法,将写入索引的请求路由到指定的机器上。
    具体算法:hash(dockement_id)%分片数 。
  • 写入主分片Transcation Log
  • 写入系统内存
  • 定时将内存刷新到Fs cache 默认定时1s将内存中的的索引数据刷新到Fs cache中,此时产生句柄,由于句柄的产生,估此时就能被es搜索到,所以ES可以实现近乎实时的查询效果。这里也提供API进行手动刷新。
  • 持久化 默认情况下每隔30s 会将 FS cache中的 index 以及 Transaction Log 一并写入磁盘中。这里也提供API进行手动刷新。
  • 写入副本 主分片写完之后,会根据副本数量,开始写副本,副本的写一致性支持支持三种策略,quorum、one和 all(和kafka一样呢),默认为 quorum(超过半数副本写入即可返回成功)。
    对应参数 :wait_for_active_shards。

一次读取过程

读取过程

  • 路由读取请求 协调节点接受到读请求,并将请求分配到相应的分片上;默认情况下,每个分片创建10个结果(仅包含 document_id 和 Scores)的优先级队列,并以相关性排序,返回给协调节点。
  • 进行聚合 假设查询落入的分片数为 N,那么聚合阶段就是对 N*10 个结果集进行排序,然后再通过已经拿到的 document_id 查到对应的 document 并组装到队列里,组装完毕后将有序的数据返回给客户端。 Tips:深度分页查询是有风险的,所谓深度查询就是涉及到大量 shard 的查询时,直接跳页到几千甚至上万页的数据,协调节点就有宕机的风险,毕竟协调节点需要将大量数据汇总起来进行排序,耗费大量的内存和 CPU 资源。所以慎用!尽可能用 Scroll API ,即只允许拿到下一页的信息,不允许跳页的情况出现,会避免这种情况的发生。

读主分片还是幅?

查询阶段如果不特殊指定,落入的分片有可能是主也有可能是副,这个根据协调节点的负载均衡算法来确定。
如果要指定查询主副,可以在参数中配置preference:GET /_search?preference=*****。

  • _primary:只查询主分片。
  • primary_first:优先读取主分片,如果主分片无效或者失败,则会读取其他副本
  • _replica:只查副本
  • _replica_first:优先查询副本,如果副本无效就查询其他的分片

当然还有其他的,详见:search-request-preference

文档删除

文档并不会进行删除,只是会记录删除标记。

索引的扩容

我们知道,索引创建时就指定了分片数且不能更改,那么当我们单机的索引达到峰值该如何处理?
官方推荐我们:重新索引数据

mapping 修改、新增

  • es中的mapping field不允许修改
  • 但是可以新增
    需要注意的是新增field,老的数据并不会自动就拥有了这个新字段。 这时候我们用新增的字段是查询不到历史数据的;我们可以查询历史数据,批量修改。
    API: update-by-query

副本升级

分片同步

分片过多的影响

每个分片本质上就是一个Lucene索引, 因此会消耗相应的文件句柄, 内存和CPU资源。 在查询的时候,由于协调节点需要进行聚合,分片数多会对协调节点压力增大。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!