Elasticsearch架构设计

性能

首先是关于性能问题,前文也提到了Elasticsearch是可以做到近乎实时,这里就不过多介绍了,有兴趣的可以去上一篇实时架构了解。

索引文件的更新

数据写入Elasticsearch,形成索引文件(segments),索引文件用看来支持用户查询。Elasticsearch默认每一秒会形成一个segment,就是说一个小时会有3600个segments。这些segments组成完整的数据分片。

merge

对于新的数据,增加segment可以实现数据的写入。而对于修改和删除,同样是依赖新生成的segment来进行修改/删除。因为Lucene的segment一旦形成,是不允许再进行修改的,所以Elasticsearch中所谓的删除是通过在新的segment中打标记实现的,修改则是通过新segment中通过对已有doc的_version来控制的。只有在触发segments merge,对多个segments进行合并成一个大的segment时,才会真正意义上删除掉数据。

segments merge

Elasticsearch自己有一个算法会自动触发segments merge,因为每一秒生成一个文件意味着会有很多很多文件,这是受文件句柄数限制的,所以必定要进行merge。

归并流程:

  1. 通过算法触发segments merge,将多个小的segments合并成一个大的segment。这个过程由独立线程完成,对Elasticsearch的功能没有影响。
  2. 合并过程中删除掉执行delete/update操作的原始doc。
  3. 刷新新的segment到磁盘。
  4. 检索请求从小的segment转移到大的segment中。
  5. 等待所有请求都转移成功后,删除小的segments。

force merge

Elasticsearch也提供了API支持我们手动强制merge,但是要慎用,因为merge会占用很大的系统开销。

curl -XPOST "http://localhost:9200/library/_forcemerge?max_num_segments=1
  • 1
  • 2

参数说明:

  • max_num_segments 期望merge到多少个segments,1的意思是强行merge到1个segment
  • only_expunge_deletes 只做清理有deleted的segments,即瘦身
  • flush 清理完执行一下flush,默认是true

归并

上面介绍了,无论是主动merge还是被动merge,在merge的过程中对Elasticsearch的功能是不会有影响的,但即便如此,也要谨慎使用merge功能。因为merge过程需要消耗大量的磁盘io和cpu,对集群的性能影响非常大,在一个高峰期触发一个merge很有可能导致崩溃。

归并线程大小

5.x之前的版本,Elasticsearch对于归并的这个线程,做了限速处理,配置indices.store.throttle.max_bytes_per_sec,默认是20MB。对于转速很高的磁盘像SSD,建议配置100M以上。
5.x之后的版本,使用了 Lucene 的 CMS(ConcurrentMergeScheduler) 的 auto throttle 机制。已经不再需要indices.store.throttle.max_bytes_per_sec这个配置了。

归并线程数

配置index.merge.scheduler.max_thread_count,默认:Math.min(4, Runtime.getRuntime().availableProcessors() / 2))。意思就是当cpu核数的一半大于4时,最多启动4个线程,否则启动cpu核数一半的线程数。如果觉得性能吃紧,就降低点线程数。

参考:
https://github.com/elastic/elasticsearch/blob/237650e9c054149fd08213b38a81a3666c1868e5/docs/reference/index-modules/merge.asciidoc

早期版本默认值是:Math.min(3, Runtime.getRuntime().availableProcessors() / 2)

归并策略

归并线程是按照一定的运行策略来挑选 segment 进行归并的。主要有以下几条:

  • index.merge.policy.floor_segment
    默认 2MB,小于这个大小的 segment,优先被归并。
  • index.merge.policy.max_merge_at_once
    默认一次最多归并 10 个 segments
  • index.merge.policy.max_merge_at_once_explicit
    默认 force merge 时一次最多归并 30 个 segments
  • index.merge.policy.max_merged_segment
    默认 5 GB,大于这个大小的 segment,不用参与归并。force merge 除外。

从这里我们可以看出,对于实时性要求不高的场景,加大flush的间隔(默认1秒),让每次生成的segment都很大,这样能够减少merge的次数,从而实现是能上的调优。

routing

前面系列文章中已经介绍了Elasticsearch通过routing来对Lucene实现分布式,但并没有具体介绍是怎么通过routing来计算得出写拿个分片的,在这里做补充。
公式:

shard = hash(routing) % number_of_primary_shards
  • 1
  • 2

routing即我们写入数据时指定的_routing值,如过没有指定则按照_id值来计算。从公式上很容易看出首先是对routing进行hash,然后除以主分片数取余。得到的结果就是要写入的分片。
公式很简单但也造成了弊端,就是number_of_primary_shards,一旦在创建index时指定就不能再进行修改,否则计算结果就会发生变化,整个数据就乱了。

数据一致性

Elasticsearch实现了对Lucene的分布式架构,并加入的副本机制来保障数据的安全性。但Elasticsearch时如何保证主分片与副本分片之间数据一致呢?
如图:
这里写图片描述

  1. 首先一个写入请求发到node1,当然也可以发送到集群中的任何一个节点,这里拿node1举例。
  2. node1接收到请求,根据_routing或_id来计算数据该写到哪个分片上,并且根据集群状态中的信息找到该分片的主分片在哪个节点上。找到知道发送数据到该节点。这里发送到node3。
  3. node3接收到请求的时候,开始往主分片里写数据。
  4. 主分片写入完成后,转发请求到该分片的副本分片所在节点(node1、node2),并等待返回结果。
  5. 副本分片接收到请求后,开始写入,写入成功后会返回结果给主分片节点。
  6. 主分片节点(node3)接收到返回请求后,会把写入成功返回给node1。

这里有几个配置是可以控制上诉行为的。

  • wait_for_active_shards
    等待副本分片返回个数,并不一定要等待所有副本分片全部返回。如果设置为1,则只要主分片写入成功,即返回给请求节点(node1),这个时候同时会转发请求给副本节点,但不再关系副本是否写入成功。

默认值是:int( (primary + number_of_replicas) / 2 ) + 1。

  • timeout
    超时时间,可以理解为等待返回的超时时间。一般情况下等待返回不会太久,但如果集群出现问题,已经有部分分片不可用,很有可能就会超时。

默认值:60s

分片的分配

分片分配在哪个节点上并不是固定的,某种触发条件下,会导致分片所在节点变化。

  • 创建index
  • 删除index
  • 副本分片数修改
  • 节点数修改

第一个还好说,新建的索引一般数据量很少。后三个操作在数据量很大的情况下,会造成严重的性能影响。
Elasticsearch同样有参数来控制分片分配行为的,由于篇幅较长,这里另起一篇文章详细介绍。

参考:Elasticsearch干货(四):深入理解分片分配

集群自动发现

Elasticsearch集群采用的是peer-to-peer模式,使用gossip协议。除了集群状态的请求之外,像写入/查询这种请求是可以发送到任何一个节点上的。

Elasticsearch2.X之前,同一个集群使用一个cluster.name配置进行识别,拥有相同cluster.name的节点视为同一个集群。

Elasticsearch2.X之后,为了数据安全考虑,进行了优化调整,改采用unicast的方式,就是单播。这样我们需要在每个节点的配置文件上指定集群节点的ip。

discovery.zen.ping.unicast.hosts=[ip1:port,ip2:port]

以下是关于集群节点发现和检测的相关配置:

  • discovery.zen.ping_timeout
    参数仅在加入或者选举 master 主节点的时候才起作用;

  • discovery.zen.fd.ping_timeout
    参数则在稳定运行的集群中,master 检测所有节点,以及节点检测 master 是否畅通时长期有用。

  • discovery.zen.fd.ping_interval: 10s
    重试间隔

  • discovery.zen.fd.ping_retries: 10
    重试次数

  • discovery.zen.minimum_master_nodes
    节点需要看到具有Master资格的节点最小个数

  • discovery.zen.ping.unicast.hosts
    配置具有Master资格的节点地址

--------------------- 本文来自 桃花惜春风 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/xiaoyu_BD/article/details/82427289?utm_source=copy

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值