elasticsearch入门

一. 简介

Elasticsearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java语言开发的,并作为Apache许可条款下的开放源码发布,是一种流行的企业级搜索引擎。

二. 为什么使用Elasticsearch

优点:

1.实时

2.分布式

3.搜索

4.分析

对比 mysql ,同样也能做到 (实时,分布式,搜索,分析),但是es强大之处在于模糊搜索。

对比mysql 模糊搜索,比如:

select * from table where name like '%你好%'

主要问题是

1.模糊查询不走索引,当数据量非常大的时候,查询将非常慢,都是秒级别。

2.查询内容不精确,只能匹配到 xx你好xx的内容,当内容为 你x好的时候无法匹配到。

而es就能很好解决以上问题。

1.Elasticsearch对模糊搜索非常擅长(搜索速度很快)

2.从Elasticsearch搜索到的数据可以根据评分过滤掉大部分的,只要返回评分高的给用户就好了(原生就支持排序)

3.没有那么准确的关键字也能搜出相关的结果(能匹配有相关性的记录)

三. 倒排索引

在没有搜索引擎时,我们是直接输入一个网址,然后获取网站内容,这时我们的行为是:

document -> to -> words

通过文章,获取里面的单词,此谓「正向索引」,forward index.

后来,我们希望能够输入一个单词,找到含有这个单词,或者和这个单词有关系的文章:

word -> to -> documents

于是我们把这种索引,成为inverted index

如图所示:

Elasticsearch会根据分词器对我们的那段文字进行分词(也就是图上所看到的Ada/Allen/Sara..),这些分词汇总起来我们叫做Term Dictionary,而我们需要通过分词找到对应的记录,这些文档ID保存在PostingList。

在Term Dictionary中的词由于是非常非常多的,所以我们会为其进行排序,等要查找的时候就可以通过二分来查,不需要遍历整个Term Dictionary。

由于Term Dictionary的词实在太多了,不可能把Term Dictionary所有的词都放在内存中,于是Elasticsearch还抽了一层叫做Term Index,这层只存储  部分   词的前缀,Term Index会存在内存中(检索会特别快)。

四. 术语

Index:Elasticsearch的Index相当于数据库的Table

Document:Document相当于数据库的一行记录

Field:相当于数据库的Column的概念

Mapping:相当于数据库的Schema的概念

DSL:相当于数据库的SQL(给我们读取Elasticsearch数据的API)

mysqlelasticsearch

tableindex

row document

columnfiled

schemamapping

sqldsl


五. 集群

一个Elasticsearch集群会有多个Elasticsearch节点,所谓节点实际上就是运行着Elasticsearch进程的机器。


在众多的节点中,其中会有一个Master Node,它主要负责维护索引元数据、负责切换主分片和副本分片身份等工作(后面会讲到分片的概念),如果主节点挂了,会选举出一个新的主节点。

Master节点的主要职责是和集群操作相关的内容,例如创建或删除索引、跟踪哪些节点是集群的一部分,并决定哪些分片分配给相关的节点。

稳定的主节点对集群的健康是非常重要的。默认情况下任何一个集群中的节点都有可能被选为主节点。

索引数据和搜索查询等操作会占用大量的CPU、内存、IO资源,为了确保一个集群的稳定,分离主节点和数据节点是一个比较好的选择。

六.分片

Elasticsearch最外层的是Index(相当于数据库 表的概念);一个Index的数据我们可以分发到不同的Node上进行存储,这个操作就叫做分片

比如上图集群里边有4个节点,现在有一个Index,想将这个Index在4个节点上存储,那我们可以设置为4个分片。这4个分片的数据合起来就是Index的数据。

为什么要分片?

1.如果一个Index的数据量太大,只有一个分片,那只会在一个节点上存储,随着数据量的增长,一个节点未必能把一个Index存储下来。

2.多个分片,在写入或查询的时候就可以并行操作(从各个节点中读写数据,提高吞吐量)

七. 副本

通过分片 将数据分散到各个节点中,此时如果其中一个节点挂了,数据就会存在丢失的问题。此时副本就能很好的解决这个问题。所以分片会有主分片和副本分片之分(为了实现高可用

数据写入的时候是写到主分片,副本分片会复制主分片的数据,读取的时候主分片和副本分片都可以读

Index需要分为多少个主分片和副本分片都是可以通过配置设置的


如果某个节点挂了,前面所提高的Master Node就会把对应的副本分片提拔为主分片,这样即便节点挂了,数据就不会丢。

八.  数据写入流程

客户端写入一条数据,到Elasticsearch集群里边就是由节点来处理这次请求:


集群上的每个节点都是coordinating node(协调节点),协调节点表明这个节点可以做路由。比如节点1接收到了请求,但发现这个请求的数据应该是由节点2处理(因为主分片在节点2上),所以会把请求转发到节点2上。

coodinate(协调)节点通过hash算法可以计算出是在哪个主分片上,然后路由到对应的节点

shard = hash(document_id) % (num_of_primary_shards)

路由到对应的节点以及对应的主分片时,会做以下的事:

1. 将数据写到内存缓存区

2. 然后将数据写到translog缓存区

3. 每隔1s数据从buffer中refresh到FileSystemCache中,生成segment文件,一旦生成segment文件,就能通过索引查询到了

4. refresh完,memory buffer就清空了。

5. 每隔5s中,translog 从buffer flush到磁盘中

6. 定期/定量从FileSystemCache中,结合translog内容flush index到磁盘中。


具体描述:

1.Elasticsearch会把数据先写入内存缓冲区,然后每隔1s刷新到文件系统缓存区(当数据被刷新到文件系统缓冲区以后,数据才可以被检索到)。所以:Elasticsearch写入的数据需要1s才能查询到。

2.为了防止节点宕机,内存中的数据丢失,Elasticsearch会另写一份数据到日志文件上,但最开始的还是写到内存缓冲区,每隔5s才会将缓冲区的刷到磁盘中。所以:Elasticsearch某个节点如果挂了,可能会造成有5s的数据丢失

3.等到磁盘上的translog文件大到一定程度或者超过了30分钟,会触发commit操作,将内存中的segement文件异步刷到磁盘中,完成持久化操作。

总结:

写内存缓冲区(定时去生成segement,生成translog),能够让数据能被索引、被持久化。最后通过commit完成一次的持久化。

等主分片写完了以后,会将数据并行发送到副本集节点上,等到所有的节点写入成功就返回ack给协调节点,协调节点返回ack给客户端,完成一次的写入。

九. 数据更新和删除

给对应的doc记录打上.del标识,如果是删除操作就打上delete状态,如果是更新操作就把原来的doc标志为delete,然后重新新写入一条数据。

上面提到,每隔1s会生成一个segement 文件,那segement文件会越来越多越来越多。Elasticsearch会有一个merge任务,会将多个segement文件合并成一个segement文件。

在合并的过程中,会把带有delete状态的doc给物理删除掉。

十.  查询过程

查询最简单的方式可以分为两种:

1.根据ID查询doc

2.根据query(搜索词)去查询匹配的doc

根据ID去查询具体的doc流程:

1.检索内存的Translog文件

2. 检索硬盘的Translog文件

3. 检索硬盘的Segement文件

根据query(搜索词)去查询匹配的doc

1.同时去查询内存和硬盘的Segement文件


Get(通过ID去查Doc是实时的),Query(通过query去匹配Doc是近实时的) 原因: segement文件是每隔一秒才生成一次的

Elasticsearch查询又分可以为三个阶段:

1.  QUERY_AND_FETCH(查询完就返回整个Doc内容)

2.  QUERY_THEN_FETCH(先查询出对应的Doc id ,然后再根据Doc id 匹配去对应的文档)

3.  DFS_QUERY_THEN_FETCH(先算分,再查询) 分:  词频率和文档的频率(Term Frequency、Document Frequency),出现频率越高,相关性就更强


QUERY_AND_FETCH

只适合于只需要查一个分片的请求。

QUERY_THEN_FETCH

一般使用最多就是该查询方式。具体流程如下:

1.客户端请求发送到集群的某个节点上。集群上的每个节点都是coordinate node(协调节点)

2.然后协调节点将搜索的请求转发到所有分片上(主分片和副本分片都行)

3.每个分片将自己搜索出的结果(doc id)返回给协调节点,由协调节点进行数据的合并、排序、分页等操作,产出最终结果。

4.接着由协调节点根据doc id去各个节点上拉取实际的document数据,最终返回给客户端。

Query 阶段时节点做的事情:

1.协调节点向目标分片发送查询的命令(转发请求到主分片或者副本分片上)

2.数据节点(在每个分片内做过滤、排序等等操作),返回doc id给协调节点

Fetch 阶段时节点做的事情:

1.协调节点得到数据节点返回的doc id,对这些doc id做聚合,然后将目标数据分片发送抓取命令(希望拿到整个Doc记录)

2.数据节点按协调节点发送的doc id,拉取实际需要的数据返回给协调节点

总结:

Elasticsearch是分布式的,所以需要从各个节点都拉取对应的数据,然后最终统一合成给客户端

你可能感兴趣的:(elasticsearch入门)