翻译自官网, 水平有限,用于自查。转载请注明网址: http://www.jianshu.com/p/2f546a525a81
介绍
每个Elasticsearch中的索引被分割成分片, 并且可以拥有多个副本。这些副本被称之为replication group且必须在文档添加和删除的时候保持同步。如果不这样做,从一份副本中读取到的结果可能与另一份读到的结果截然不同。保持分片副本同步和在服务器中读取它们就是我们所说的数据同步模型( data replication model)
Elasticsearch的数据分片模型基于主备模型(primary-backup model ),在微软的研究报告中有着及详尽的描述。这个模型基于replication group的一个副本作为主分片,其他副本称为副分片(replica shards)。主分片作为所有索引操作的入口,它负责验证它们, 并确保它们是正确的。一旦一个索引操作被主分片接受,主分片也负责将操作复制到其他副本上。
本节的目的是对Elasticsearch复制模型进行高度概述,并讨论它对读写操作之间的各种交互影响。
基础写模型
Elasticsearch中每个索引操作首先被解析为一个使用路由的replication group, 通常基于文档ID。 一旦确定了replication group, 操作就会被内部转发到组中的主分片。主分片负责验证操作,并将它转发给其他副本。由于副本可以脱机, 主分片无需复制到所有副本。相反, Elasticsearch保留了一个应该接受操作的分片副本里列表。这个列表被称为同步副本(in-sync copies)并由主节点维护。顾名思义, 这是一组“好”分片副本, 它们保证处理所有向用户承诺的索引和删除操作。 主分片负责维护这个不变量,因此必须将所有操作复制到集合中的每一个副本上。
主分片遵循这个基本流程:
- 验证到来的操作, 拒绝结构无效的操作。 (例如: 应该传一个数字而传来一个对象类型字段)
- 在本地执行操作, 即索引或删除相关文档。这也需要验证字段的内容并在需要的时候拒绝。(例如:一个keyword类型的值对Lucene索引来说过长了)
- 将操作转发到当前同步副本集合中, 如果有多个副本, 则并行执行。
- 一旦所有副本成功执行了操作并对主分片做出响应, 主分片就会认为成功地完成了客户端的请求。
失败处理
索引过程中,很多事情可能会出错 —— 磁盘可能会损坏, 节点可能彼此失联, 或者某些配置错误也能导致一个副本操作失败,尽管在主分片上执行成功了。 尽管这些错误并不常见, 但主分片必须能够做出应对。
在主分片失败的情况下, 主分片所在的节点将像主节点发送一条消息。 索引操作将等待(默认1分钟)主节点将一个新分片提升为新的主分片。然后, 操作将被转发到新的主分片中进行处理。 注意, 主节点还会监视节点的健康状态, 并可能会主动为主分片降级。 这种情况典型地发生在主分片所在节点因为网络问题脱离集群。
一旦操作在主分片上成功地执行完毕, 当操作在副分片上执行时, 主服务器必须处理潜在的故障。 可能是由于副本的实际故障或由于网络问题导致操作无法到达副本(或阻碍副本做出响应)。 这些分片的结果是相同的: 同步副本中的一个副本错过了一个承诺的操作。 为了避免违背这个不变量, 主分片向主节点发送一条消息, 将有问题的分片从同步副本集合中删除。只有一次删除分片的操作被主节点接受, 主分片才告知确认操作。请注意, 主节点还将知识另一个节点开始构建新的副本分片, 以便将系统恢复到健康状态。
在将一个操作转发到副本时, 主分片将使用副本去验证自己仍然是存活的主分片。 如果由于网络分区(活一个长时间的垃圾回收)而脱离集群, 在它意识到自己被降级之前, 可能会继续处理进入的索引操作。 这些来自过期的主分片的操作会被副本拒绝。 当主分片因为自己不再是主分片而接收到来自副本的拒绝请求, 它将向主节点发送请求并了解到自己已经被替换。 操作将会被路由到新的主分片。
如果没有副本会怎样?
这是一个合法的场景,可能因为索引配置发生, 也可能只是因为所有的副本都创建失败了。在这种情况下, 主分片只处理操作而不需要外部验证似乎是有问题的。 另一方面, 主分片不能代替主节点而自行舍弃其他分片。 这意味着主节点知道主分片是唯一的“好”副本。 因此, 我们保证主节点不会提升任何其他(过时的)分片复制为新的主分片, 并且任何索引进主分片的操作都不会丢失 。 当然, 因为在这点上, 我们只运行数据的单一副本, 硬件问题可能会导致数据丢失。 See the section called "Wait For Active Shards" for some mitigation options.
基础读模型
Elasticsearch中的读取可以是非常轻量级的通过ID查找, 或者是一个占据重要CPU资源的带有复杂聚合的重量级搜索。 主备模型的一个好处是保持所有分片副本相同(除了“飞行模式”操作的异常), 因此一个同步副本就可以满足读需求。
当一个节点接收到读请求, 该节点负责将其转发到保存着相关分片的节点。 并收集整理响应,返回给客户端。 我们称此节点为该请求的协调节点(coordinating node)
基本流程如下:
- 将读请求分解到相关的分片。 注意, 由于大多数搜索将被发送到一个或多个索引, 所以它们需要从多个分片中读取, 每个分片代表着不同的数据子集。
- 从分片replication group中选择每一个相关分片中的活动副本。 可以是主分片,也可以是副本。 默认情况下, Elasticsearch 会简单地在分片副本之中轮询。
- 发送分片级别的读请求到所选的副本上。
- 合并结果并作出响应。 注意, 在ID查找的情况下, 只有一个相关分片, 这个步骤可被跳过。
失败处理
当一个分片不能响应一个读请求时,协调节点将从相同的replication group中选择另一个副本, 并发送分片级别的读请求到这个副本上。 重复的失败会导致没有可用的分片副本。 在有些情况下, 比如说 _search, Elasticsearch将会更加倾向于快速响应, 尽管是部分结果。 而不是等待问题的解决(部分结果在响应头部以_shards标明)。
一些简单含义
每一个基础流程都决定了Elasticsearch如何作为一个系统来进行读和写操作。 此外, 由于读和写请求可以并发执行, 这两个基本流是互相影响的。 这里有一些内在含义:
有效读取
正常情况下, 每个相关的replication group对每个读操作进行一次操作。 只有在失败的条件下会对同一个分片的多个副本执行相同的搜索操作。
未确认的读取
由于主分片首先在本地索引然后复制请求, 可能会有一个并发的读操作在写确认前就能发现变化。
默认情况下两个副本
同时只维护两个数据副本是一个可容错的模型。对比候选团系统(quorum-based system),容错需要最少三个副本。
失败
失败可能因为:
一个单独的分片会减慢索引
因为在每个操作期间,主分片等待同步副本中的所有副本, 单个慢分片会减慢整个replication group的速度。 这是我们为上面提到的读效率付出的代价。 当然一个慢分片也会减慢不幸被路由到它的搜索。
脏读取
一个孤立的主分片可以写,但不会被确认操作 。 这是因为一旦一个孤立的主分片向其副本发送请求或与主服务器联系, 它会意识到自己被隔离。此时, 操作已经索引进主分片并且可以被一个并行的读操作读取。
Elasticsearch可以通过默认每秒ping主节点来减轻这种风险, 如果没有主节点的消息, 则拒绝此操作。
冰山一角
本文提供了Elasticsearch如何处理数据的高层次概述。 当然, 有很多很多实际发生的情况。 像primary terms, cluster state publishing 和 master election 都在保持系统正确运行中扮演着重要的角色。 本文中也不包含已知的重要的bug(包括关闭和打开的)。 我们认为Github很难追随, 为了帮助人们在这些问题上保持领先, 我们在网站上维护了一个弹性页面, 我们强烈建议您阅读。