Elasticsearch基础与读写原理
ES应用场景:海量数据检索,数据分析
ES分布式架构原理:es存储的基本单位是索引index,index就相当与mysql中的一张表,index中可以有一个或多个type,当存放多个type时尽量使每个type中的各部分字段是一样的,一般来说一个index中只存放一个type。mapping是type的结构定义,document是type中的具体的记录,field表示document中的具体的某一个字段;
es集群中有多个节点,集群会自动选举中一个master节点,master节点做一些管理工作的事情,比如维护索引元数据拉,负责切换primary shard和replica shard身份拉,之类的。要是master节点宕机了,那么会重新选举一个节点为master节点。每个节点中有多个shard,相同的primary shard和replica shard不能同时位于同一个节点上,当master宕机后,集群中会重新选择一个master节点,并利用副本机制补全由于master节点宕机所丢失的副本以及选出新的primary shard。保证系统的高可用
倒排索引(Inverted Index):倒排索引是实现“单词-文档矩阵”的一种具体存储形式,通过倒排索引,可以根据单词快速获取包含这个单词的文档列表。倒排索引主要由两个部分组成:“单词词典”和“倒排文件”。其中单词词典的数据结构为B+树,B+树构造可视化链接
单词词典(Lexicon):搜索引擎的通常索引单位是单词,单词词典是由文档集合中出现过的所有单词构成的字符串集合,单词词典内每条索引项记载单词本身的一些信息以及指向“倒排列表”的指针。
倒排列表(PostingList):倒排列表记载了出现过某个单词的所有文档的文档列表及单词在该文档中出现的位置信息,每条记录称为一个倒排项(Posting)。根据倒排列表,即可获知哪些文档包含某个单词。
倒排文件(Inverted File):所有单词的倒排列表往往顺序地存储在磁盘的某个文件里,这个文件即被称之为倒排文件,倒排文件是存储倒排索引的物理文件。
Elasticsearch 是一个开源的搜索引擎,建立在一个全文搜索引擎库Apache Lucene基础之上,Elasticsearch也可以被形容为一个分布式的实时文档存储、一个分布式实时分析搜索引擎、可水平拓展并支持pb级别的结构化和非结构化数据
索引分片:索引建立时可手动指定分片的数量以及副本的数量,分片数量在创建之后无法改变,副本数量在之后可以改变,随着集群中节点的增加与删除,各个分片与副本会重新分配到各个节点中
分片路由规则:shard = hash(routing) % number_of_primary_shards
分片数据一致性:一致性:可以通过设置参数consistency的值来确定写请求是否执行,当consistency为all则只有所有分片副本都存活的时候才执行写操纵,当consisteny为one时只要主分片存活就执行写操作,当consistency为具体的数值时,需要保证至少有规定的数量的分布存活才进行写操纵
分布式系统中的深度分页:每个分片都将返回大量数据给协调节点,协调节点再对结果进行排序返回
官方Java Api文档:Elasticsearch Api 文档
查询结果关键字介绍:total表示匹配的文档总量、hits数组包含文档的index,type,id,source字段、took表示搜索请求耗费的时间、shards表示搜索请求中参与的分片数量以及成功了多少个失败了多少个、timeout表示查询是否超时
读写原理:
es写数据过程
-
客户端选择一个node发送请求过去,这个node就是coordinating node(协调节点)
-
coordinating node,对document进行路由,将请求转发给对应的node(有primary shard)
-
实际的node上的primary shard处理请求,然后将数据同步到replica node
-
coordinating node,如果发现primary node和所有replica node都搞定之后,就返回响应结果给客户端
es读数据过程
查询,GET某一条数据,写入了某个document,这个document会自动给你分配一个全局唯一的id,doc id,同时也是根据doc id进行hash路由到对应的primary shard上面去。也可以手动指定doc id,比如用订单id,用户id。
你可以通过doc id来查询,会根据doc id进行hash,判断出来当时把doc id分配到了哪个shard上面去,从那个shard去查询
1)客户端发送请求到任意一个node,成为coordinate node
2)coordinate node对document进行路由,将请求转发到对应的node,此时会使用round-robin随机轮询算法,在primary shard以及其所有replica中随机选择一个,让读请求负载均衡
3)接收请求的node返回document给coordinate node
4)coordinate node返回document给客户端
es搜索数据过程
es最强大的是做全文检索,就是比如你有三条数据
- java真好玩儿啊
- java好难学啊
- j2ee特别牛
你根据java关键词来搜索,将包含java的document给搜索出来
es就会给你返回:java真好玩儿啊,java好难学啊
-
客户端发送请求到一个coordinate node
-
协调节点将搜索请求转发到所有的shard对应的primary shard或replica shard也可以
-
query phase:每个shard将自己的搜索结果(其实就是一些doc id),返回给协调节点,由协调节点进行数据的合并、排序、分页等操作,产出最终结果
-
fetch phase:接着由协调节点,根据doc id去各个节点上拉取实际的document数据,最终返回给客户端
写数据底层原理
-
先写入buffer,在buffer里的时候数据是搜索不到的;同时将数据写入translog日志文件
-
如果buffer快满了,或者每隔一秒钟,就会将buffer数据refresh到一个新的segment file中并清空buffer,但是此时数据不是直接进入segment file的磁盘文件的,而是先进入os cache的。当数据进入os cache后,就代表该数据可以被检索到了。因此说es是准实时的,这个过程就是refresh。
-
只要数据进入os cache,此时就可以让这个segment file的数据对外提供搜索了
-
重复1~3步骤,新的数据不断进入buffer和translog,不断将buffer数据写入一个又一个新的segment file中去,每次refresh完buffer清空,translog保留。随着这个过程推进,translog会变得越来越大。当translog达到一定长度的时候,就会触发commit操作。
commit操作(也叫flush操作,默认每隔30分钟执行一次):执行refresh操作 -> 写commit point -> 将os cache数据fsync强刷到磁盘上去 -> 清空translog日志文件
commit操作保证了在机器宕机时,buffer和os cache中未同步到segment file中的数据还可以在重启之后恢复到内存buffer和os cache中去,
-
translog其实也是先写入os cache的,默认每隔5秒刷一次到磁盘中去,所以默认情况下,可能有5秒的数据会仅仅停留在buffer或者translog文件的os cache中,如果此时机器挂了,会丢失5秒钟的数据。但是这样性能比较好,最多丢5秒的数据。也可以将translog设置成每次写操作必须是直接fsync到磁盘,但是性能会差很多。
-
如果是删除操作,commit的时候会生成一个.del文件,里面将某个doc标识为deleted状态,那么搜索的时候根据.del文件就知道这个doc被删除了
-
如果是更新操作,就是将原来的doc标识为deleted状态,然后新写入一条数据
-
buffer每次refresh一次,就会产生一个segment file,所以默认情况下是1秒钟一个segment file,segment file会越来越多,此时会定期执行merge,当segment多到一定的程度时,自动触发merge操作
-
每次merge的时候,会将多个segment file合并成一个,同时这里会将标识为deleted的doc给物理删除掉,然后将新的segment file写入磁盘,这里会写一个commit point,标识所有新的segment file,然后打开segment file供搜索使用,同时删除旧的segment file。
es里的写流程中主要的4个底层核心概念,refresh、flush、translog、merge
读写操作流程图:来自石杉学院(公众号:石杉码农)
01_es读写底层原理剖析.png
es性能优化:
1. os cache(充分利用操作系统缓存)
2. 数据预热(定时查询热数据,将热数据刷进操作系统缓存中)
3. 冷热分离
4. document模型设计,减少复杂查询(一些数据关联的逻辑操作,在应用层完成 ,允许一定的数据冗余)
5. 分页查询优化(禁止跳跃查询,只能翻页查询)