ES原理解读
ES原理解读摘要:本篇文章仅仅是谈谈个人对ES原理的理解,可能理解不对的地方,欢迎大家指出。概念ES就是elasticsearch,专门做文本搜索,其重要组件是Lucence。Lucence就是一个jar包,它的主要功能就是提供封装好的各种索引算法、生成倒排索引等。ES是基于Lucene的搜索服务器,它提供了一个分布式多用户能力的全问搜索引擎,且ES支持RestFulweb风格的url访问。ES是
ES原理解读
摘要:本篇文章仅仅是谈谈个人对ES原理的理解,可能理解不对的地方,欢迎大家指出。
- 概念
ES就是elasticsearch,专门做文本搜索,其重要组件是Lucence。
Lucence就是一个jar包,它的主要功能就是提供封装好的各种索引算法、生成倒排索引等。
ES是基于Lucene的搜索服务器,它提供了一个分布式多用户能力的全问搜索引擎,且ES支持RestFulweb风格的url访问。ES是基于Java开发的开源搜索引擎,设计用于云计算,能够达到实时搜索,稳定、可靠、快速。此外,ES还提供了数据聚合分析功能,但在数据分析方面,es的时效性不是很理想,在企业应用中一般还是用于搜索。ES自2016年起已经超过Solr等,称为排名第一的搜索引擎应用。
与数据库对比
RDBS ES
数据库(database) 索引(index)
表(table) 类型(type)(ES6.0之后被废弃,es7中完全删除)
表结构(schema) 映射(mapping)
行(row) 文档(document)
列(column) 字段(field)
值 term
索引 反向索引
SQL 查询DSL
SELECT * FROM table GET http://.....
UPDATE table SET PUT http://......
DELETE DELETE http://......
Node:一般指的是一个es服务实例(通常就是在一台机器上)。
Cluster:集群,即由多个es服务组成的服务群组,由多个es实例共同对外提供服务。
primary shard:主分片,用来存储数据,多分片会对数据进行切割,比如id 1 2 3 4 5,现在有两个分片,id 1 3 5 可能存储在分片1上 而id 2 4 则存储在分片2 上。
replica shard:副本分片,即主分片的备份分片,个人认为有两个目的,一个是为了提高查询效率,第二个是保证数据的高可用。
索引:
名词:即上面提到的与RDBS对应为database的概念。
动词:相当于数据库中的insert into的概念,索引(动词)一个文档(一条数据)到索引(名词)中这样这条数据才能被查找到,其实就是在数据中插入一条数据的意思。
倒排索引:相当于RDBS中索引的概念,目的是为了能够快速查找到文档(某一条数据),只是倒排索引的实现比不是B-Tree。
创建过程:
客户端发往任意节点,创建索引请求会先转为bulk请求,执行createIndex,如果当前节点不是主节点,它然后先去请求master节点。master节点验证索引创建的请求,然后内部算出一个新的集群信息ClusterState,执行executeIngestAndBulk,发往主分片节点,主分片所在数据节点根据ClusterState创建对应的索引。
- 基本原理
- 写入过程:
- 客户端选择一个node发送请求过去,这个node就是coordinating node(协调节点)
- 协调节点接受数据,并根据路由规则对数据进行路由,不同的数据会路由到不同的节点,即将数据发送到给它分配的存储节点上。
- 实际节点接受数据并进行处理,完成后将数据同步到副本节点。
- 协调节点等待主节点和副本节点处理,当这些节点都处理完成后,协调节点将处理成功的结果返回给客户端。
- 读取过程:
- 客户端发送查询请求到任意节点,也就是上面的协调节点。
- 协调节点对查询id(doc id)进行hash路由将请求转发到对应的节点,目的是要能找到id数据所在的节点,此时值得注意的是:发送的时候会进行轮询,在主节点和副本节点上任意选取节点,目的是进行负载均衡。
- 当被请求的数据节点查找到数据后,将数据返回给协调节点,协调节点再将数据整理(合并啊、排序啊 等等的)返回给客户端。
以上是es的进本理论和原理,应该还算比较清楚,下面看下存储、搜索、更新、删除等的深入原理
- 深入原理
- 文档存储过程:
- 数据写入buffer(基本所有的程序写数据都会有这一步),同时将数据写入translog日志文件,此时文档是不可被检索的,因为es还没有生成必要的检索条件。
- Translog日志文件其实就是文档的另一个备份,作用有两个(可以在看完文档存储过程后再回头看一下):
- 当系统宕机后重启,es会重新加载日志文件中的文档,根据commit point加载需要被加载的文档,生成segment file。
- 系统没有宕机的时候,当日志文件超出规定大小,或者超过一定时间30min,es就会强制使用flush操作将segment持久化到磁盘。
- 当buffer中的数据量达到一定的量,或者到以一定的时间,es会将buffer中的数据refresh到segment file(段)中,同时更新commint point,此刻数据其实还没有被持久化到磁盘,值得注意的是如果buffer中没有数据此时即使是到了refresh的时间点es也不会进行refresh的。
- Segment(段)在被创建写入时会生成对应倒排索引用于索引数据。
- Refresh过程中会将segment写入到os cache中,os cache并不是磁盘,而是操作系统级别的缓存,当完成这一步的时候,文档检索将会被打开,此时文件就能就被检索了。
- 写入os cache后buffer就不需要了,为了节省空间它将会被立即清理。
- 重复接受数据-写入buffer-refresh-生成translog-生成segment
- 此时translog越来越大,则会触发commint操作,不过当到了一定的时间30min后也会进行commit。
- Commit也叫flush,就是将segment持久化到磁盘,当触发了flush后,buffer中可能存在数据,此时需要将现有的数据执行refush、生成log、segment等操作。
- 每个commit都会标识此次commit point有哪些segment是可用的,比如更新的时候原有的segment就是delete状态,重入一条segment。
主要过程图和关系
- 文档删除和更新
- 删除时的commint会生成一个.del文件,这个文件里面会将那些被删除的文档标识为delete,那么在搜索的时候对于客户端而言是检索不到了但是在es中是可以匹配到的只是在返回的时候被过滤,当segment发生合并时,被删除的文档不会被合并,因为没有必要。
- 更新时,会先将原有的doc标识为delete,然后重新生成segment并重新写入,注意并不是对segment更新重排,但是其中会有版本记录。
- 记住一点:es中的文档是不能被更改的,所有的操作都是写操作。
- 逆向索引、倒排索引
前面说的倒排索引的作用类似于B-Tree,都是为了能够快速定位数据,如果对其实现算法有兴趣的可以自己看看,我这里只说它在es中的应用。
Position:位置,即一个doc在es中的存储位置,也可以说一行数据在一个index(名词)的一个type(类型、库表)中的位置。
Posting List:位置列表就是一个term(值)在所在doc的位置列表
Position index:位置索引,就是一个term(一个值)与Posting List等的映射关系,说白了就是一个字典。
Term Dictionary:值的字典,为了能快速找到某个term,es添加了值的字典概念,也就是经过排序后的term可以使用二分法快速找到。
Term index:值索引,B-tree基本就是做到了字典哪个阶段,但是海量数据场景的情况下并不适用,比如字典过大放哪,是放内存还是disk,于是就使用了值索引,它就相当于字典的索引页,比如查a开头的term,可以先知道a大概在多少页,Term index就是这么应用的。
FST:压缩技术,能让Term index以极小的空间存储在内存中。
个人认为关系应该是这样的:
· 在Lucene中,单个倒排索引文件被称作Segment。Segment是不可变更的。多个Segment汇总在一起,称为Lucene的Index,其对应的就是ES中的Shard
· 当有新文档写入时,会生成新Segment,查找时会同时查找多个Segments,并且对结果进行汇总。Lucene中有个Commit Point文件,用来记录所有Segments信息。
· 删除文档的信息,会保存在.del文件中。在搜索时,返回的结果会根据.del中记录的文档信息,将其过滤掉。
- 没有必要给逆向索引加锁,因为不允许被更改,只有读操作,所以就不用考虑多线程导致互斥等问题。
- 索引一旦被加载到了缓存中,大部分访问操作都是对内存的读操作,省去了访问磁盘带来的io开销。
- 因为逆向索引的不可变性,所有基于该索引而产生的缓存也不需要更改,因为没有数据变更,这就是为什么更新的时候是将原来的segment删除重新生成segment。
- 使用逆向索引可以压缩数据,减少磁盘io及对内存的消耗。
更多推荐
所有评论(0)