一篇搞懂ElasticSearch(附学习脑图)

5,986 阅读12分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动

既然你点进来了,说明你了解过ES或者是对ES感兴趣,这一篇目的在于扫盲,主要以概念理解为主,可能会比较枯燥,但是天将降大任于斯人也,必先...

这篇我以ElasticSearch是什么、底层原理、特点和应用场景三部分来让大家入门ElasticSearch

​文章末尾白嫖es学习脑图,要个关注不过分吧?

了解ElasticSearch

先看看排名,很强的位置吧,学起来,让你薪资翻啊翻,一个月因为学会了一门技术多领个几千块薪资难道不香吗?

ElasticSearch,大家可能都是听说过它是个用于做搜索的,也有可能是可能没听过,不知道大家对它的认知达到什么程度呢?如果你是没听说过或者是只是了解,这篇文章正好适合你,带你真正学习ElasticSearch,如果你用的比较多,也可以读读,查漏补缺,废话少说,我们开始吧

1、ElasticSearch是什么?

ElasticSearch是一个实时的分布式存储、搜索和分析的引擎

Elasticsearch is a real-time, distributed storage, search, and analytics engine

什么是搜索引擎?所谓搜索引擎,就是根据用户需求和一定的算法,运用特定策略从互联网检索出制定信息反馈给用户的一种搜索技术

国内搜索引擎有百度、360、搜狗等,国外的有谷歌、雅虎、Yandex这些

ElasticSearch是用Java语言编写的,基于Restful接口的,使用Json格式存储数据(属于文档存储)的一款分布式全文检索框架。千言万语不如一张图,这是es和mysql的对比(大家应该对mysql很熟悉了吧!)

**索引index:**可以把索引index比作mysql中的数据库,索引名称必须为小写,索引是一个逻辑命名空间映射到一个或多个主要的分片,可以有零个或多个副本分片

**类型type:**把类型type比作比作mysql中的一张表,但是从es6.0版本默认type是log,后续版本将不再使用type这个概念

**文档document:**可以被检索的最小单元,类似于数据库mysql中的一条记录,可以包含多个字段,使用json格式和服务端交互

除了上面三个主要的,还有一些ElasticSearch中的名词,一起理解下

**字段Field:**类似于mysql中的column,文档中包含的一组字段或者是键值对,字段的值可以是一个简单的(标量)值(如字符串,整数,日期),或者一个嵌套的结构就像一个数组或对象

**映射Mapping:**像是mysql中的模式定义,每个索引有一个映射,定义了索引中各个Field的类型,映射可以自己定义,也可以自动生成

**DSL:**相当于数据库的SQL,可用来查询读取数据

**集群Cluster:**一个集群包含一个或多个分配了相同的集群名称的节点。每个集群都有一个主节点是集群自动选择产生,并且可以决定如果当前主节点失败,哪些可以替换

**节点Node:**节点是属于elasticsearch群集的运行实例。测试的时候,在一台服务器可以启动多个节点,但通常情况下应该在一台服务器运行一个节点。在启动时,节点将使用单播(或组播,但是必须指定)来发现使用相同的群集名称的群集,并会尝试加入集群

**切片Shards:**即把一个大文件分割成多个小文件然后分散到集群中的多个节点上,可以类比mysql中的分库和分表,这样做好处就是可以把索引较大的数据分散到多台服务器上,减少压力,可以调动整个集群的资源,处理效率也会提高,默认情况下es会将用户的index拆分成5个shard,也可以在创建索引的时候通过number_of_shards参数指定shard的数量(注意:索引一旦创建,shard值是不可变的)

**副本Replica****s:**即某个文件的拷贝,就是备份数据,两个文件一模一样,保证数据不会因为误删而导致丢失,查询的时候两个都可以查看,也可以提高查询效率

replica是相对与shard而言的,一般成对使用,比如你有一个索引,shard设置为5,replica设置为1,那么总的切片数为shard(5) + shard(5) * replicas(1) = total(10);如果有5台data节点,每台节点上都会存储两个不相同的shard,这样某台data节点坏掉集群能从其它节点上保存了整个index的5个shard,所以不影响正常使用;一旦有新的节点加入,集群可以从其它节点将shard再次存储在该节点,从而保证集群高可用性

replica可在index创建后更改,其值越大搜索效率越高,但写入性能越低(一条数据写入操作需要做(1+replicas)遍),具体值与集群data节点数量相关,不宜超过【data节点数-1】

2、ElasticSearch底层原理

我们可能听过es底层是采用Lucene设计的,也听过倒排索引这种名词,或许你也可能听过什么分词、中文分词器这些,到底怎么一回事呢?

接下来我们从倒排索引、分词这两部分来了解es到底是如何设计的

倒排索引VS正排索引

举一个例子,现在有ID为1、2、3、4的四个文档

ID

VALUE

1

一个程序员

2

一个公众号程序控

3

程序员浏览程序控的文章

4

程序员关注公众号程序控

我们有上面几条数据,如果是正排索引存储会以ID作为索引,来查询相应的数据,假如我想查询含有程序控的数据,底层需要遍历所有的数据,判断是否符合标准,如果数据量很大,则会导致经常性的全表扫描,有人是不是要说,我把这个字段设置成索引就可以加速查询了?

告诉你不是的,你想想在mysql中我要是用like进行模糊查询一定会走索引吗,不一定,如果你用前导模糊查询"%程序控"这种则不会走索引,如果用非前导模糊查询"程序控%"则会走索引,你可以去用explain去实践下,实践出真知

正排索引会导致全表扫描,效率低下,于是倒排索引登场了,还是看上面例子,就会变成

词条

ID

一个

1、2

程序员

1、3、4

关注

4

浏览

3

公众号

2、3、4

程序控

2、3、4

3

文章

3

我相信你应该已经明白一二了这个时候,倒排表以字或词为关键字进行索引,表中关键字所对应的记录表项记录了出现这个字或词的所有文档,一个表项就是一个字表段,它记录该文档的ID和字符在该文档中出现的位置情况

由于每个字或词对应的文档数量在动态变化,所以倒排表的建立和维护都较为复杂,但是在查询的时候由于可以一次得到查询关键字所对应的所有文档,所以效率高于正排表。在全文检索中,检索的快速响应是一个最为关键的性能,而索引建立由于在后台进行,尽管效率相对低一些,但不会影响整个搜索引擎的效率

正排索引是从文档到关键字的映射(已知文档求关键字),倒排索引是从关键字到文档的映射(已知关键字求文档)

分词

在上面的倒排索引中你可能会存在一个问题,我怎么知道它是关注、程序员、公众号这样分词的呢?为什么不能是关注程这样分词?

es里面可以指定分词器,根据大量的数据算法来对中文进行分词,让es可以更聪明的知道如何对中文分词,es默认的标准分词器对中文的分词不是很友好,会将中文词语拆分成一个个中文的汉字,因此这里引入别的中文分词器,应用最多的是ik中文分词器,而且我们也可以自己配置特定的词库

**es的数据结构
**

es会根据分词器对我们的内容进行分词,也就是上图中的Ada、Allen、Sara、Selena这些,这些分词汇总起来叫做Term Dictionary里面,每一个分词对应的文档ID则存储在PostingList中,由于Term Dictionary中的词会越来越多,所以这里会对Term Dictionary进行排序,查找的时候则根据二分法来查找,不需要遍历整个Dictionary

正是由于Dictionary中词很多,我们不能把所有词都放在内存中,于是es又加了一层Term index,这里可以存储词语的前缀,Term Index这块会存储在内存中,所以速度会很快,Term Index在内存中是以FST(Finite State Transducers)形式保存的,会很节省内存

FST的两个优点:

  • 空间占用小,通过对词典中单词前缀和后缀的重复利用,压缩了存储空间

  • 查询速度快,O(len(str))的查询时间复杂度

PostingList也有对应的优化,PostingList使用FOR编码技术对里边的数据进行压缩,节约磁盘空间

PostingList里边存的是文档ID,检索的时候经常需要对文档的ID进行交集和并集的操作,比如多个条件检索,PostingList使用Roaring Bitmaps来对文档ID进行交并集操作,

使用**Roaring Bitmaps(一种基于BitMaori的数据结构和压缩算法)**的好处是可以节省空间和快速得出交并集的结果,感兴趣的可以去研究一波

3、特点和应用场景

其实我觉得看了上面那些,特点应该大家也能知道个七七八八了,接下来我来总结下

  • 支持快速的全文检索引擎和数据分析引擎(倒排索引和分词技术)

  • 可以作为一个大型分布式集群,处理PB级数据,也可以运行单机服务小公司

  • 底层是基于Lucene封装的,使用json格式存储数据

  • 同义词处理、相关度排名、海量数据的近实时处理

  • 不支持事务,还有各种联机事务型的操作

相对于数据库来说,ElasticSearch的强大之处在于可以进行模糊查询(通过分词),你可能会疑问了,模糊查询,不是数据库就可以做到吗?

反手一个sql甩到了我的脸上:

select * from user where name like '%程序控%'

这难道不是模糊查询?的确这样是可以,但是这样不走索引啊,会造成全文检索,不走索引意味着如果你的数据量超大,查询会变得很慢

而且,即使返回给你模糊查询的数据,也无法得出哪一个是更精确的,我们知道百度谷歌这些搜索引擎,肯定是根据用户搜索得出最符合用户搜索条件的放在最前面,这一点数据库是无法支持的,es中会根据搜索的数据的评分进行排序,越符合条件评分越高,原生支持这一点

使用场景借鉴于博客《铭毅天下》

**场景一:使用ElasticSearch作为主要的后端,作为搜索引擎
**

在传统的项目中,搜索引擎是部署在成熟的数据存储的顶部,因为早期的搜索引擎不能提供存储或者其他的功能,我们只是为了提高快速检索能力引入

Es提供持久存储、统计等多项强大的功能,是一款现代的搜索引擎,如果你刚开始一个新项目,可以考虑用es作为唯一数据存储,这样设计会更简单,但是这种情况需要个人斟酌是否符合应用场景,场景不支持频繁更新、事务等操作

举个例子:新建的一个博客系统使用es作为存储,我们可以向es提交新的博文存储,使用es进行检索、统计数据等

**场景二:在现有系统增加ElasticSearch
**

由于ES不能提供存储的所有功能,一些场景下需要在现有系统数据存储的基础上新增ES支持

  • 如果原有系统需要事务支持,或者关系复杂,需要考虑在原有的系统基础上引入es的支持,因为es不支持事务(1.x版本不支持,2.x版本支持的不够好)

  • 如果现在需求是在一个复杂系统上新增检索服务而已,那么可以考虑引入es作为系统检索引擎,不建议重构系统,建议在原有数据存储的基础上增加

场景三:使用ElasticSearch和现有的工具

在一些使用情况下,您不必写一行代码就能通过elasticssearch完成一项工作。很多工具都可以与Elasticsearch一起工作,所以你不必到你从头开始编写。
例如,假设要部署一个大规模的日志框架存储,搜索,并分析了大量的事件。
如图下图,处理日志和输出到Elasticsearch,您可以使用日志记录工具,如rsyslog,Logstash,或Apache Flume(flume.apache.org),搜索和可视化界面分析这些日志,你可以使用Kibana

白嫖

白嫖一时爽,一直白嫖一直爽

(来源blog.csdn.net/laoyang360/…

白嫖之后

赠人玫瑰,手有余香(疯狂暗示...)