一文读懂ElasticSearch底层原理

一、ES基本概念介绍

1.ES简介

ES是一个分布式、可扩展的、近实时的,有数据搜索、分析与存储的引擎。支持全文搜索、结构化搜索、半结构化搜索、数据分析、地理位置和对象间关联关系搜索等功能。

近实时:非实时,数据不是实时最新的。

其底层基于Lucene,但Lucene比较复杂,面向普通应用开发者而言,易用性不是很好,同时对于目前的主流分布式架构支持也不好,所以就诞生了ES。

ES使用Java编写,它的内部使用Lucene做索引与搜索,隐藏了Lucene的复杂性,面向开发者暴露了即使不同编程语言也基本一致的API和Client,方便大家将搜索功能快速植入到日常应用中。

2.ES使用场景

(1)全文检索

ES的主要应用场景之一,类似于Google搜索,百度搜索和维基百科等,对全文关键字进行检索。

(2)日志分析

海量数据进行近实时的处理,对复杂的日志进行分析,得到我们想要的结果

(3)复杂条件查询

数据量很大,又需要各种条件查询,实时的返回查询数据结果,如管理后台

(4)相似搜索,模糊匹配,地理位置聚合等

3.ES基本概念

(1)文档(Document)

是在ES中可以被索引的基本单位,以JSON标识,类似于关系数据库中的一行

(2)类型(Type)

表示一类相似的文档,作为一个元数据来实现逻辑划分,类似于关系数据库中的表

(3)索引(Index)

索引是具有相似特征的文档的集合,类似于关系数据库中的数据库。

4.ES的节点、分片

默认情况下,每个索引由5个主要分片组成,每份主要分片又有一个副本,一共10个分片

分片是ES所处理的最小单元,一份分片是Lucene的索引,包含倒排索引的文件目录,分片仅保存了全部数据中的一部分

副本分片是主分片的拷贝,副本分片作为硬件故障时数据的备份,并为搜索和返回文档等读操作提供服务。副本分片可以提高可用性和性能。

默认的,文档在分片上均匀分布,通过文档ID字符串的散列决定分布到哪个分片,每份分片拥有相同的散列范围,接收新文档的机会均等。一旦目标分片确定,接收请求的节点将文档转发到该分片所在的节点,随后索引操作在所有目标分片的所有副本分片中进行。

写索引只能写在主分片上,然后同步到副本分片,ES写入哪个分片是由文档ID的hash值决定的,公式如下:

shard = hash(routing) % number_of_primary_shards

一次文档写入流程大致如下

(1)客户端向节点2(协调节点)发送写请求,通过路由计算公式得到分片值为0,则文档应该写到主分片0上

(2)协调节点将请求转发到分片0所在的节点1上,节点1接收请求并写入到磁盘

(3)并发将数据复制到节点2的副本分片0(节点2上的0分片为副本分片)上,通过锁解决数据冲突,一旦所有副本都报告成功,则节点1向协调节点报告成功,协调节点向客户端报告成功。

5.倒排索引

倒排索引是一种类似于HashMap的数据结构,不会直接存储字符串,而是将每个文档拆分为单个搜索词,然后将每个搜索词映射到这些搜索词出现过的文档。

idcontent
1elasticsearch in action
2redis in action

如上表标识我们关系型数据库中的两条数据,转变为倒排索引的形式则为(词频主要是查询时打分使用):

contentid词频
elasticsearch1id1->1次
redis2id2->1次
in1,2id1->1次 id2->1次
action1,2id1->1次 id2->1次

二、分析数据

分析是在文档发送并加入倒排索引之前,ES在其主体上进行的操作。在文档被加入索引之前,ES让每个被分析字段经过一系列的处理步骤。

(1)字符过滤:使用字符过滤器转变为字符

(2)文本切分:将文本切分为单个或多个分词

(3)分词过滤:使用分词过滤器转变每个分词

(4)分词索引:将这些分词存储到索引中

三、数据写入

数据的写入最终是要写到ES磁盘上,但是如果每次写数据都直接更新磁盘,磁盘的I/O消耗会非常应用性能,当写数据量大的时候就会造成ES停顿卡死,查询也会受到严重影响,ES就无法成为近实时搜索引擎了。

1.分段存储

索引文件被拆分为多个子文件,每个子文件叫做

每一个段本身都是一个倒排索引,并且段具有不变性,一旦索引的数据被写入磁盘,就不可再修改。在底层采用了分段的存储模式,使它在读写时几乎完全避免了锁的出现,大大提升了读写性能。

段被写入到磁盘后会生成一个提交点,提交点是一个用来记录所有提交后 段信息的文件。一个段一旦拥有了提交点,就说明这个段只有读的权限,失去了写的权限。相反,当段在内存中时,就只有写的权限,而不具备读数据的权限,意味着不能被检索。

索引文件分段存储并且不可修改,那么新增、更新和删除如何处理呢?

(1)新增:数据是新的,所以只需要对当前文档新增一个段就可以了

(2)删除:由于不可修改,所以对于删除操作,不会把文档从旧的段中移除而是通过新增一个.del文件,文件中会列出这些被删除文档的段信息。这个被标记删除的文档仍然可以被查询匹配到,但它会在最终结果被返回前从结果集中移除。

(3)更新:不能修改旧的段来反映文档的更新,其实更新相当于是由删除和新增这两个动作组成。会将旧的文档会标记.del文件,然后文档的新版本被索引到一个新的段中。可能两个版本的文档都会被一个查询匹配到,但被删除的那个旧版本文档在结果集返回前就会被移除。

2.刷新(refresh)

每当有新增的数据时,就将其先写入到内存中在内存和磁盘之间是文件系统缓存(以下操作都是在文件系统缓存中进行),当达到默认的时间(1秒钟)或者内存的数据达到一定量时,会触发一次刷新(refresh),将内存中的数据生成到一个新的段上并缓存到文件缓存系统上,稍后再被刷新到磁盘中并生成提交点。

  -》 

如上,数据会优先写入到内存缓存中,此时新写入的数据还不可以被检索,这也是为什么ES被称为近实时检索的原因,随着数据不断写入,ES会将内存缓存中的数据刷新到一个新的段中,这时新写的数据就可以被检索了。

3.冲刷(flush)

将内存中的分段提交到磁盘的过程叫做冲刷,在数据没有冲刷到磁盘之前,此时新写入的数据还在内存中,如果这时系统断电或者出现宕机异常,如果保证数据不会丢失?

ES增加了一个translog,或者叫事务日志,在每一次对ES进行操作时均进行了日志记录。

数据refresh的时候,内存中的缓存数据被请求,但是事务日志不会。

数据flush到磁盘之后,段被全量提交到磁盘,事务日志被清空。

当满足以下条件之一就会触发刷新操作。

(1)内存缓冲区已满

(2)自上次flush后超过了一定的时间

(3)事务日志达到了一定的阈值

4.段合并(merge)

段合并主要有两个目的:将分段的总数量保持在受控的范围内,保障查询的性能,因为每个搜索请求都必须轮流检查每个段,所以段越多,搜索也就越慢。第二个是真正的删除文档。

合并的最终目的是提升搜索的性能并均衡I/O和CPU计算能力

合并发生在写入、更新或删除文档的时候,所以合并的越多,更新操作的成本就越高。

四、数据查询

1.索引优化

ES为了能快速找到某个term,先将所有的term排个序,然后根据二分法查找term,时间复杂度为logN,就像通过字典查找一样,这就是term dictionary。现在再看起来,似乎和传统数据库通过B-Tree的方式类似。

但是如果term太多,term dictionary也会很大,放内存不现实,于是有了term index,就像字典里的索引页一样,A开头的有哪些term,分别在哪页,可以理解term index是一棵树。这棵树不会包含所有的term,它包含的是term的一些前缀。通过term index可以快速地定位到term dictionary的某个offset,然后从这个位置再往后顺序查找。

2.FST压缩

为了让内存中可以存储更多数据,ES在内存中用FST方式压缩term index,FST有两个优点:

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

(2)查询速度快。O(len(str))的查询时间复杂度

FST压缩率一般在3倍~20倍之间,相对于TreeMap/HashMap的膨胀3倍,内存节省就有9倍到60倍。

3.打分机制

ES使用搜索词条的频率以及它有多常见来影响得分,简单介绍为:一个词条出现在某个文档中的次数越多,就越相关;但是如果该词条出现在不同文档的次数越多,就越不相关。这一点称为TF-IDF(TF是词频,IDF是逆文档频率)。

比如搜索词条“the score”,单词the几乎出现在所有文档中,所有the不重要,如果不适用逆文档频率,那么the关键词将覆盖单词score的频率。

五、其他

1.Master选举

集群中可能会有多个可以成为,此时就要进行master选举,保证只有一个当选master。如果有多个node当选为master,则集群会出现脑裂,脑裂会破坏数据的一致性,导致集群行为不可控,产生各种非预期的影响。

为了避免产生脑裂,ES采用了常见的分布式系统思路,投票机制,保证选举出的master被多数节点认可,以此来保证只有一个master。配置名称:discovery.zen.minimum_master_nodes,为了避免脑裂,这个配置一般配置为sum(node)/2+1,保证超过一半的节点投票了主节点。

2.选举谁

public static int compare(MasterCandidate c1, MasterCandidate c2) {// we explicitly swap c1 and c2 here. the code expects "better" is lower in a sorted// list, so if c2 has a higher cluster state version, it needs to come first.int ret = Long.compare(c2.clusterStateVersion, c1.clusterStateVersion);if (ret == 0) {ret = compareNodes(c1.getNode(), c2.getNode());}return ret;
}

如上面源码所示,先根据节点的clusterStateVersion比较,clusterStateVersion越大,优先级越高。clusterStateVersion相同时,进入compareNodes,其内部按照节点的Id比较(Id为节点第一次启动时随机生成)。

为什么要有排序逻辑,主要是避免每次选举的节点不一致,导致达不到minimum_master_nodes数量,不要出现都想当master而选不出来的情况。

3.怎么保证不脑裂

基本原则还是多数派的策略,如果必须得到多数派的认可才能成为Master,那么显然不可能有两个Master都得到多数派的认可。

上述流程中,master候选人需要等待多数派节点进行join后才能真正成为master,就是为了保证这个master得到了多数派的认可。上述流程在绝大部份场景下没问题,听上去也非常合理,但是却是有bug的。

因为上述流程并没有限制在选举过程中,一个Node只能投一票,那么什么场景下会投两票呢?比如Node_B投Node_A一票,但是Node_A迟迟不成为Master,Node_B等不及了发起了下一轮选主,这时候发现集群里多了个Node_0,Node_0优先级比Node_A还高,那Node_B肯定就改投Node_0了。假设Node_0和Node_A都处在等选票的环节,那显然这时候Node_B其实发挥了两票的作用,而且投给了不同的人。

那么这种问题应该怎么解决呢,比如raft算法中就引入了选举周期(term)的概念,保证了每个选举周期中每个成员只能投一票,如果需要再投就会进入下一个选举周期,term+1。假如最后出现两个节点都认为自己是master,那么肯定有一个term要大于另一个的term,而且因为两个term都收集到了多数派的选票,所以多数节点的term是较大的那个,保证了term小的master不可能commit任何状态变更(commit需要多数派节点先持久化日志成功,由于有term检测,不可能达到多数派持久化条件)。这就保证了集群的状态变更总是一致的。

4.批量操作提升性能

Elasticssearch提供批量操作(插入,更新,删除),批量操作的API是_bulk,此功能非常强大,因为它提供了一种非常有效的机制,可以尽可能快地进行多个操作,并尽可能少地进行网络往返。批量查询使用mget。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/451308.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java21 + SpringBoot3集成七牛云对象存储OSS,实现文件上传

文章目录 前言实现步骤引入maven依赖修改配置文件创建七牛云配置类创建文件操作服务类创建文件操作控制器前端实现运行效果 总结 前言 近日心血来潮想做一个开源项目,目标是做一款可以适配多端、功能完备的模板工程,包含后台管理系统和前台系统&#xf…

apipost 简单的性能压测总结

1、简单的使用机型牌评估 1)jdk默认256M给100用,推荐给1000人同时用JVM 堆栈建议2G~4G(目前定了机型4核8G内存 2T磁盘做radio0存储); 2)数据库配置文件写了占了2G内存(my.cnf文件&#xff09…

计算机网络-封装成帧透明传输(组帧方法)

文章目录 数据链路层功能概述封装成帧透明传输组帧方法字符计数法字符填充法零比特填充法违规编码法 字符填充法为啥复杂和不兼容 数据链路层功能概述 类似老板让小秘书送文件给别的公司,小秘书告诉傻子怎么把该文件送到别的公司的小秘书,然后别的公司的…

em/px/rem/vh/vw的区别

文章目录 一、介绍二、单位pxemremvh、vw 三、总结 一、介绍 传统的项目开发中,我们只会用到px、%、em这几个单位,它可以适用于大部分的项目开发,且拥有比较良好的兼容性 从CSS3开始,浏览器对计量单位的支持又提升到了另外一个境…

寒假 day3

1.请编程实现双向链表的头插&#xff0c;头删、尾插、尾删 2.请编程实现双向链表按任意位置插入、删除、修改、查找 //头文件 #ifndef __HEAD_H__ #define __HEAD_H__ #include<stdio.h> #include<string.h> #include<stdlib.h> typedef char datatype;//…

3. 状态管理 vuex 状态管理库

目录 3.1 vuex 介绍 3.2 使用方式 3.1 vuex 介绍 vuex 是一个专为 Vue.js 应用程序开发的状态管理库 vuex 可以在多个组件之间共享数据&#xff0c;并且共享的数据是响应式的&#xff0c;即数据的变更能及时渲染到模板 vuex 采用集中式存储管理所有组件的状态 每一个 Vuex…

使用ESP32-S3对MQ-135空气质量传感器的使用记录(Arduino版)

一、硬件上&#xff1a; 1、使用esp32开发板的04引脚与AO连接&#xff0c;检测AO引脚的电平 二、软件上&#xff1a; 1、使用Arduino快速完成开发 2、源码&#xff1a; // Potentiometer is connected to GPIO 04 (Analog ADC1_CH3) const int adcPin 4;// variable for s…

2023启示录丨中国ESG这一年:在矛盾与摸索中前行

图片&#xff5c;Photo by Colby Winfield on Unsplash ©自象限原创 作者丨罗辑 编辑丨程心 2023年&#xff0c;许多行业开始争抢ESG人才&#xff0c;在猎聘APP上搜索“ESG”&#xff0c;相关岗位月薪可以达到10W~13W&#xff0c;甚至一些行业应届生的起薪都达到2~4万。…

少儿编程 中国电子学会图形化编程2022年1月等级考试Scratch三级真题解析(选择题、判断题)

1.默认小猫角色和气球角色都是显示状态&#xff0c;小猫程序如下图所示&#xff0c;气球没有程序&#xff0c;点击绿旗&#xff0c;舞台上最终显示的效果是&#xff1f;&#xff08; &#xff09; A&#xff1a;可能出现6个不同位置的小猫和6个小球 B&#xff1a;可能出现6个…

Opencv(C++)学习 TBB与OPENMP的加速效果实验与ARM上的实践(二)

在上一篇文章中&#xff0c;我们成功验证了Intel Threading Building Blocks (TBB) 与 OpenMP 在多线程并行处理方面的加速潜力。为了更深入地理解这些技术在实际应用场景中的效能提升&#xff0c;接下来我们将目光转向目标开发板环境&#xff0c;进一步探究这两种框架在嵌入式…

《幻兽帕鲁》好玩吗?幻兽帕鲁能在Mac上运行吗?

最近一款叫做《幻兽帕鲁》的新游戏走红&#xff0c;成为了Steam游戏平台上&#xff0c;连续3周的销量冠军&#xff0c;有不少Mac电脑用户&#xff0c;利用Crossover成功玩上了《幻兽帕鲁》&#xff0c;其实Crossover已经支持很多3A游戏&#xff0c;包括《赛博朋克2077》《博德之…

外卖单店小程序模板/小程序前端模板

外卖单店小程序模板简介&#xff1a;外卖单店小程序前端模板 外卖单店小程序模板截图