网络知识 娱乐 ES(elasticsearch)的分片/副本与数据操作流程

ES(elasticsearch)的分片/副本与数据操作流程

1、前言 

        一台服务器上无法存储大量数据,ES把一个index里面的数据分成多个shard分布式的存储在多个服务器上(对大的索引分片,拆成多个,分不到不同的节点上)。ES就是通过shard来解决节点的容量上限问题的,通过主分片可以将数据分布到集群内的所有节点上。主分片数是在索引创建时指定的,一般不允许修改,除非Reindex。一个索引中的数据保存在多个分片中(默认为一个)相当于水平分表。一个分片表示一个Lucene的实例,它本身就是一个完整的搜索引擎。我们的文档被存储和索引到分片内,这些对应用程序是透明的,即应用程序直接与索引交互而不是分片。

        首先看一下一个ES集群大概的组织形式图。非常直观!!!!!

由上图可以看到shard可以分为主分片(primary shard)和副分片(replaca shard)。

图示为三个节点。其中任何一个都是有可能故障或者宕机的,此时其承载的shard的数据就会丢失;通过设置一个或者多个replica shard就可以在发生故障的时候提供备份服务。一方面可以保证数据不丢失,另一方面还可以提升操作的吞吐量和性能。

2、解读shard

        我们可以通过shards查看分片的具体信息。命令会列出详细的列出哪些节点包含哪些分片。也会告诉你这个分片的主/副信息、每个分片的文档数和这些文档在磁盘上占用的字节数。同时也会告诉你这些节点位于那个ip。 

#查看所有分片的情况
GET /_cat/shards?v
#指定查看某个索引的分片的情况
GET /_cat/shards/es_qidian_flow_online_v2_202202?v

GET /_cat/shards/es_qidian_flow_online_v2_202202?pretty&v  

注:GET /_cat/shards?v  这里"v"而不是"?v",如上这里是url链接参数的语法而已。他的的作用就是列出表头(还是要比较好,不熟悉的情况至少知道每个字段的含义)。如下为一个实例。

下图 为消息记录搜索功能对应的一个索引的具体分片信息,结合前面的示意图进行解读。

①可以看到node节点号和ip是完全;也可以看到对于消息记录搜索这个case总共有三个节点和腾讯与所购买的资源完全一致。

②shard列为分片号,分别为0~8;针对其中任一分片例如4,可以看到其有一个主分片(p)和一个副分片(p)。其中每一个分片有点像是mongodb的1主1从的一份副本集,不过在具体组织上还是有区别的。即mongodb任一个主or从其实都是对应一个mongod实例;但是对于这里的es而言总共只有三个node,2*9=18个主副分片都是分布在这三个node上,只不过在组织的时候尽量让主副分片不落在同一个node上就可以了。和前面的示意图也完全一致。

③docs可以看到每个分片的文档数,可以留意到同一分片的主副节点的文档数是完全一致的。这从侧面也说明了主副节点之间"副本集"的关系(一份数据冗余存储)。

④store可以看到磁盘存储空间的占用情况。

⑤增减节点(node)的时候shard会自动在nodes中负载均衡;其实从上面截图中我们也可以看到三个节点承载的分片数是差不多的。

⑥primary shard的数量在建立索引的时候一次设置,后续不能修改。replica shard数量应该是可以修改的。默认情况会分别创建5个primary shard和5个replica shard。关于截图这个case的9个分片就是创建索引的时候指定的,如下模板和索引中都能看到相关设置。

注:当然硬要修改分片数也是可以的,es也提供了相应的api来进行reindex。不过这个代价有点高,要重建整个索引。

思考:其实之所以代价高是es的路由机制决定的,分片数变化后就routing不到原来的数据了。当然我们可以进行更深层次的思考,尤其是和mongodb这种可以任意扩充分片的数据库进行对比。会发现本质原因对于ES来说shard就是承载数据的最小单位,写入的时候也完全是按照shard的数量进行的路由;而mongodb最小承载单位是chunk,chunk不是固定在某个shard一成不变,而是在balancer的控制下动态地游走于各个shard之间。

⑦primary shard不能和自己的replica shard放到同一个节点上(否则该节点挂了后这个分片的数据就彻底丢失了,起不到容错作用),但是可以和其他shard的replica节点放到一个节点上。

⑧每个doc肯定只存在于某一个primary shard以及其对应的replica shard中,不可能存在于多个primary shard上。

⑨replica的容错。primary shard宕机后,新master将某个replica提升为primary shard。重启宕机node,master copy备份的数据到重启后的node,然后还会同步宕机所落后的数据,并将这个shard降级为replica。

注:统计数据量的时候副本集只能算一份数据,不要重复统计了哦!(大概8亿/月)

3、ES集群的各节点(client/master/data)

前面第⑨点提到了发生宕机时master会参与恢复,这里简要的介绍下master。其实除了master ES集群中的节点根据其被配置后所实际执行的功能可以大致分为 client/master/data三种。

查看节点信息(谁是master节点),如下图有"*"号的就是master节点。 

GET _cat/nodes?v

前面所说的配置无非就是主节点和数据节点的配置,如下:

node.master: true
node.data: false

3.1 主节点(master node)

elasticsearch.yml

node.master: true
node.data: false

主要功能:维护元数据,管理集群节点状态;不负责数据写入和查询。
配置要点:内存可以相对小一些,但是机器一定要稳定,最好是独占的机器。

        当node.master被设置为true的时候就为主节点。理想情况下这个master节点就干一些管理性质的工作,比如维护索引元数据(创建删除索引)、负责切换primary shard和replica shard身份等。主节点的稳定性非常重要。默认情况集群中任何一个node.master没有被设为false的节点都有可能被选为主节点,为了让集群更加稳定分离主节点和数据节点是一个比较好的选择。

        要是master节点宕机了,那么会自动重新选举一个节点为master。

        如果非master节点宕机了,会有master节点让宕机节点上的primary shard的身份转义到其他机器上的replica shard。等到宕机机器重启恢复后,master节点会控制将缺失的replica shard分片补充过去,同步后续修改数据之类的,让集群恢复到有容错保障的状态。

        稳定的主节点对集群的健康是非常重要的。默认情况下任何一个集群中的节点都有可能被选为主节点。索引数据和搜索查询等操作会占用大量的CPU、内存、IO资源,为了确保一个集群的稳定,分离主节点和数据节点是一个比较好的选择。我们可以通过配置指定一个节点应该是数据节点还是master节点。

3.2 客户端节点(client node)

elasticsearch.yml

node.master: false
node.data: false
 
主要功能:负责任务分发和结果汇聚,分担数据节点压力。
配置要点:大内存,最好是独占的机器

        当node.master/data都被设置为false的时候即为客户端节点。此时该节点只能处理路由请求、处理搜索、分片索引操作等。独立的客户端节点在大型集群中是非常有用的,它协调主节点和数据节点。

3.3  数据节点(data node)

elasticsearch.yml

node.master: false
node.data: true


主要功能:负责数据的写入与查询,压力大。
配置要点:大内存,最好是独占的机器。

        node.master未设置为false、data被设置为true即为数据节点。数据节点的作用就是实际承载数据的节点,也是执行增删改查、聚合操作的节点。数据节点对cpu、内存、io要求较高。注意当资源不够用的时候需要向集群中添加新的节点。        

3.4 混合节点(mixed node)  不建议


elasticsearch.yml

node.master: true
node.data: true

4、ES的扩容

ES的扩容就是新增节点(node),然后在将所有的shard在节点之间进行一个重新的分配(负载均衡)就可以了。

5、ES集群数据写入拉取流程

相关参考

​​​​​​ElasticSearch学习之数据写入及查询流程分析_Charles Yan的博客-CSDN博客_elasticsearch接口写入数据

 【分布式搜索引擎】Elasticsearch写入和读取数据过程_NICE波的技术博客_51CTO博客

Elasticsearch分布式架构思考 - 知乎

5.1  ES数据写入流程

1)客户端选择一个node发送请求过去,这个node就是coordinating node(协调节点);
2)coordinating node,对document进行路由,将请求转发给对应的node(有primary shard);
3)实际的node上的primary shard处理请求,然后将数据同步到replica node;
4)coordinating node,如果发现primary node和所有replica node都搞定之后,就返回响应结果给客户端。
 

5.2  ES数据拉取流程

1)客户端发送请求到任意一个node,成为coordinate node;
2)coordinate node对document进行路由,将请求转发到对应的node,此时会使用round-robin随机轮询算法,在primary shard以及其所有replica中随机选择一个,让读请求负载均衡;
3)接收请求的node返回document给coordinate node;
4)coordinate node返回document给客户端。
 

1.写入document时,每个document会自动分配一个全局唯一的id即doc id,同时也是根据doc id进行hash路由到对应的primary shard上。也可以手动指定doc id,比如用订单id,用户id。

2.读取document时,你可以通过doc id来查询,然后会根据doc id进行hash,判断出来当时把doc id分配到了哪个shard上面去,从那个shard去查询

6、ES同mongodb分片集群比较

(0)MongoDB就是一个个的节点先组成副本集,一个个的副本集在mongos/configserver的组织下成为一个完整的分片集群;其逻辑组织(主副关系)形式和物理实体(ip)组织形式是完全一样的。ES更像是实现约定好固定的shard数量(主副),这些shard尽量均匀的分布在N个节点(node)上;其逻辑组织形式(主副关系)和物理实体(ip)组织形式是完全独立的。

(1)最大的不同就是ES各个节点的角色更加平等。对于ES而言,无论是写入还是查询客户端的请求可以作用与任意一个node。这个node就是协调节点,它的角色有点像是mongos了;负责路由、聚合等。其实从这个实现我们知道ES的每一个node都是要维护一个routing table的。

(2)比对mongodb和ES后发现,两者对于一个副本集在命令上存在差异,但意思是差不多的。ES把主、副称为primary shard和replica shard,但是mongodb里面称为primary节点和secondary节点。简单理解节点可以认为为一个ip实例(一台机器);对于ES来说一个节点通常包括多个shard,所以意思还是那个意思但是你不能用节点。但是对于mongodb来说一个mongod就是一个实例,所以直接称为节点就好了。

(3)对于写入操作。mongos的角色可能由任一个node承担,但是真正往某个shard写数据的时候其实还是优先作用与primary shard然后在同步到replica shard,这一点和mongodb差不多;只不过mongodb的一个副本集里面叫主从节点罢了。

(4)对于查询操作。mongos的角色可能由任一个node承担,但是具体进行查询的时候则是在对应分片的primary和replica中进行轮询;而mongodb则是提供了不同的选项。

下面也贴一个mongodb分片集的示意图,方便对比。