转载:http://www.infoq.com/cn/articles/anatomy-of-an-elasticsearch-cluster-part02

共识——裂脑问题及法定票数的重要性

共识是分布式系统的一项基本挑战。它要求系统中的所有进程/节点必须对给定数据的值/状态达成共识。已经有很多共识算法诸如RaftPaxos等,从数学上的证明了是行得通的。但是,Elasticsearch却实现了自己的共识系统(zen discovery),Elasticsearch之父Shay Banon在这篇文章中解释了其中的原因。zen discovery模块包含两个部分:

  • Ping: 执行节点使用ping来发现彼此
  • 单播(Unicast):该模块包含一个主机名列表,用以控制哪些节点需要ping通

Elasticsearch是端对端的系统,其中的所有节点彼此相连,有一个master节点保持活跃,它会更新和控制集群内的状态和操作。建立一个新的Elasticsearch集群要经过一次选举,选举是ping过程的一部分,在所有符合条件的节点中选取一个master,其他节点将加入这个master节点。ping间隔参数ping_interval的默认值是1秒,ping超时参数ping_timeout的默认值是3秒。因为节点要加入,它们会发送一个请求给master节点,加入超时参数join_timeout的默认值是ping_timeout值的20倍。如果master出现问题,那么群集中的其他节点开始重新ping以启动另一次选举。这个ping的过程还可以帮助一个节点在忽然失去master时,通过其他节点发现master。

注意:默认情况下,client节点和data节点不参与这个选举过程。可以在elasticsearch.yml配置文件中,通过设置discovery.zen.master_election.filter_client属性和discovery.zen.master_election.filter_data属性为false来改变这种默认行为。

故障检测的原理是这样的,master节点会ping所有其他节点,以检查它们是否还活着;然后所有节点ping回去,告诉master他们还活着。

如果使用默认的设置,Elasticsearch有可能遭到裂脑问题的困扰。在网络分区的情况下,一个节点可以认为master死了,然后选自己作为master,这就导致了一个集群内出现多个master。这可能会导致数据丢失,也可能无法正确合并数据。可以按照如下公式,根据有资格参加选举的节点数,设置法定票数属性的值,来避免爆裂的发生。

discovery.zen.minimum_master_nodes = int(# of master eligible nodes/2)+1

这个属性要求法定票数的节点加入新当选的master节点,来完成并获得新master节点接受的master身份。对于确保群集稳定性和在群集大小变化时动态地更新,这个属性是非常重要的。图a和b演示了在网络分区的情况下,设置或不设置minimum_master_nodes属性时,分别发生的现象。

注意:对于一个生产集群来说,建议使用3个节点专门做master,这3个节点将不服务于任何客户端请求,而且在任何给定时间内总是只有1个活跃。

我们已经搞清楚了Elasticsearch中共识的处理,现在让我们来看看它是如何处理并发的。

并发

Elasticsearch是一个分布式系统,支持并发请求。当创建/更新/删除请求到达主分片时,它也会被平行地发送到分片副本上。但是,这些请求到达的顺序可能是乱序的。在这种情况下,Elasticsearch使用乐观并发控制,来确保文档的较新版本不会被旧版本覆盖。

每个被索引的文档都拥有一个版本号,版本号在每次文档变更时递增并应用到文档中。这些版本号用来确保有序接受变更。为了确保在我们的应用中更新不会导致数据丢失,Elasticsearch的API允许我们指定文件的当前版本号,以使变更被接受。如果在请求中指定的版本号比分片上存在的版本号旧,请求失败,这意味着文档已经被另一个进程更新了。如何处理失败的请求,可以在应用层面来控制。Elasticsearch还提供了其他的锁选项,可以通过这篇来阅读。

当我们发送并发请求到Elasticsearch后,接下来面对的问题是——如何保证这些请求的读写一致?现在,还无法清楚回答,Elasticsearch应落在CAP三角形的哪条边上,我不打算在这篇文章里解决这个素来已久的争辩。

但是,我们要一起看下如何使用Elasticsearch实现写读一致。

一致——确保读写一致

对于写操作而言,Elasticsearch支持的一致性级别,与大多数其他的数据库不同,允许预检查,来查看有多少允许写入的可用分片。可选的值有quorumoneall。默认的设置为quorum,也就是说只有当大多数分片可用时才允许写操作。即使大多数分片可用,还是会因为某种原因发生写入副本失败,在这种情况下,副本被认为故障,分片将在一个不同的节点上重建。

对于读操作而言,新的文档只有在刷新时间间隔之后,才能被搜索到。为了确保搜索请求的返回结果包含文档的最新版本,可设置replication为sync(默认),这将使操作在主分片和副本碎片都完成后才返回写请求。在这种情况下,搜索请求从任何分片得到的返回结果都包含的是文档的最新版本。即使我们的应用为了更高的索引率而设置了replication=async,我们依然可以为搜索请求设置参数_preferenceprimary。这样,搜索请求将查询主分片,并确保结果中的文档是最新版本。

我们已经了解了Elasticsearch如何处理共识、并发和一致,让我们来看看分片内部的一些主要概念,正是这些特点让Elasticsearch成为一个分布式搜索引擎。

Translog(预写日志)

因为关系数据库的发展,预写日志(WAL)或者事务日志(translog)的概念早已遍及数据库领域。在发生故障的时候,translog能确保数据的完整性。translog的基本原理是,变更必须在数据实际的改变提交到磁盘上之前,被记录下来并提交。

当新的文档被索引或者旧的文档被更新时,Lucene索引将发生变更,这些变更将被提交到磁盘以持久化。这是一个很昂贵的操作,如果在每个请求之后都被执行。因此,这个操作在多个变更持久化到磁盘时被执行一次。正如我们在上一篇文章中描述的那样,Lucene提交的冲洗(flush)操作默认每30分钟执行一次或者当translog变得太大(默认512MB)时执行。在这样的情况下,有可能失去2个Lucene提交之间的所有变更。为了避免这种问题,Elasticsearch采用了translog。所有索引/删除/更新操作被写入到translog,在每个索引/删除/更新操作执行之后(默认情况下是每5秒),translog会被同步以确保变更被持久化。translog被同步到主分片和副本之后,客户端才会收到写请求的确认。

在两次Lucene提交之间发生硬件故障的情况下,可以通过重放translog来恢复自最后一次Lucene提交前的任何丢失的变更,所有的变更将会被索引所接受。

注意:建议在重启Elasticsearch实例之前显式地执行冲洗translog,这样启动会更快,因为要重放的translog被清空。POST /_all/_flush命令可用于冲洗集群中的所有索引。

使用translog的冲洗操作,在文件系统缓存中的段被提交到磁盘,使索引中的变更持久化。现在让我们来看看Lucene的段。

Lucene的段

Lucene索引是由多个段组成,段本身是一个功能齐全的倒排索引。段是不可变的,允许Lucene将新的文档增量地添加到索引中,而不用从头重建索引。对于每一个搜索请求而言,索引中的所有段都会被搜索,并且每个段会消耗CPU的时钟周、文件句柄和内存。这意味着段的数量越多,搜索性能会越低。

为了解决这个问题,Elasticsearch会合并小段到一个较大的段(如下图所示),提交新的合并段到磁盘,并删除那些旧的小段。

这会在后台自动执行而不中断索引或者搜索。由于段合并会耗尽资源,影响搜索性能,Elasticsearch会节制合并过程,为搜索提供足够的可用资源。

剖析Elasticsearch集群系列之二:分布式的三个C、translog和Lucene段的更多相关文章

  1. 剖析Elasticsearch集群系列第一篇 Elasticsearch的存储模型和读写操作

    剖析Elasticsearch集群系列涵盖了当今最流行的分布式搜索引擎Elasticsearch的底层架构和原型实例. 本文是这个系列的第一篇,在本文中,我们将讨论的Elasticsearch的底层存 ...

  2. 剖析Elasticsearch集群系列之一:Elasticsearch的存储模型和读写操作

    转载:http://www.infoq.com/cn/articles/analysis-of-elasticsearch-cluster-part01 1.辨析Elasticsearch的索引与Lu ...

  3. 剖析Elasticsearch集群系列之三:近实时搜索、深层分页问题和搜索相关性权衡之道

    转载:http://www.infoq.com/cn/articles/anatomy-of-an-elasticsearch-cluster-part03 近实时搜索 虽然Elasticsearch ...

  4. mongo 3.4分片集群系列之二:搭建分片集群--哈希分片

    这个系列大致想跟大家分享以下篇章: 1.mongo 3.4分片集群系列之一:浅谈分片集群 2.mongo 3.4分片集群系列之二:搭建分片集群--哈希分片 3.mongo 3.4分片集群系列之三:搭建 ...

  5. Hadoop集群搭建-full完全分布式(三)

    环境:Hadoop-2.8.5 .centos7.jdk1.8 一.步骤 1).4台centos虚拟机 2). 将hadoop配置修改为完全分布式 3). 启动完全分布式集群 4). 在完全分布式集群 ...

  6. ElasticSearch实战系列一: ElasticSearch集群+Kinaba安装教程

    前言 本文主要介绍的是ElasticSearch集群和kinaba的安装教程. ElasticSearch介绍 ElasticSearch是一个基于Lucene的搜索服务器,其实就是对Lucene进行 ...

  7. mongo 3.4分片集群系列之六:详解配置数据库

    这个系列大致想跟大家分享以下篇章: 1.mongo 3.4分片集群系列之一:浅谈分片集群 2.mongo 3.4分片集群系列之二:搭建分片集群--哈希分片 3.mongo 3.4分片集群系列之三:搭建 ...

  8. mongo 3.4分片集群系列之一:浅谈分片集群

    这篇为理论篇,稍后会有实践篇. 这个系列大致想跟大家分享以下篇章: 1.mongo 3.4分片集群系列之一:浅谈分片集群 2.mongo 3.4分片集群系列之二:搭建分片集群--哈希分片 3.mong ...

  9. mongo 3.4分片集群系列之八:分片管理

    这个系列大致想跟大家分享以下篇章: 1.mongo 3.4分片集群系列之一:浅谈分片集群 2.mongo 3.4分片集群系列之二:搭建分片集群--哈希分片 3.mongo 3.4分片集群系列之三:搭建 ...

随机推荐

  1. 在 Gradle 中使用 MyBatis Generator

    在 Intellij IDEA 中结合 Gradle 使用 MyBatis Generator 逆向生成代码 Info: JDK 1.8 Gradle 2.14 Intellij IDEA 2016. ...

  2. Mysql高效插入/更新数据

    从tushare抓取到的财务数据,最开始只是想存下来,用的办法想简单点,是:插入--报错-update 但发现这个方法太蠢,异常会导致大量无效连接,改为: for idx,row in d2.iter ...

  3. 快速准备(复制替换)一套新测试环境,CentOS7 MySQL相关配置

    拿到一个新环境,需要找相关配置,我有一个办法,相对能比较快速地复制一套环境出来. 修改机器配置: virsh 相关几条命令,已完成,后续我再整理补充... 虚拟化相关,参考:https://www.c ...

  4. Windows下libjpeg-trubo-1.5.3编译(VS2015)

    简述 https://libjpeg-turbo.org/的网站上是有已经编译好的版本下载的,但是VC下是使用的VC10.0编译的.虽然在VC14.0下也能用,但是我还是需要编译一个VC14.0版本的 ...

  5. 使用Ubuntu

    一.ubuntu把文件夹名称改为中文 vim ~/.config/user-dirs.dirs 修改文件内容为: XDG_DESKTOP_DIR="$HOME/Desktop" X ...

  6. ceph 对象存储跨机房容灾

    场景分析 每个机房的Ceph都是独立的cluster,彼此之间没有任何关系. 多个机房都独立的提供对象存储功能,每个Ceph Radosgw都有自己独立的命名空间和存储空间. 这样带来两个问题: 针对 ...

  7. 安装配置OSA运维管理平台

    1.下载完整包V1.0.2wget http://www.osapub.com/download/OSA_BETA_V1.0.2.tar.gzV1.0.5wget http://www.osapub. ...

  8. RandomAccessFile类理解

    一.简述 这个是JDK上的截图,我们可以看到它的父类是Object,没有继承字节流.字符流家族中任何一个类.并且它实现了DataInput.DataOutput这两个接口,也就意味着这个类既可以读也可 ...

  9. iOS的动态代理模式的实现

    动态代理模式的应用很多,特别是在不能修改被代理类的前提下,要对执行某些方法时需要打log或者捕捉异常等处理时,是一个非常方便的方法.只需要少量修改客户端(场景类)代码和添加一个代理类就可以实现,这个符 ...

  10. Android Studio Prettify 插件

    1.功能:能够一键声明layout文件中的所有注明id的控件,节省时间 2.github地址 https://github.com/Haehnchen/idea-android-studio-plug ...