ElasticSearch学习笔记之原理介绍

ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并做为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,可以达到实时搜索,稳定,可靠,快速,安装使用方便。node

揭面:python

架构图:web

架构各模块介绍:算法

Lucence Directory:是lucene的框架服务发现以及选主 ZenDiscovery: 用来实现节点自动发现,还有Master节点选取,假如Master出现故障,其它的这个节点会自动选举,产生一个新的Master;数据库

Plugins:插件能够经过自定的方式扩展增强Elasticsearch的基本功能,好比能够自定义类型映射,分词器,本地脚本,自动发现等;缓存

Scripting:使用脚本语言能够计算自定义表达式的值,好比计算自定义查询相关度评分。支持的脚本语言有groovy,js,mvel(1.3.0废弃),python等;安全

Disovery:该模块主要负责集群中节点的自动发现和Master节点的选举。节点之间使用p2p的方式进行直接通讯,不存在单点故障的问题。Elasticsearch中,Master节点维护集群的全局状态,好比节点加入和离开时进行shard的从新分配;服务器

River:表明es的一个数据源,也是其它存储方式(如:数据库)同步数据到es的一个方法。它是以插件方式存在的一个es服务,经过读取river中的数据并把它索引到es中;架构

Gateway:模块用于存储es集群的元数据信息;app

Zen Discovery:zen发现机制是elasticsearch默认的内建模块。它提供了多播和单播两种发现方式,可以很容易的扩展至云环境。zen发现机制是和其余模块集成的,例如全部节点间通信必须用trasport模块来完成。

核心概念:

集群(Cluster):ES集群是一个或多个节点的集合,它们共同存储了整个数据集,并提供了联合索引以及可跨全部节点的搜索能力。多节点组成的集群拥有冗余能力,它能够在一个或几个节点出现故障时保证服务的总体可用性。

集群靠其独有的名称进行标识,默认名称为“elasticsearch”。节点靠其集群名称来决定加入哪一个ES集群,一个节点只能属一个集群;

节点(node):一个节点是一个逻辑上独立的服务,能够存储数据,并参与集群的索引和搜索功能, 一个节点也有惟一的名字,群集经过节点名称进行管理和通讯;

主节点:主节点的主要职责是和集群操做相关的内容,如建立或删除索引,跟踪哪些节点是群集的一部分,并决定哪些分片分配给相关的节点。稳定的主节点对集群的健康是很是重要的。虽然主节点也能够协调节点,路由搜索和从客户端新增数据到数据节点,但最好不要使用这些专用的主节点。一个重要的原则是,尽量作尽可能少的工做。

对于大型的生产集群来讲,推荐使用一个专门的主节点来控制集群,该节点将不处理任何用户请求。

数据节点:持有数据和倒排索引。

客户端节点:它既不能保持数据也不能成为主节点,该节点能够响应用户的状况,把相关操做发送到其余节点;客户端节点会将客户端请求路由到集群中合适的分片上。对于读请求来讲,协调节点每次会选择不一样的分片处理请求,以实现负载均衡。

部落节点:部落节点能够跨越多个集群,它能够接收每一个集群的状态,而后合并成一个全局集群的状态,它能够读写全部节点上的数据。

索引(Index): ES将数据存储于一个或多个索引中,索引是具备相似特性的文档的集合。类比传统的关系型数据库领域来讲,索引至关于SQL中的一个数据库,或者一个数据存储方案(schema)。索引由其名称(必须为全小写字符)进行标识,并经过引用此名称完成文档的建立、搜索、更新及删除操做。一个ES集群中能够按需建立任意数目的索引。

文档类型(Type):类型是索引内部的逻辑分区(category/partition),然而其意义彻底取决于用户需求。所以,一个索引内部可定义一个或多个类型(type)。通常来讲,类型就是为那些拥有相同的域的文档作的预约义。例如,在索引中,能够定义一个用于存储用户数据的类型,一个存储日志数据的类型,以及一个存储评论数据的类型。类比传统的关系型数据库领域来讲,类型至关于“表”。

文档(Document) :文档是Lucene索引和搜索的原子单位,它是包含了一个或多个域的容器,基于JSON格式进行表示。文档由一个或多个域组成,每一个域拥有一个名字及一个或多个值,有多个值的域一般称为“多值域”。每一个文档能够存储不一样的域集,但同一类型下的文档至应该有某种程度上的类似之处。至关于数据库的“记录”

Mapping: 至关于数据库中的schema,用来约束字段的类型,不过 Elasticsearch 的 mapping 能够自动根据数据建立。

ES中,全部的文档在存储以前都要首先进行分析。用户可根据须要定义如何将文本分割成token、哪些token应该被过滤掉,以及哪些文本须要进行额外处理等等。

分片(shard) :ES的“分片(shard)”机制可将一个索引内部的数据分布地存储于多个节点,它经过将一个索引切分为多个底层物理的Lucene索引完成索引数据的分割存储功能,这每个物理的Lucene索引称为一个分片(shard)。

每一个分片其内部都是一个全功能且独立的索引,所以可由集群中的任何主机存储。建立索引时,用户可指定其分片的数量,默认数量为5个。

Shard有两种类型:primary和replica,即主shard及副本shard。

Primary shard用于文档存储,每一个新的索引会自动建立5个Primary shard,固然此数量可在索引建立以前经过配置自行定义,不过,一旦建立完成,其Primary shard的数量将不可更改。

Replica shard是Primary Shard的副本,用于冗余数据及提升搜索性能。

每一个Primary shard默认配置了一个Replica shard,但也能够配置多个,且其数量可动态更改。ES会根据须要自动增长或减小这些Replica shard的数量。

ES集群可由多个节点组成,各Shard分布式地存储于这些节点上。

ES可自动在节点间按须要移动shard,例如增长节点或节点故障时。简而言之,分片实现了集群的分布式存储,而副本实现了其分布式处理及冗余功能。

建立索引:

过程:当分片所在的节点接收到来自协调节点的请求后,会将该请求写入translog,并将文档加入内存缓存。若是请求在主分片上成功处理,该请求会并行发送到该分片的副本上。当translog被同步到所有的主分片及其副本上后,客户端才会收到确认通知。

内存缓冲会被周期性刷新(默认是1秒),内容将被写到文件系统缓存的一个新段(segment)上。虽然这个段并无被同步(fsync),但它是开放的,内容能够被搜索到。

每30分钟,或者当translog很大的时候,translog会被清空,文件系统缓存会被同步。这个过程在Elasticsearch中称为冲洗(flush)。在冲洗过程当中,内存中的缓冲将被清除,内容被写入一个新段。段的fsync将建立一个新的提交点,并将内容刷新到磁盘。旧的translog将被删除并开始一个新的translog。

ES如何作到实时检索?

因为在buffer中的索引片先同步到文件系统缓存,再刷写到磁盘,所以在检索时能够直接检索文件系统缓存,保证了实时性。

这一步刷到文件系统缓存的步骤,在 Elasticsearch 中,是默认设置为 1 秒间隔的,对于大多数应用来讲,几乎就至关因而实时可搜索了。

不过对于 ELK 的日志场景来讲,并不须要如此高的实时性,而是须要更快的写入性能。咱们能够经过 /_settings接口或者定制 template 的方式,加大 refresh_interval 参数。

当segment从文件系统缓存同步到磁盘时发生了错误怎么办? 数据会不会丢失?

因为Elasticsearch 在把数据写入到内存 buffer 的同时,其实还另外记录了一个 translog日志,若是在这期间故障发生时,Elasticsearch会从commit位置开始,恢复整个translog文件中的记录,保证数据的一致性。

等到真正把 segment 刷到磁盘,且 commit 文件进行更新的时候, translog 文件才清空。这一步,叫作flush。一样,Elasticsearch 也提供了 /_flush 接口。

索引数据的一致性经过 translog 保证,那么 translog 文件本身呢?

Elasticsearch 2.0 之后为了保证不丢失数据,每次 index、bulk、delete、update 完成的时候,必定触发刷新translog 到磁盘上,才给请求返回 200 OK。这个改变在提升数据安全性的同时固然也下降了一点性能

检索文档:

搜索相关性

相关性是由搜索结果中Elasticsearch打给每一个文档的得分决定的。默认使用的排序算法是tf/idf(词频/逆文档频率)。词频衡量了一个词项在文档中出现的次数 (频率越高 == 相关性越高),逆文档频率衡量了词项在所有索引中出现的频率,是一个索引中文档总数的百分比(频率越高 == 相关性越低)。最后的得分是tf-idf得分与其余因子好比(短语查询中的)词项接近度、(模糊查询中的)词项类似度等的组合

更新删除索引:

删除和更新也都是写操做。可是Elasticsearch中的文档是不可变的,所以不能被删除或者改动以展现其变动。那么,该如何删除和更新文档呢?

磁盘上的每一个段都有一个相应的.del文件。当删除请求发送后,文档并无真的被删除,而是在.del文件中被标记为删除。该文档依然能匹配查询,可是会在结果中被过滤掉。当段合并(咱们将在本系列接下来的文章中讲到)时,在.del文件中被标记为删除的文档将不会被写入新段。

接下来咱们看更新是如何工做的。在新的文档被建立时,Elasticsearch会为该文档指定一个版本号。当执行更新时,旧版本的文档在.del文件中被标记为删除,新版本的文档被索引到一个新段。旧版本的文档依然能匹配查询,可是会在结果中被过滤掉。

物理删除索引:当索引数据不断增加时,对应的segment也会不断的增多,查询性能可能就会降低。所以,Elasticsearch会触发segment合并的线程,把不少小的segment合并成更大的segment,而后删除小的segment,当这些标记为删除的segment不会被复制到新的索引段中。

Elasticseach查询:

Elasticseach查询分为两种,结构化查询和全文查询;

尽管统一称之为query DSL,事实上Elasticsearch中存在两种DSL:查询DSL(query DSL)和过滤DSL(filter DSL)。

查询子句和过滤子句的天然属性很是相近,但在使用目的上略有区别。

简单来说,当执行full-text查询或查询结果依赖于相关度分值时应该使用查询DSL,当执行精确值(extac-value)查询或查询结果仅有“yes”或“no”两种结果时应该使用过滤DSL。

Filter DSL计算及过滤速度较快,且适于缓存,所以可有效提高后续查询请求的执行速度。而query DSL不只要查找匹配的文档,还须要计算每一个文件的相关度分值,所以为更重量级的查询,其查询结果不会被缓存。

不过,得益于倒排索引,一个仅返回少许文档的简单query或许比一个跨数百万文档的filter执行起来并得显得更慢。

Elasticsearch支持许多的query和filter,但最经常使用的也不过几种。

Filter DSL中常见的有term Filter、terms Filter、range Filter、exists and missing Filters和bool Filter。

而Query DSL中常见的有match_all、match 、multi_match及bool Query。鉴于时间关系,这里再也不细述,朋友们可参考官方文档学习。

Queries用于查询上下文,而filters用于过滤上下文,不过,Elasticsearch的API也支持此两者合并运行。

组合查询可用于合并查询子句,组合过滤用于合并过滤子句,然而,Elasticsearch的使用习惯中,也常会把filter用于query上进行过滤。不过,不多有机会须要把query用于filter上的。

结构化搜索:是指查询包含内部结构的数据。日期,时间,和数字都是结构化的:它们有明确的格式给你执行逻辑操做。通常包括比较数字或日期的范围,或肯定两个值哪一个大。

文本也能够被结构化。一包蜡笔有不一样的颜色:红色,绿色,蓝色。一篇博客可能被打上 分布式 和 搜索的标签。电子商务产品有商品统一代码(UPCs) 或其余有着严格格式的标识。

经过结构化搜索,你的查询结果始终是 是或非;是否应该属于集合。结构化搜索不关心文档的相关性或分数,它只是简单的包含或排除文档。

这必须是有意义的逻辑,一个数字不能比同一个范围中的其余数字更多。它只能包含在一个范围中,或不在其中。相似的,对于结构化文本,一个值必须相等或不等。这里没有 更匹配 的概念。

所谓的全文搜索查询一般是指在给定的文本域内部搜索指定的关键字,但搜索操做该须要真正理解查询者的目的,例如:

(1) 搜索“UK”应该返回包含“United Kingdom”的相关文档;

(2) 搜索“jump”应该返回包含“JUMP”、“jumped”、“jumps”、“jumping”甚至是“leap”的文档;

为了完成此类全文搜域的搜索,ES必须首先分析文本并将其构建成为倒排索引(inverted index),倒排索引由各文档中出现的单词列表组成,列表中的各单词不能重复且须要指向其所在的各文档。

所以,为了建立倒排索引,须要先将各文档中域的值切分为独立的单词(也称为term或token),然后将之建立为一个无重复的有序单词列表。这个过程称之为“分词(tokenization)”。

其次,为了完成此类full-text域的搜索,倒排索引中的数据还需进行“正规化(normalization)”为标准格式,才能评估其与用户搜索请求字符串的类似度。

这里的“分词”及“正规化”操做也称为“分析(analysis)”。

Analysis过程由两个步骤的操做组成:首先将文本切分为terms(词项)以适合构建倒排索引,其次将各terms正规化为标准形式以提高其“可搜索度”。这两个步骤由分析器(analyzers)完成。

一个分析器一般须要由三个组件构成:字符过滤器(Character filters)、分词器(Tokenizer)和分词过滤器(Token filters)组成。

字符过滤器:在文本被切割以前进行清理操做,例如移除HTML标签,将&替换为字符等;

分词器:将文本切分为独立的词项;简单的分词器一般是根据空白及标点符号进行切分;

分词过滤器:转换字符(如将大写转为小写)、移除词项(如移除a、an、of及the等)或者添加词项(例如,添加同义词);

Elasticsearch内置了许多字符过滤器、分词器和分词过滤器,用户可按需将它们组合成“自定义”的分析器。

与SOLR比对:

三种使用方式:

相关文章
相关标签/搜索