ElasticSearch简介

ElasticSearch提供了搜索、分析、存储数据三大功能,其主要特点是:分布式、零配置、易装易用、自动发现、索引自动分片、索引副本机制、RestFul风格接口等。

ElasticSearch底层依赖于Lucene库,采用Lucene构建索引,提供搜索功能。

倒排索引

在倒排索引中, 有词条(term)、词典(term dictionary)、倒排表(post List)三个概念

词条:索引中最小的存储和查询单元,在中文语境中,一个词组通常指一个词条

词典:又称字典,是词条的集合,词典一般由网页或文章集合中出现的所有词构成的字符串集合

倒排表:倒排表记录的是词出现在哪些文档里,出现的位置和频率等

ElasticSearch基于Lucene实现的,词典与倒排表是分俩部分存储的,词典存储在内存中,倒排表存储在磁盘中

ElasticSearch核心概念

ElasticSearch核心概念有:Node、Cluster、Shards、Replicas、Index、Type、Document、Settings、Mapping和Analyzer

  • Node(节点):是组成ElasticSearch集群的基本服务单元,集群中运行的ElasticSearch服务器都称为节点。

    节点的状态有(红、绿、黄)三种状态

  • Cluster(集群):有一个或多个节点组成,各个节点协同工作,共享数据。同一集群内节点名称不能重复,但集群名称一定要相同

  • Shards(分片):索引的数据量太大时,受限于单个节点的内存、磁盘处理能力等。将一个索引上的数据进行水平拆分,拆分出来的数据部分称为一个分片。一般每个分片放在不同的服务器上

​ 底层实际上每个分片是Lucene中的一个索引文件,因此一个分片有一个主分片和0到多个副本分片

​ ElasticSearch进行索引时,是对多个分片信息进行索引后进行汇总,则分片一旦设置则不可更改,默认是5个分片,索引写入数据时,是通过路由来确定具体写入哪个分片的

  • Replicas(备份):也称为副本,指对主分片进行备份,ElasticSearch构建索引时,先在主分片完成数据的索引,然后数据会从主分片分发备份分片上进行索引
  • Index(索引):ElasticSearch中索引由一个和多个分片组成,使用索引时,需要通过索引名称在集群中进行唯一标识
  • Type(类别):索引内部逻辑分区,后面会取消Type
  • Document(文档):索引中每一条数据叫做一个文档,一个文档通过_id在索引中进行唯一标识。
  • Settings:对集群中索引定义信息,比如一个索引的分片数、副本数等
  • Mapping:Mapping中保存定义索引中字段(Field)的存储类型,分词方式、是否存储等信息,类型数据库中的Schema
  • Analyzer:Analyzer表示的是字段分词方式的定义,一个Analyzer通常由一个Tokenizer和零到多个Filter组成。默认的标准的Analyzer包含一个标准的Tokenizer和三个Filter、即Standard Token Filter、Lower case Token Filter和Stop Token Filter

ElasticSearch架构

ElasticSearch架构

ElasticSearch架构自底向上分为五层,分别为核心层、数据处理层、发现与脚本层、协议层和应用层。

:japanese_ogre:在ElasticSearch内部,通过集群中配置一个相同的集群名称,就能将不同的节点连接到一个集群中,这是通过ElasticSearch节点自动发现机制实现的

分片与路由

ElasticSearch对文档的新建、索引和删除请求等写操作,必须在主分片上面完成之后才能被复制到相关的副本分片。Elasticsearch为了加快写入的速度,写入过程往往是并发实施的。为了解决在并发写的过程中出现的数据冲突的问题,Elasticsearch通过乐观锁进行控制,每个文档都有一个version (版本号),当文档被修改时版本号递增。Elasticsearch引入了路由功能,即数据在写入时,通过路由将数据写入指定分片Elasticsearch默认会搜索所有分片上的数据,最后在主节点上汇总各个分片数据并进行排序处理后,返回最终的结果数据。

”段“是Elasticsearch从Lucene中继承的概念。在索引中,索引文件被拆分为多个子文件,其中每个子文件就叫做段,每个段都是一个 倒排索引的小单元。

段具有不变性,一旦索引的数据被写入硬盘,就不能再修改。

:question:为什么要引入分段呢

如果全部文档集合仅构建在一个很大的倒排索引文件中,且数据量还在不断增加,当进行修改时,我们需要全量更新当前的倒排索引文件,这会使得数据更新时效性很差,且耗费大量资源,显然这不是我们希望的。其实在Lucene中,分段的存储模式可以避免在读写操作时使用锁,从而大大提升Elasticsearch的读写性能。这有点类似CurrentHashMap中“分段锁”的概念,俩者都是为了减少锁的使用,提高并发。

提交点

当分段被写入磁盘后会生成一个提交点,提交点意味着一个用来记录所有段信息的文件已经生成。因此,一个段一旦拥有了提交点,就表示从此该段仅有读的权限,永远失去了写的权限。
当段在内存中时,此时分段拥有只写的权限,数据还会不断写入,而不具备读数据的权限,意味着这部分数据不能被Elasticsearch用户检索到。
那么,既然索引文件分段存储并且不可修改,那么新增、更新和删除如何处理呢?
其实新增是比较容易处理的。既然数据是新的,那么只需在当前文档新增一个段即可。
删除数据时,由于分段不可修改的特性,Elasticsearch不会把文档从旧的段中移除,因而是新增一个.del文件,.del文件中会记录这些被删除文档的段信息。被标记删除的文档仍然可以被查询匹配到,但它会在最终结果被返回前通过.del文件将其从结果集中移除。
当更新数据时,由于分段不可修改的特性,Elasticsearch无法通过修改旧的段来反映文档的更新,于是,更新操作变成了两个操作的结合,即先删除、后新增。Elasticsearch会将旧的文档从.del文件中标记删除,然后将文档的新版本索引到一个新的段中。在查询数据时,两个版本的文档都会被一个查询匹配到,但被删除的旧版本文档在结果集返回前就会被移除。
综上所述,段作为不可修改是具有一定优势的,段的优势主要表现在:不需要锁,从而提升Elasticsearch的读写性能。

段合并

Elasticsearch引入段合并机制。段合并机制在后台定期进行,从而小的段被合并到大的段,然后这些大的段再被合并到更大的段。
在段合并过程中,Elasticsearch会将那些旧的已删除文档从文件系统中清除。被删除的文档不会被拷贝到新的大段中,当然,在合并的过程中不会中断索引和搜索。
段合并是自动进行索引和搜索的,在合并进程中,会选择一小部分大小相似的段,在后台将它们合并到更大的段中,这些段既可以是未提交的,也可以是已提交的。
在合并结束后,老的段会被删除,新的段被Flush到磁盘,同时写入一个包含新段且排除旧的和较小的段的新提交点。打开新的段之后,可以用来搜索。
由于段合并的计算量较大,对磁盘I/O的消耗也较大,因此段合并会影响正常的数据写入速率,因此Elasticsearch不会放任自流,让段合并影响搜索性能。Elasticsearch在默认情况下会对合并流程进行资源限制,这就是搜索服务仍然有足够的资源仍然可以执行的原因。

事务日志机制

Elasticsearch引入事务日志(Translog)机制。事务日志用于记录所有还没有持久化到磁盘的数据。
于是,在添加了事务日志机制后,数据写入索引的流程如下所示。
(1)新文档被索引之后,先被写入内存中。为了防止数据丢失,Elasticsearch会追加一份数据到事务日志中。
(2)新的文档持续在被写入内存时,同时也会记录到事务日志中。当然,此时的新数据还不能被检索和查询。
(3)当达到默认的刷新时间或内存中的数据达到一定量后,Elasticsearch会触发一次刷新,将内存中的数据以一个新段形式刷新到文件缓存系统中并清空内存。这时新段虽未被提交到磁盘,但已经可以对外提供文档的检索功能且不被修改。
(4)随着新文档索引不断被写入,当日志数据大小超过某个值(如512MB),或者超过一定时间(如30 min)时,Elasticsearch会触发一次Flush。
此时,内存中的数据被写入一个新段,同时被写入文件缓存系统,文件缓存系统中的数据通过Fsync刷新到磁盘中,生成提交点。而日志文件被删除,创建一个空的新日志。

高级客户端

高级客户端基于初级客户端来实现。
高级客户端的主要目标是公开特定的API方法,这些API方法将接收请求作为参数并返回响应结果,以便由客户端本身处理请求和响应结果。

高级客户端也有同步、异步两种API调用方式。其中,以同步调用方式调用后直接返回响应对象,而异步调用方式则需要配置一个***参数才能调用,该参数在收到响应或错误后会得到相应的结果通知。

高级客户端文档相关API

在Elasticsearch中,高级客户端支持以下文档相关的API:
(1)Single document APIs——单文档操作API。
(2)Index API——文档索引API。
(3)Get API——文档获取API。
(4)Exists API——文档存在性判断API。
(5)Delete API——文档删除API。
(6)Update API——文档更新API。
(7)Term Vectors API——词向量API。
(8)Bulk API——批量处理API。
(9)Multi-Get API——多文档获取API。
(10)ReIndex API——重新索引API。
(11)Update By Query API——查询更新API。
(12)Delete By Query API——查询删除API。
(13)Multi Term Vectors API——多词条向量API。

文档索引

Elasticsearch是面向文档的,它可以存储整个文档。
但Elasticsearch对文档的操作不仅限于存储,Elasticsearch还会索引每个文档的内容使之可以被搜索。用户可以对文档数据进行索引、搜索、排序和过滤等操作

构建Json文档:1、String构建 2、Map构建 3、利用Jackson序列化Java bean构建 4、使用内置的帮助类XContentFactory.jso

IndexReques:构建文档请求----->构建文档响应

IndexRequest中,除三个参数外(index-type-id),还有一些可选参数。可选参数包含路由、超时时间、版本、版本类型和索引管道名称等。

文档搜索查询

在执行文档索引查询请求前,需要构建文档索引查询请求,即GetRequest。GetRequest有两个必选参数,即索引名称和文档ID

删除文档索引

在执行删除文档索引请求前,需要构建删除文档索引请求,即DeleteRequest。在DeleteRequest中有两个必选参数,即索引名称和文档ID

更新文档索引

在执行更新索引文档请求前,需要构建更新文档索引请求,即UpdateRequest。UpdateRequest有两个必选参数,即索引名称和文档ID

文档处理过程解析

写入磁盘的倒排索引是不可变的。

Lucene中的索引其实是ElasticSearch中的分片,ElasticSearch中的索引就是分片的集合。当ElasticSearch搜索索引时,它发送查询请求给该索引下的所有分片,然后过滤这些结果,最后聚合成全局的结果。

为了避免混淆,Elasticsearch引入了per-segment search的概念。一个段(segment)就一个是有完整功能的倒排索引。Lucene中的索引指的是段的集合,再加上提交点(commit point,包括所有段的文件)。新的文档在被写入磁盘的段之前,需要先写入内存区的索引。
一个per-segment search的工作流程如下所示:
(1)新的文档首先被写入内存区的索引。
(2)内存中的索引不断被提交,新段不断产生。当新的提交点产生时就将这些新段的数据写入磁盘,包括新段的名称。
写入磁盘是文件同步写入的,也就是说,所有的写操作都需要等待文件系统内存的数据同步到磁盘,确保它们可以被物理写入。
(3)新段被打开,于是它包含的文档就可以被检索到。
(4)内存被清除,等待接收新的文档。
当一个请求被接收,所有段依次被查询时。所有段上的term统计信息会被聚合,确保每个term和文档的相关性被正确计算。通过这种方式,新的文档就能够以较小的代价加入索引。
段是不可变的,那么Elasticsearch是如何删除和更新文档数据的呢?
段的不可变特性,意味着文档既不能从旧的段中移除,旧的段中的文档也不能被更新。于是Elasticsearch在每一个提交点都引入一个.del文件,包含了段上已经被删除的文档。
当一个文档被删除时,它实际上只是在.del文件中被标记为删除。在进行文档查询时,被删除的文档依然可以被匹配查询,但是在最终返回之前会从结果中删除。
当一个文档被更新时,旧版本的文档会被标记为删除,新版本的文档在新的段中被索引。当对文档进行查询时,该文档的不同版本都会匹配一个查询请求,但是较旧的版本会从结果中被删除。
被删除的文件越积累越多,每个段消耗的如文件句柄、内存、CPU等资源越来越大。如果每次搜索请求都需要依次检查每个段,则段越多,查询就越慢。这些势必会影响Elasticsearch的性能,那么Elasticsearch是如何处理的呢?Elasticsearch引入了段合并段。在段合并时,我们会展示被删除的文件是如何从文件系统中清除的。
Elasticsearch通过后台合并段的方式解决了上述问题,在段合并过程中,小段被合并成大段,大段再合并成更大的段。在合并段时,被删除的文档不会被合并到大段中。
在索引过程中,refresh会创建新的段,并打开它。合并过程是在后台选择一些小的段,把它们合并成大的段。在这个过程中不会中断索引和搜索。当新段合并后,即可打开供搜索;而旧段会被删除。

批量请求

BulkRequest可用于通过单次请求执行多个操作请求,如文档索引、文档更新、文档删除等操作。

优质文章