正文前的小菜——Elasticsearch的基础概念(对基础概念了解的朋友可以直接往下看题)
Elasticsearch(简称ES)是一个基于Apache Lucene构建的开源、分布式、RESTful接口的全文搜索引擎。
以下是Elasticsearch的基础概念:
1.Elasticsearch的基本概念
(1) 索引(Index):
- 索引是Elasticsearch中存储数据的地方,可以把它理解为一个优化过的、快速查询的大型文档集合。
- 索引类似于关系型数据库中的“数据库”或“表”的概念,但它是面向文档的,且每个字段都可以被索引和搜索。
- 索引由名称(必须为全小写字符)标识,并通过此名称进行文档的创建、搜索、更新及删除操作。
(2) 文档(Document):
- 文档是Elasticsearch中的最小单位,是索引中的一条数据。
- 文档以JSON格式存储,包含多个字段,每个字段的类型由映射(Mapping)定义。
- 文档的字段类型可以是文本、数值、日期等,也可以是复杂类型,如嵌套文档或数组。
(3) 映射(Mapping):
- 映射定义了索引中文档的结构,包括字段的名称、类型和其他相关设置。
- 类似于关系型数据库中的模式(Schema),但Elasticsearch支持动态映射,即可以在插入新字段时自动创建映射。
(4) 分片(Shard):
- 分片是Elasticsearch分布式架构的基础,每个索引都可以被分成多个主分片(Primary Shard)和副本分片(Replica Shard)。
- 主分片负责数据的存储和索引,而副本分片则提供数据的冗余存储和负载均衡。
- 分片使得Elasticsearch能够横向扩展至数以百计的服务器,处理PB级的数据。
(5) 节点(Node):
- 节点是Elasticsearch集群中的一个实例,它可以是主节点(Master Node)、数据节点(Data Node)或客户端节点(Client Node)。
- 主节点负责集群的元数据存储和协调,数据节点负责数据的存储和检索,而客户端节点则提供RESTful API接口供外部访问。
2.Elasticsearch的工作原理简述
(1) 索引过程:
- 当向Elasticsearch中存入文档时,它会自动对文档的内容进行索引。
- 索引过程包括分词和倒排索引,帮助系统快速找到与查询匹配的文档。
(2) 查询过程:
- 查询请求会首先被发送到客户端节点或数据节点。
- 节点会根据查询条件将请求路由到包含相关数据的分片上。
- 分片会执行查询并返回结果给节点,节点再将结果汇总后返回给客户端。
3.Elasticsearch的应用场景
(1) 全文搜索:适用于需要全文检索的应用场景,如搜索引擎、文档管理系统等。
(2) 日志分析:适用于需要实时分析日志数据的应用场景,如运维监控、故障排查等。
(3) 实时数据分析:提供了聚合分析功能,可以实现对保存的大量数据的近实时统计分析。适用于需要实时数据分析的应用场景,如商业智能、数据分析等。
面试官:ES的整体架构是怎样的?
Elasticsearch(简称ES)的整体架构是分布式和模块化的,旨在支持大规模数据的搜索、分析和实时查询。
以下是ES整体架构的详细解释:
1.集群与节点
(1) 集群:Elasticsearch集群由多个节点组成,这些节点共同协作以提供搜索和分析功能。每个集群都有一个唯一的名称,节点通过这个名称进行通信。
(2) 节点:每个节点都是一个运行Elasticsearch实例的服务器。节点可以是主节点、数据节点、协调节点或备份节点(也称副本节点)。
- 主节点(Master Node):负责管理集群的状态和配置,如索引的创建和删除、节点的加入和离开等。
- 数据节点(Data Node):用于存储数据并执行与数据相关的操作,如搜索、聚合和索引。数据节点是集群中最重要的节点,因为它们会处理大多数请求。
- 协调节点(Coordinating Node):负责将请求路由到适当的节点,并将结果聚合返回给客户。协调节点本身不存储任何数据。
- 备份节点(Replica Node):不用于主数据存储,而是为主节点分片提供备份。若主节点出现故障,副本将自动替代其功能,保证高可用性。
2.索引与分片
(1) 索引:索引是存储文档的地方,可以视为一个数据库。每个索引都有一个唯一的名称,用于在搜索时引用。索引中的数据通常以JSON格式存储,并可以通过REST API进行操作。
(2) 分片:索引被分割成多个分片,每个分片是一个独立的Lucene索引。分片使得数据可以水平扩展,允许在多个节点上分布存储。每个索引可以有多个主分片(primary shard)和副本分片(replica shard)。主分片存储数据,副本分片用于提供数据冗余和负载均衡。
3.文档与字段
(1) 文档:文档是Elasticsearch中存储的基本信息单元,通常与数据库中的一行相对应。每个文档都有一个唯一的ID,且以JSON格式存储。文档包含多个字段,这些字段提供了文档的元数据或内容。
(2) 字段:文档中的每个属性都称为一个字段。字段可以包含文本、数字、日期、布尔值或地理位置等数据类型。
4.存储与检索机制
(1) 存储机制:当文档被写入Elasticsearch时,它们首先被存储在内存缓冲区(Memory Buffer)中。然后,这些文档会定期被刷新到磁盘上的段文件(Segment)中。段文件是Lucene索引的基本单位,它们包含了文档的倒排索引和其他相关信息。
(2) 检索机制:当用户执行搜索查询时,Elasticsearch会首先在Term Dictionary中查找查询字符串中的每个单词。然后,它会使用这些单词对应的倒排列表来找到包含这些单词的文档。最后,系统会根据文档的相关性得分对结果进行排序并返回给用户。倒排索引允许Elasticsearch快速定位到包含特定单词的文档集合。
5.容错与副本管理
(1) 容错机制:Elasticsearch通过副本机制来提高数据的可靠性和可用性。当主分片出现故障时,副本分片会自动提升为主分片,以继续提供服务。
(2) 副本管理:Elasticsearch会根据配置为主分片创建副本分片。这些副本分片可以分布在不同的节点上,以确保在主分片出现故障时,数据仍然可以从副本分片中恢复。
6.分布式架构与扩展性
(1) 分布式架构:Elasticsearch的分布式架构允许它横向扩展,以支持大规模数据集的存储与处理。通过添加更多节点到集群中,Elasticsearch可以自动重新分配数据以平衡负载并提高性能。
(2) 扩展性:Elasticsearch提供了灵活的扩展选项,包括垂直扩容(使用更强大的服务器)和水平扩容(添加更多服务器)。然而,水平扩容通常是更受欢迎的选择,因为它可以更有效地利用资源并避免单点故障。
面试官:Elasticsearch中的分片和副本是如何工作的?分片和副本的大小和数量如何影响ES的性能?
1.分片(Shard)
(1) 定义:分片是Elasticsearch分发数据的单元。每个分片本身就是一个完整的搜索引擎(Lucene实例),它保存了全部数据中的一部分。
(2) 创建与分配:
当创建一个新索引时,Elasticsearch会根据用户指定的分片数量(通过number_of_shards参数)创建主分片,并将这些分片分配到集群中的不同节点上。
分片的分配由Elasticsearch自动管理,确保它们分布在集群的不同节点上,以最大限度地提高系统的容错能力和性能。
(3) 数据写入:
对于写操作(如创建、更新或删除),Elasticsearch会将请求发送到包含相关分片的节点上执行。
写请求首先发送到主分片,主分片处理写请求并将数据写入到分片中,然后主分片将写操作同步到所有的副本分片,确保数据的一致性。
(4) 数据读取:
对于读取操作,Elasticsearch可以从任何具有对应分片(无论是主分片还是副本分片)的节点上获取数据。
这允许查询负载均衡,并且可以利用副本分片来增加搜索吞吐量。
2.副本(Replica)
(1) 定义:
副本是对主分片的冗余复制,用于提高数据的可用性和容错性。
每个主分片都可以有一个或多个副本分片。
(2) 创建与分配:
Elasticsearch根据索引的副本设置(通过number_of_replicas参数),为每个主分片创建副本分片。
副本分片被分配到与主分片不同的节点上,以确保数据冗余和故障恢复能力。
(3) 故障恢复:
如果某个节点宕机了,导致某些分片不可用,Elasticsearch会自动检测到这个问题并尝试使用副本分片来恢复服务。
Elasticsearch会将副本分片提升为主分片,并在集群中的其他节点上创建新的副本分片,以恢复数据冗余。
(4) 性能提升:
副本分片可以分担读请求,减少单个分片的读负载,从而提高搜索性能和吞吐量。
如下所示是启动2个ES节点,创建5个分片,1个副本的示例。
下面是启动3个ES节点,创建5个分片,1个副本的示例。
下面再说说看分片和副本的大小和数量对ES性能的影响。
3.分片大小和数量对性能的影响
(1) 分片大小:
- 写入性能:较小的分片可以减少每个分片上的数据量,从而可能加快写入速度,因为每次写入操作涉及的数据量更少。然而,过小的分片可能导致过多的分片数量,增加管理开销和I/O操作。相反,较大的分片可以处理更多的写入请求,提高系统的写入吞吐量,但过大的分片可能使故障恢复速度变慢。
- 读取性能:分片大小对读取性能的影响相对复杂。较小的分片可能减少查询时的数据扫描范围,但也可能增加查询时的分片间通信开销。较大的分片可能提高查询效率,但也可能导致查询延迟增加,因为需要处理的数据量更大。
(2) 分片数量:
- 写入性能:更多的主分片可以提高写入吞吐量,因为操作可以并行化到多个分片上。然而,每个分片都会消耗资源(CPU、内存、磁盘),过多的分片会导致资源竞争,反而降低性能。
- 读取性能:读取性能可以通过增加副本分片来提高,因为更多的副本可以处理更多的并发读请求。然而,分片数量过多也可能导致查询时的分片间通信开销增加,影响读取性能。
4.副本大小和数量对性能的影响
(1) 副本大小:
副本是数据的冗余拷贝,存储在副本分片中。副本分片的大小与主分片相同,因为它们是对主分片的完整复制。因此,副本大小本身对性能没有直接影响,但副本的数量和分布会影响性能。
(2) 副本数量:
提示:这里说的副本的数量是指ES对分片复制了几份副本,而不是一份副本有多少个分片。
- 读取性能:增加副本分片数量可以提高系统的读取性能,因为更多的副本可以处理更多的并发读请求。副本分片还可以减少单个分片的读负载,因为请求可以在多个副本之间均匀分配。
- 写入性能:每次写入操作不仅要在主分片上执行,还要在所有副本分片上重复。因此,增加副本分片数量会增加写操作的负担,每次写操作需要同步到更多的副本上。这可能导致写入性能下降,特别是在资源有限的情况下。
- 容错能力:副本分片还可以提高系统的容错能力。如果一个节点或分片失败,Elasticsearch可以从副本中恢复数据,几乎不影响用户查询。更多的副本可以更快地恢复数据,因为Elasticsearch有更多选项来重新分配和平衡网络中的数据。
5.优化建议
(1) 合理设置分片数量:
- 根据数据量、硬件资源和使用场景来设置主分片的数量。通常建议将每个主分片的大小保持在几十GB到几百GB之间。
- 对于需要频繁更新或删除的数据,较小的分片(如10GB-20GB)可能更合适,以减少段合并的开销。对于静态数据或只增加不修改的数据,更大的分片(接近50GB)通常更有效。
(2) 根据读取负载调整副本数量:
- 如果系统是读取密集型的(如搜索或分析应用),增加副本分片可以提供更好的读取性能。
- 在决定副本数量时,也要考虑集群的节点数量。至少应该有足够的节点来分配这些副本,以避免所有副本都在同一个节点上导致资源竞争。
(3) 监控和调整:
- 使用Elasticsearch的监控工具(如Kibana Monitoring)定期检查分片的健康和性能。
- 如果检测到性能瓶颈,可以根据具体情况调整分片和副本的数量。例如,使用Shrink API减少分片数量,或使用Split API增加分片数量。
面试官:说说看ES的倒排索引是如何实现的?
Elasticsearch使用倒排索引(Inverted Index)来存储和检索数据。倒排索引是一种数据结构,用于存储每个词(term)及其对应的文档ID列表(Posting List)。这种结构使得Elasticsearch能够快速地根据一个或多个词找到包含这些词的文档。
ES的倒排索引包括以下结构:
1.Term Dictionary
Elasticsearch将所有的词进行排序,并使用二分法查找词,以提高查找效率。这种排序后的词列表被称为Term Dictionary。
如下图所示是正排索引,正排索引是以文档的ID作为关键字,并且记录文档中每个字段的值信息,通过查询id来把整条文档拿出来。但是在查询某一个keyword存在于哪些文档的时候, 需要对所有文档进行扫描匹配。
这样检索效率比较低下:
再看倒排索引的Term Dictionary,倒排索引以字或词作为关键字索引, 倒排索引建立的是分词(Term)和文档(Document)之间的映射关系。
2.倒排列表(Posting List)
倒排列表记载了出现过某个单词的所有文档的文档列表。
列表中包含单词在该文档中出现的位置信息及频率(作关联性算分),每条记录称为一个倒排项(Posting)。
3.Term Index
由于Term Dictionary可能非常大,无法全部放入内存,因此Elasticsearch引入了Term Index。Term Index类似于字典的索引页,它包含了词的一些前缀和对应的Term Dictionary的block位置。通过Term Index,Elasticsearch可以快速定位到Term Dictionary的某个位置,然后从这个位置顺序查找所需的词。
4.FST(Finite State Transducers)
为了进一步优化Term Index,Elasticsearch使用了FST压缩技术。FST是一种有限状态机,它将词(字节序列)映射到任意输出。通过FST,Elasticsearch可以将Term Index占用的空间进一步缩小并缓存到内存中,从而提高查找效率。FST的实现相对比较复杂,面试的时候答到Term Dictionary、倒排列表 和 Term Index即可,如果还想把FST答出来就要理解FST算法的原理。下面简单描述下FST的构造过程。我们对“cat”、 “deep”、 “do”、 “dog” 、“dogs”这5个单词进行插入构建FST(注:必须已排序)。1)插入“cat”插入cat,每个字母形成一条边,其中t边指向终点。
2)插入“deep”与前一个单词“cat”进行最大前缀匹配,发现没有匹配则直接插入,P边指向终点。
3)插入“do”与前一个单词“deep”进行最大前缀匹配,发现是d,则在d边后增加新边o,o边指向终点。
4)插入“dog”与前一个单词“do”进行最大前缀匹配,发现是do,则在o边后增加新边g,g边指向终点。
5)插入“dogs”与前一个单词“dog”进行最大前缀匹配,发现是dog,则在g后增加新边s,s边指向终点。
最终我们得到了如上一个有向无环图。利用该结构可以很方便的进行查询,如给定一个term “dog”,我们可以通过上述结构很方便的查询存不存在,甚至我们在构建过程中可以将单词与某一数字、单词进行关联,从而实现key-value的映射。那么只要在每个节点或者指针上存储该节点上单词的倒排列表的地址就可以知道该单词对应的文档ID有哪些了。
面试官:能说说看Elasticsearch写入文档的过程是怎么样的吗?
在介绍ES的写入过程之前,先要介绍有关ES索引和段的基础概念。
在ES中,索引(Index)是一个逻辑命名空间,包含一组文档。每个索引由多个分片(Shard)组成,而每个分片又由多个segment组成。
segment是索引数据的实际存储单元,而分片则是数据分布和并行处理的基本单位。当查询一个Elasticsearch索引时,查询会在所有分片上执行,进而查询到segment,然后合并所有结果。每一个段都是一个独立的、不可变的文件集合,包含了完整索引中的一部分数据(包括倒排索引和正排索引)。
我们可以理解为,ES写入文档最终是要将文档写入到段中,这个文档才算进入了倒排索引,能够被搜索。
索引在 Lucene 中除表示所有段的集合外,还增加了提交点的概念。
为了提升写的性能,Lucene并没有每新增一条数据就增加一个段,而是采用延迟写的策略,每当有新增的数据时,就将其先写入内存中,然后批量写入磁盘中。若有一个段被写到硬盘,就会生成一个提交点,提交点就是一个列出了所有已知段和记录所有提交后的段信息的文件。
再回过头来说ES写入文档的过程,详细描述如下:
1.写入请求的接收与路由
(1) 接收请求:
客户端向Elasticsearch集群中的任意节点发送写入(Index)请求。
(2) 确定目标分片:
接收请求的节点(作为协调节点)根据文档的ID和索引的设置(如分片数量),使用哈希函数和模运算来确定文档应该写入到哪个主分片。
分片计算公式:shard_num = hash(_routing) % num_primary_shards。其中,_routing默认情况下是文档的ID,num_primary_shards是主分片的数量。
(3) 路由请求到目标节点:
协调节点根据目标分片的ID,通过集群状态中的路由表找到该分片的主分片所在的节点,并将请求转发给该节点。
2.在主分片上执行写入操作
(1) 内存缓冲区:
主分片接收到写入请求后,首先将文档存储在内存中的一个缓冲区(In-memory buffer)中。
(2) 记录事务日志:
同时,为了确保数据的持久性和可靠性,Elasticsearch将每个写入操作记录到事务日志(Translog)中。
Translog是一个追加写入的日志文件,它记录了所有对索引的更改,以便在系统崩溃后恢复数据。
(3) 创建倒排索引:
在内存缓冲区中,Elasticsearch将文档转换成倒排索引的形式,这个索引会在内存中形成一个分段对象(Segment),详情见下方的刷新操作(Refresh)。
倒排索引是Elasticsearch高效搜索的关键,它记录了每个单词在哪些文档中出现,以及出现的位置。
3.将数据同步到副本分片
(1) 异步复制:
一旦文档被写入到主分片,主分片会开始将数据异步地同步到其对应的副本分片上。
副本分片是主分片的完整拷贝,它们可以处理搜索请求并提供数据恢复的能力。
(2) 等待确认:
主分片等待所有副本分片都成功写入文档后,才向协调节点发送确认信息。
Elasticsearch的写入一致性策略(如quorum)确保了在写入数据时,必须有足够数量的活跃分片(包括主分片和副本分片)处于可用状态。
4.刷新与持久化
(1) 刷新操作(Refresh):
刷新操作会将内存缓冲区中的数据创建成一个新的Lucene段(Segment),并将其添加到索引中。
刷新操作是周期性的,可以通过配置来控制刷新的频率,它使得新写入的数据可以被搜索到,但它不会将数据持久化到磁盘上。
(2) 持久化操作(Flush):
持久化操作会将内存中的数据以及Translog中的更改写入到磁盘上。
这意味着数据被真正写入到了物理存储中,而不仅仅是保存在操作系统的文件系统缓存中。
持久化操作会调用操作系统的fsync函数来确保数据被写入磁盘,并且会清空相关的缓存和文件(如Translog)。
5.合并段(Segment Merging)
(1) 优化存储和搜索性能:
ElasticSearch 每次 refresh 一次都会生成一个新的 segment 文件,这样下来 segment 文件会越来越多。因为每一个 segment 都会占用文件句柄、内存、cpu资源,每个搜索请求都必须访问每一个segment,这就意味着存在的 segment 越多,搜索请求就会变得更慢。
为了优化存储和搜索性能,Lucene会定期进行段合并操作。
小的段会被合并到大的段中,然后这些大的段再被合并到更大的段。
(2) 合并过程:
合并过程在后台进行,不会中断索引和搜索操作。ElasticSearch 有一个后台进程专门负责 segment 的合并,定期执行 merge 操作,将多个小 segment 文件合并成一个 segment,在合并时被标识为 deleted 的文档不会被写入到新的 segment 中。
合并完成后,老的段会被删除,然后将新的 segment 文件 flush 写入磁盘。
然后创建一个新的 commit point 文件,标识所有新的 segment 文件,并排除掉旧的 segement 和已经被合并的小 segment。
面试官:Elasticsearch是如何实现master选举的?
1.选举机制概述
Elasticsearch的master选举机制主要通过Zen Discovery插件(默认插件)来实现。当Elasticsearch集群启动时,所有节点都处于一种“候选”状态,然后通过Zen Discovery机制相互发现,并参与到主节点的选举过程中。
2.选举过程
(1) 节点发现:
Elasticsearch集群中的节点通过Zen Discovery机制相互发现,确保集群状态的一致性。
(2) 候选者声明:
每个节点在启动时都会检查自己的配置(如node.master设置为true),以确定自己是否有资格成为主节点候选者。
具备候选资格的节点会将自己添加到候选者列表中。
(3) 投票机制:
候选者节点会向集群中的其他所有节点发送投票请求。
每个节点在收到投票请求后,会根据一定的规则(如节点的健康状况、存储的数据量、负载情况等)来决定是否投票给该候选者。
投票过程遵循多数原则,即一个候选者必须获得超过半数节点的选票才能成为主节点。
(4) 选举结果:
如果某个候选者得到了超过半数的投票,那么它就会成为新的master节点。
如果两个或更多的候选者得到了相同的票数,那么集群将会再次进行选举,直到选出一个明确的master节点。
三、选举过程中的关键要素
(1) 节点ID和版本号:
在选举过程中,节点的ID和版本号也是重要的考虑因素。通常,版本号更高的节点会被优先考虑作为主节点。
如果版本号相同,则会根据节点ID的大小来决定选举结果(ID越小,优先级越高)。
(2) 稳定性检查:
Elasticsearch会周期性地检查当前的主节点是否仍然有效。
如果主节点失去联系或不可用,集群会再次启动一个新的选举过程来选出新的主节点。
(3) 持久化和同步:
主节点的选举结果会被集群中的所有节点同步和持久化。
这确保了每个节点对当前的主节点有一致的认知,从而维护了集群的一致性。
面试官:ES集群的脑裂问题是如何产生的?如何避免ES集群发生脑裂?
1.基本概念
Elasticsearch集群中的脑裂问题(split-brain problem)是指在网络分裂或节点故障的情况下,集群中的节点可能无法就主节点的选择达成一致,导致多个节点各自认为自己是主节点,从而引发数据不一致和潜在的数据丢失问题。
2.产生原因
(1) 网络问题:
集群间的网络延迟或中断,导致一些节点无法访问到主节点(Master Node),从而认为主节点已经失效。
在这种情况下,这些节点可能会选举出新的主节点,并对原有的主节点上的分片和副本进行标记(如标红),然后分配新的主分片。
(2) 节点负载:
当主节点的角色既为Master又为Data时,如果访问量较大,可能会导致主节点停止响应或处于假死状态。
此时,其他节点得不到主节点的响应,会认为主节点已经挂掉,从而重新选举主节点。
(3) JVM内存回收:
Data节点上的Elasticsearch进程占用的内存较大时,可能会引发JVM的大规模内存回收,导致Elasticsearch进程失去响应。
这种情况也可能导致节点认为其他节点已经失效,从而尝试选举新的主节点。
(4) 配置不当:
如果Elasticsearch集群的配置不当,如最小主节点数(Minimum Master Nodes)设置不正确,也可能导致脑裂问题的发生。
最小主节点数应该设置为(N/2) + 1(其中N是具有主节点资格的节点数),以确保在集群分裂时只有一个主节点被选举出来。
3.影响与后果
- 数据不一致:在脑裂问题发生时,不同的节点组可能会执行不同的写操作,导致数据不一致。
- 数据丢失:如果在脑裂问题发生期间,集群中的某些节点发生故障或宕机,可能会导致数据丢失。
为了防止Elasticsearch集群中的脑裂问题,可以采取以下措施:
(1) 主节点选举机制
- Zen Discovery模块:Elasticsearch使用Zen Discovery模块进行主节点选举,确保集群中只有一个主节点管理集群元数据。
- 仲裁节点数配置:合理配置discovery.zen.minimum_master_nodes,这个参数用于定义在选举主节点时,集群中必须有多少个节点被认为是活跃的,才能允许进行主节点的选举。
推荐的配置值是(N/2) + 1(向下取整),其中N是具有主节点资格的节点数。这个配置可以有效防止在网络分区时形成多个主节点。
(2) 网络配置与故障处理
①网络超时与重试机制:
- 配置网络超时(如discovery.zen.ping_timeout)和重试机制,以减少网络故障对集群的影响。
- 适当增加超时时间可以减少因网络抖动导致的误判,从而避免不必要的主节点重选。
②网络分区检测:定期进行集群健康检查,如果发现网络分区,集群会自动尝试恢复并重新连接。
③网络隔离:尽量避免将Elasticsearch集群部署在可能存在网络隔离风险的环境中,如跨数据中心部署时,要确保网络连接的稳定性和可靠性。
(3) 节点配置与负载管理
① 主节点与数据节点分离:
- 将主节点(master node)与数据节点(data node)分离,以减轻主节点的负载,提高其稳定性和响应速度。
- 可以通过配置node.master和node.data属性来实现节点的角色分离。
关于node.master和node.data属性的解释如下:一个Elasticsearch集群是由许多Node构成的,Node可以有不同的类型,通过以下配置,可以产生四种不同类型的Node:
conf/elasticsearch.yml:
node.master: true/false
node.data: true/false
四种不同类型的Node是一个node.master和node.data的true/false的两两组合。
当node.master为true时,其表示这个node是一个master的候选节点,可以参与选举。ES正常运行时只能有一个master,多于1个时会发生脑裂。
当node.data为true时,这个节点作为一个数据节点,会存储分配在该node上的shard的数据并负责这些shard的写入、查询等。
② 负载均衡:
- 在数据节点之间实现负载均衡,避免单个节点过载导致集群不稳定。
- 可以使用Elasticsearch的内置负载均衡机制或外部负载均衡器来实现。
面试官:ES在高并发下如何保证读写一致性?
Elasticsearch在高并发环境下保证读写一致性,主要通过以下几种机制来实现:
1.最终一致性模型
Elasticsearch采用最终一致性模型,这意味着在理想情况下,系统会最终达到一致性,但可能在某些情况下会有短暂的不一致,尤其是在分布式系统中发生网络分区或节点故障时。这种模型提供了高可用性和容错能力,同时降低了严格一致性带来的性能开销。
2.事务日志(Translog)
作用:记录所有对索引的更改操作,包括文档的插入、更新和删除。
写前日志(Write-Ahead Logging, WAL):当写入请求到达时,Elasticsearch首先将数据写入事务日志,然后再将其异步刷新到磁盘上的分片中。这种机制确保了在系统崩溃等异常情况下,已经提交的数据不会丢失。
持久化:事务日志的使用对于处理高并发写入请求至关重要,因为写入操作只需要写入事务日志,而不需要直接更新磁盘上的分片,因此写入性能得到了极大的提升。同时,定期将事务日志的内容写入到一个新的日志文件中,并删除旧的日志文件,以确保数据的持久化。
3.分片和副本
分片:Elasticsearch通过将数据分布在多个分片上来实现水平扩展。每个索引由一个或多个分片组成,每个分片可以独立存储和处理数据。这种分片机制有助于将写入和读取请求分散到集群的不同节点上,从而提高并发处理能力。
副本:每个分片可以有零个或多个副本。副本是分片的完整拷贝,用于提高数据的可用性和容错能力。当原始分片不可用时(例如,由于节点故障),副本可以接管处理请求。通过合理配置分片和副本的数量,可以在集群中平衡负载,进一步提高并发处理能力。
4.乐观并发控制
版本号:Elasticsearch在每个文档上维护版本号。每当文档被更新时,该版本号就会增加。
写入操作:当写入操作请求使用一个特定版本时,Elasticsearch会检查当前存储的版本与请求的版本是否匹配。如果匹配,则执行更新操作;如果不匹配,则返回版本冲突错误。
冲突处理:如果两个并发请求试图更新同一个文档,只有第一个请求会成功,第二个请求会收到一个版本冲突错误。应用程序可以根据业务逻辑对这些冲突进行处理,比如重试或者合并数据。
5.写入一致性和读取一致性控制
写入一致性:通过设置write consistency,可以要求在写操作时,必须等待多少个分片副本确认成功才能返回。这可以提高数据的可靠性,但可能会增加延迟。例如:
- quorum:等待多数副本确认。
- all:等待所有副本确认。
读取一致性:通过设置search consistency,可以保证读取到的数据是某个时间点的一致视图。例如:
- 使用refresh机制,确保查询时能够看到刚刚写入的数据。
- 在分页查询时,可以使用search_after进行基于游标的查询,以避免由于分页查询中的数据变化导致的不一致问题。