Elasticsearch 文档读写模型实现原理
2、基本写模型
ElasticSearch 每个索引操作都首先被解析为一个使用路由的复制组,默认基于文档 ID(routing),其基本算法为 hash(routing) % (primary count)。一旦确定了复制组,则该操作将被转发到组的主分片(primary shard)。主碎片负责验证操作并将其转发到其他副本。由于副本可以离线,所以不需要复制到所有副本。相反,弹性搜索维护一个应该接收操作的碎片副本列表。这个列表被称为 in-sync 副本,由主节点维护。正如其名称所暗示的,这些是一组“好”碎片副本,它们保证已经处理了所有已被用户认可的索引和删除操作。主负责维护这个不变式,因此必须将所有操作复制到这个集合中的每个副本。
主分片处理流程:
验证请求是否符合 Elasticsearch 的接口规范,如果不符合,直接拒绝。
在主分片上执行操作(例如索引、更新或删除一个文档)。如果执行过程中出错,直接返回错误。
将操作转发到当前同步副本集的每个副本。如果有多个副本,则并行执行。(in-sync 当前可用、激活的副本)。
一旦所有的副本成功地执行了操作并对主服务器进行了响应,主服务器就会承认对客户机的请求的成功完成。写请求的流程如下图所示(图片来源于《Elasticsearch 权威指南》):
错误处理:
在索引过程中,许多事情可能会出错——磁盘可能会被破坏,节点可以彼此断开,或者一些配置错误可能导致一个副本的操作失败,尽管它在主服务器上是成功的。这些都是罕见的,但主要的是要对它们做出反应。
另外一种情况是如果主服务器不可用,托管主节点的节点将向 master 发送一条消息。索引操作将等待(默认情况下最多 1 分钟),以便 master 服务器将其中一个副本提升为一个新的主节点。然后,该操作将被转发到新的主服务器进行处理。请注意,主服务器(master)还监控各个节点的健康状况,并可能决定主动降级主节点。这通常发生在持有主节点的节点通过网络问题与集群隔离的情况下。为了更好的理解 master 服务器与主分片所在服务器的关系,下面给出一个 ElasticSearch 的集群说明图:
其中 NODE1 为整个集群的 master 服务器,而第一个复制组(P0,R0,RO,其主分片所在服务器 NODE3),第二个复制组(P1,R1,R1,其主分片所在服务器 NODE1)。
一旦在主服务器上成功执行了操作,主服务器就必须确保数据最终一致,即使由于在副本上执行失败或由于网络问题导致操作无法到达副本(或阻止副本响应)造成的。为了避免数据在复制组内数据的不一致性(例如在主分片中执行成功,但在其中一两个复制分片中执行失败),主分片在如果未在指定时间内(默认一分钟)未收到复制分片的成功响应或是收到错误响应,主分片会向 Master 服务器发送一个请求,请求从同步副本中删除有问题的分片,当主分片确认删除有问题的副本时,Master 会指示删除有问题的副本。同时,master 还会指示另一个节点开始构建新的分片 《一线大厂 Java 面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》开源 副本,以便将系统恢复到一个健康状态。
主分片将一个操作转发到副本时,首先会使用副本数来验证它仍然是活动的主节点。如果由于网络分区(或长 GC)而被隔离,那么在意识到它已经被降级之前,它可能会继续处理传入的索引操作并转发到从服务器。来自陈旧的主服务器的操作将会被副本拒绝。当主接受到来自副本的响应为拒绝它的请求时,此时的主分片会向 Master 服务器发送请求,最终将知道它已经被替换了,后续操作将会路由到新的主分片服务器上。
如果没有副本,那会发生什么呢?
这是一个有效的场景,可能由于配置而发生,或者是因为所有的副本都失败了。在这种情况下,主分片要在没有任何外部验证的情况下处理操作,这可能看起来有问题。另一方面,主分片服务器不能自己失败其他的分片(副本),而是请求 master 服务器代表它这样做。这意味着 master 服务器知道主分片是该复制组唯一的可用拷贝。因此,我们保证 master 不会将任何其他(过时的)分片副本提升为一个新的主分片,并且任何索引到主分片服务器的操作都不会丢失。当然这样意味着我们只使用单一的数据副本,物理硬件问题可能导致数据丢失。请参阅 Wait For Active Shards,以获得一些缓解选项,(该参数项将在下一节中详细描述)。
注:在一个 ElasticSearch 集群中,存在两个维度的选主。Master 节点的选主、各个复制组主分片的选主。详细的原理分析将在源码分析篇深入学习。
3、基本读模型
在 Elasticsearch 中,可以通过 ID 进行非常轻量级的查找,也可以使用复杂的聚合来获取非平凡的 CPU 能力。主备份模型的优点之一是它使所有的分片副本保持相同(除了异常情况恢复中)。通常,一个同步副本就足以满足读取请求。
当一个节点接收到 read 请求时,该节点根据路由规则负责将其转发给相应的数据节点,对响应进行整理,并对客户端作出响应。我们称该节点为该请求的协调节点。基本流程如下:
将读请求路由到到相关的分片节点。注意,由于大多数搜索条件中不包含分片字段,所以它们通常需要从多个分片组中读取数据,每个分片代表一个不同的数据子集(默认 5 个数据子集,因为 ElasticSearch 默认的主分片个数为 5 个)。
从每个分片复制组中选择一个副本。读请求可以是复制组中的主分片,也可以是其副本分片。在默认情况下,ElasticSearch 分片组内的读请求负载算法为轮询。
根据第二步选择的各个分片,向选中的分片发送请求。
汇聚各个分片节点返回的数据,然后返回个客户端,注意,如果带有分片字段的查询 Java 开源项目【ali1024.coding.net/public/P7/Java/git】 ,将之后转发给一个节点,该步骤可省略。
总结
面试难免让人焦虑不安。经历过的人都懂的。但是如果你提前预测面试官要问你的问题并想出得体的回答方式,就会容易很多。
此外,都说“面试造火箭,工作拧螺丝”,那对于准备面试的朋友,你只需懂一个字:刷!
给我刷刷刷刷,使劲儿刷刷刷刷刷!今天既是来谈面试的,那就必须得来整点面试真题,这不花了我整 28 天,做了份“Java 一线大厂高岗面试题解析合集:JAVA 基础-中级-高级面试+SSM 框架+分布式+性能调优+微服务+并发编程+网络+设计模式+数据结构与算法等”
且除了单纯的刷题,也得需准备一本【JAVA 进阶核心知识手册】:JVM、JAVA 集合、JAVA 多线程并发、JAVA 基础、Spring 原理、微服务、Netty 与 RPC、网络、日志、Zookeeper、Kafka、RabbitMQ、Hbase、MongoDB、Cassandra、设计模式、负载均衡、数据库、一致性算法、JAVA 算法、数据结构、加密算法、分布式缓存、Hadoop、Spark、Storm、YARN、机器学习、云计算,用来查漏补缺最好不过。
评论