大数据技术学习——ElasticSearch
1 一句话介绍
ElasticSearch(简称ES)是分布式实时全文搜索引擎和实时文件存储数据库。
2 ES架构
- EsMaster:集群中只能有一个主节点,管理集群级别的一些变更, 例如决定分片的分配、新建或删除索引、增加或移除节点等。主节点不参与文档级别的变更或搜索。
- EsClient:协调节点,只处理路由请求、搜索,及分发索引等操作。自身不存储数据,也不管理集群。
- EsNode:数据节点,主要是存储索引数据,对文档进行增删改查、聚合等操作。节点上每个EsNode进程对应一个目录,存放该EsNode管理的索引分片。
- Gateway:集群索引底层存储方式,如本地文件系统,HDFS(性能太差,基本不用)等。
3 ES数据存储结构
3.1 重要概念
- Index:索引是文档的集合,类似于关系型数据库的table(表)。分布式文件存储中,索引仅仅是一个指向分片的逻辑命名空间,实际提供搜索服务的是位于节点上的分片。Indexing意思就是存储文档。
- Document:文档是一次插入的一系列键值对的集合(Json序列),类似于关系型数据库的Row(行)。
- Shard:分片是一个独立的Lucene实例(即Lucene index),实际存储数据,并能提供完整搜索服务能力。
- Segment:分片由大量的Segment(段)文件构成,段直接提供搜索功能。
- Field:即Json字符串中Key,类似于关系型数据库的列。
- Mapping:定义文档包含多少个字段,字段类型等
- Term:对text类型的Value进行分词后的最小单元。
3.2 倒排索引
即从所有文档中抽取Term,构建Term与文档ID的映射关系。例如:
两个文档如下:
- The quick brown fox jumped over the lazy dog
- Quick brown foxes leap over lazy dogs in summer
则倒排索引如下:
倒排索引非常适合于搜索包含特定关键词(Term)的文档。
3.3 DocValues(正排索引)
即将倒排索引转置(列存储)如下:
DocValues非常适合于聚合操作。
3.4 数据物理存储
向ES中插入一个文档,可存储如下几个文件:
- Lucene&Segment&Field元数据文件:Segment个数,Segment包含文件列表,Field类型、是否存储、是否索引、是否分词等等。
- 数据存储文件:插入数据的原始Json文档,存储在_source字段下,可通过"_source": {"enabled": false}禁用。
- 倒排索引文件:可持久化到磁盘,但不可变,如需修改只能重建。
- DocValues:正排索引数据结构,如字段没有聚合的需求,可以通过设置doc_values: false禁用。
ES数据以分片为粒度,可设置多个复制分片。集群状态显示与分片的关系如下:
4 ES重要字段
- object与nested类型
object: 默认字段类型,包含下一级字段的字段,直观理解该字段的value是一个{…}。
nested: 一种特殊的object字段,需要显式指明字段类型为“nested”,能将{…}里面多个[]当成一个整体来搜索,而不是像object那样将内部嵌套的{…}扁平化。例如:
该条数据中content以及username的实际存储方式如下,失去了content与name的关联。这时如果关联搜索"good"和"li si",同样能返回搜索结果。
若事先显示指定comment字段类型为nested,这时如果关联搜索"good"和"li si",则返回搜索结果为空。
注:text支持分词,全文检索,支持模糊、精确查询,不支持聚合,排序操作;keyword不进行分词,直接索引,支持模糊、支持精确匹配,支持聚合、排序操作。
- 固定名称字段
properties: 显示地为object或nested类型字段添加属性字段。
fields: 为同一个字段赋予别名,并为别名赋予不同的数据类型,以便进行不同的操作
- 文档的元数据字段(下划线开头)
_index: 文档归属索引
_type: mapping type,ES6已取消
_id: 文档ID,可手动或自动指定
_source: 存储文档原始Json字符串,可以禁用
5 ES读写流程
5.1 索引(写)流程
- 客户端将索引请求发送任意节点Node1上主分片P1
- 节点通过判断数据应该存在Node3上主分片P0
- P0若执行成功会将请求同步给其他节点上的复制分片R0,R0执行成功后会将结果返回给P0,P0将返回success给客户端
- 文档会根据路由算法分配到特定的分片上:
shard=hash(routing)%number_of_primary_shards
routing默认是文档id。
- 新写入数据时,数据先写入内存缓存区(in-memory buffer)以及事务日志(Translog)中,此时并不能检索到,需要从内存缓存区refresh到Segment(可以通过设置refresh_interval决定refresh时间间隔)才能被检索到。每次refresh会形成新的Segment,ES内部会开启一个新的线程进行段合并,从而提升IO性能。
5.2 搜索流程
- 客户端将请求发给任意一个节点Node3
- Node3将请求发送给index下的所有分片(可以从主分片或复制分片下任意选择一个),每个分片将查询结果排序存在本地
- 所有分片将查询到的结果统一发送给Node3(此时承担协调节点的角色)进行合并,再转发给客户端
6 翻页方案
- from+size方案:适合实时查询场景
类似于SQL的limit,from定义跳出的文档条数(hits),size定义每页展示的文档条数。ES默认的分页深度(max_result_window)是10000,也就是说from+size超过10000就会报错。深度分页非常耗时、耗内存,因为需要从每个主分片获取from+size条文档条数再在协调节点合并。
- search after方案:适合海量查询场景
利用实时游标解决实时滚动的问题,简单来说前一次查询的结果会返回一个唯一的字符串,下次查询带上这个字符串,进行下一页的查询。基于排序唯一标识,每个分片仅返回size条文档,效率高。
- scroll方案:适合一次性返回海量数据的非实时场景
首次查询时生成一个 scrollId,并将所有符合搜索条件的搜索结果的doc_id缓存起来。后续查询时,携带上一次查询返回的 scrollId。
各个方案的优缺点对比如下:(摘自:https://juejin.cn/post/7103848212154286087)
7 参考
- 点赞
- 收藏
- 关注作者
评论(0)