(十七):ElasticSearch原理
1、Elasticsearch原理概述
分布式架构:Elasticsearch是一个分布式系统,隐藏了复杂的处理机制,使得各个节点能够独立地提供搜索服务。每个节点(包括主节点)都可以接收请求并将它们转发到正确处理的节点上。
分片机制:ElasticSearch通过分片技术实现了水平拓展和高可用性。每个分片可以是单个节点的一部分,也可以跨越多个节点。每个分片包含一部分数据,并且每个分片都有一个主分片和一个或多个复制分片。主分片负责处理写入操作,而复制分片用于容错和读取操作。
再平衡机制:当节点加入或退出集群时,ElasticSearch会根据机器的负载自动对索引分片进行重新分配,以确保数据的一致性和可靠性。
节点对等:每个节点都能够接收请求并进行转发,因此每个节点都需要其他节点的存在以便完成请求的路由。
Lucene实现:ElasticSearch内部使用了Apache Lucene库来实现索引中数据的读写。Lucene提供了全文搜索的功能,允许用户快速地在大量的文档中进行查找。
Mapping和Field:在ElasticSearch中,Mapping是用来约束字段的类型,定义文档的结构,类似于数据库中的Schema。Field则是构成文档的最小单位,类似于数据库中的Column。
Recovery和Gateway:ElasticSearch会在节点加入或退出时进行数据恢复,并通过Gateway的方式将索引数据保存到内存中,并在必要时将数据持久化到本地硬盘。此外,Gateway还用于处理索引的长期持久性,如在服务器崩溃的情况下,可以通过Gateway恢复索引。
搜索过程:用户在ElasticSearch中提交数据后,这些数据会被分词并按照权重和分词结果存入数据。当用户执行搜索时,ElasticSearch会根据权重对结果进行排序和评分,然后返回结果给用户。
集成解决方案:ElasticSearch与Logstash、Kibana等其他组件一起构成了一个集成解决方案,被称为"Elastic Stack",这组工具旨在提供一个完整的数据收集、处理和分析。
2、ElasticSearch读写原理
2.1、写操作
写(Write)操作:针对文档的CRUD操作。
2.1.1、索引新文档(Create)
当用户向一个节点提交了一个索引新文档的请求,节点会计算新文档应该加入到哪个分片(shard)中。每个节点都有每个分片存储在哪个节点的信息,因此协调节点会将请求发送给对应的节点。这个请求只会发送给主分片,等主分片完成索引,会并行将请求发送到其所有副本分片,保证每个分片都持有最新数据。
新文档被写入内存,操作被写入translog。每次写入新文档时,都写先写入内存中,并将这一操作写入一个 tranlog 文件(transaction log)中,此时如果执行搜索操作,这个新文档还不能被索引到。
ES会每隔1秒时间(该时间可调整)进行一次刷新操作(refresh),此时在这1秒时间内写入内存的新文档都会被写入一个文件系统缓存(filesystem cache)中,并构成一个分段(segment)。此时这个 segment 里的文档可以被搜索到,但是尚未写入硬盘,即如果此时发生断电,则这些文档可能会丢失。
在执行刷新后清空内存,新文档写入文件系统缓存。
不断有新的文档写入,则这一过程将不断重复执行。每隔一秒将生成一个新的 segment,而 translog 文件将越来越大。
每隔 30 分钟或者 translog 文件变得很大,则执行一次刷盘(fsync)操作。此时所有在文件系统缓存中的 segment 将被写入磁盘,而 translog 将被删除(此后会生成新的 translog)。
由上面的流程可以看出,在两次fsync操作之间,存储在内存和文件系统缓存中的文档是不安全的,一旦出现断电这些文档就会丢失。所以ES引入了translog来记录两次fsync之间所有的操作,这样机器从故障中恢复或者重新启动,ES便可以根据translog进行还原。
translog本身也是文件,存在于内存当中,如果发生断电一样会丢失。ES会在每隔5秒时间或是一次写入请求完成后将tranlog写入磁盘,对文档的操作一旦写入磁盘便是安全的并可以复原的,只有在当前操作记录被写入磁盘,ES才会将操作成功的结果返回发送此操作请求的客户端。
由于每一秒就会生成一个新的segment,很快就会有大量的segment。对于一个分片进行查询请求,将会轮流查询分片中的所有segment,这会降低搜索效率。ES会自动启动合并segment的工作,将一部分相似大小的segment合并成一个新的大segment。
合并的过程实际上是创建了一个新的segment,当新segment被写入磁盘,所有被合并的旧segment被清除。
2.1.2、更新(Update)和删除(Delete)文档
ES的索引是不能修改的,更新和删除操作并不是直接在原索引上直接执行。
每一个磁盘上的 segment 都会维护一个 del 文件,用来记录被删除的文件。每当用户提出一个删除请求,文档并没有被真正删除,索引也没有发生改变,而是在del文件中标记该文档已被删除。因此被删除的文档依然可以被检索到,只是在返回检索结果时被过滤掉了。每次启动 segment 合并工作时,那些被标记为删除的文档会被真正删除。
更新文档会首先查找原文档,得到该文档的版本号。然后将修改后的文档写入内存,此过程与写入一个新文档相同。同时,旧版本文档被标记为删除,同理,该文档可以被搜索到,只是最终被过滤掉。
2.2、读操作
查询的过程大体上分为 查询(query) 和 取回(fetch) 两个阶段。这个节点的任务是广播查询请求到所有相关分片,并将它们的响应整合成全局排序后的结果集合,这个结果集合会返回给客户端。
2.2.1、查询阶段
当一个节点接收到一个搜索请求,则这个节点就变成了协调节点。查询过程分布式搜索:
广播请求到索引中每一个节点的分片拷贝。查询请求可以被某个主分片或某个副本分片处理,协调节点将在之后的请求中轮询所有的分片拷贝来分摊负载。
每个分片将会在本地构建一个优先级队列,如果客户端要求返回结果排序中从第from名开始的数量为size的结果集,则每个节点都需要生成一个 from+size 大小的结果集,因此优先级队列的大小也是 from+size。分片仅会返回一个轻量级的结果给协调节点,包含结果集中的每一个文档的ID和进行排序所需要的信息。
协调节点会将所有分片的结果汇总,并进行全局排序,得到最终的查询排序结果。此时查询阶段结束。
2.2.2、取回阶段
查询过程得到的是一个排序结果,标记出哪些文档是符合搜索要求的,此时仍然需要获取这些文档返回客户端。
协调节点会确定实际需要的文档,并向含有该文档的分片发送get请求;分片获取文档返回给协调节点;协调节点将结果返回给客户端。