3、ElasticSearch简介
ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。
优点:
* 分布式实时文件存储,并将每一个字段都编入索引,使其可以被搜索。
* 实时分析的分布式搜索引擎。
* 可以扩展到上百台服务器,处理PB级别的结构化或非结构化数据。
* Elasticsearch是分布式的。不需要其他组件,分发是实时的,被叫做”Push replication”。
* 各节点组成对等的网络结构,某些节点出现故障时会自动分配其他节点代替其进行工作。
3.2. Lucene与Solr
3.2.1. Lucene
Lucene不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引 引擎,部分文本分析引擎。想要使用它,你必须使用Java来作为开发语言并将其直接集成到你的应用 中,更糟糕的是,Lucene非常复杂,你需要深入了解检索的相关知识来理解它是如何工作的。
3.2.2. Solr
Solr是Apache Lucene项目的开源企业搜索平台。其主要功能包括全文检索、命中标示、分面搜索、 动态聚类、数据库集成,以及富文本(如Word、PDF)的处理。Solr是高度可扩展的,并提供了分布式 搜索和索引复制。Solr是最流行的企业级搜索引擎,Solr4 还增加了NoSQL支持。 当单纯的对已有数据进行搜索时,Solr更快。
当实时建立索引时, Solr会产生io阻塞,查询性能较差, Elasticsearch具有明显的优势。
随着数据量的增加,Solr的搜索效率会变得更低,而Elasticsearch却没有明显的变化。
综上所述,Solr的架构不适合实时搜索的应用。
4、ES安装
ElasticSearch安装,ES-head,IK,kibana安装.
5、ES数据存储结构
- 从ElasticSearch6.X开始,官方准备废弃Type了
ElasticSearch | Index 索引 | Document 文档 | Field 字段 | mapping 字段定义 |
---|---|---|---|---|
数据库 | 表 | 行记录 | 列字段 | 表结构定义–映射关系 |
5.1. 索引 Index
- 索引是文档(Document)的容器,是一类文档的集合
- 类比传统的关系型数据库领域来说,索引相当于SQL中的一个数据库(Database)。
- 索引ElasticSearch 使用了一个叫做
倒排索引
的结构来达到相同的目的。
5.2. 类型 Type
- 从6.0.0开始单个索引中只能有一个类型,7.0.0以后将将不建议使用,8.0.0 以后完全不支持。
- 索引和文档中间还有个类型的概念,每个索引下可以建立多个类型,文档存储时需要指定index和 type。
- 弃用原因
- 如 果在SQL中,Table 之前相互独立,同名的字段在两个表中毫无关系。
- 但是在ES中,同一个 Index 下不同的 Type 如果有同名的字段,他们会被 Luecence 当作同一个字段 ,并且他们的定义必须相同。
- 所以我觉得Index现在更像一个表,而Type字段并没有多少意义。
- 目前Type 已经被Deprecated,在7.0开始,一个索引只能建一个Type为_doc
5.3. 文档 Document
- Document Index 里面单条的记录称为Document(文档)。等同于关系型数据库表中的行。
_index 文档所属索引名称。
_type 文档所属类型名。
_id Doc的主键。在写入的时候,可以指定该Doc的ID值,如果不指定,则系统自动生成一个唯一的UUID值。
_version 文档的版本信息。Elasticsearch通过使用version来保证对文档的变更能以正确的顺序执行,避免乱序造成的数据丢失。
_seq_no 严格递增的顺序号,每个文档一个,Shard级别严格递增,保证后写入的Doc的
_seq_no大于先写入的Doc的_seq_no。
primary_term primary_term也和_seq_no一样是一个整数,每当Primary Shard发生重新分配时,比如重启,Primary选举等,_primary_term会递增1
found 查询的ID正确那么ture, 如果 Id 不正确,就查不到数据,found字段就是false。
_source 文档的原始JSON数据。
5.4. 字段Field
- 一行数据中心包含很多的字段,类似于关系数据库的列Column
6、ES的基本命令
先了解下restful中 GET/PUT/POST/DELETE 格式
POST /uri #创建
DELETE /uri/xxx #删除
PUT /uri/xxx #更新或创建
GET /uri/xxx #查看
在ES中,如果不确定文档的ID,那么就需要用POST,它可以自己生成唯一的文档ID。如果确定文档的ID,那
么就可以用PUT,当然也可以用POST,它们都可以创建或修改文档
PUT、GET、DELETE是幂等的,而POST并不一定是幂等。
6.1. 集群相关命令
- /_cat/nodes #查看所有节点信息
curl -X GET "192.168.88.101:9200/_cat/nodes?v&pretty"
- /_cat/shards #查看各shard的详细情况
curl -X GET "localhost:9200/_cat/shards?v&pretty"
- /_cat/indices #查看集群中所有index的详细信息
curl -X GET "localhost:9200/_cat/indices?v&pretty"
6.2. 映射Mapping
- 从7.x开始,一个Mapping只属于一个索引的type 默认type 为:_doc
- ES 字段类型主要有:核心类型、复杂类型、地理类型以及特殊类型
6.2.1. 核心类型
字符串类型
- text :
- 类型适用于需要被全文检索的字段,例如新闻正文、邮件内容等比较长的文字,text类型会被 Lucene 分词器(Analyzer)处理为一个个词项,并使用 Lucene 倒排索引存储,text 字段不能被用于排序,如果需要使用该类型的字段只需要在定义映射时指定 JSON 中对应字段的 type 为 text。
- 非结构化的文本数据。
- keyword:
- 不会被分词,适合简短、结构化字符串,例如主机名、姓名、商品名称等,可以用于过 滤、排序、聚合检索
- 也可以用于精确查询。 包括数字、日期、具体的字符串(如“192.168.0.1”)
6.3. Dynamic Mapping
动态映射时Elasticsearch的一个重要特性:
- 不需要提前创建index、定义mapping信息和type类型,
- 可以 直接向ES中插入文档数据时, ES会根据每个新field可能的数据类型, 自动为其配置type等 mapping信息
- 这个过程就是动态映射(dynamic mapping).
约束策略
- dynamic设为true时,新增字段的文档写入时,Mapping同时被更新
- dynamic设为false时,Mapping不会被更新,新增字段的数据无法被索引,但是会出现在 _source中
- dynamic设为strict,文档将写入失败
6.4. 索引CRUD命令
- 创建是命名全部小写,不能使用_开头,中间不能使用,
- 创建Index
curl -XPUT http://192.168.88.101:9200/lucky?pretty
- 获取索引
curl -XGET http://192.168.88.101:9200/lucky?pretty
- 删除索引
curl -XDELETE http://192.168.88.101:9200/lucky?pretty
8、分片与备份
-
分片分为两种,主分片和副本:
- 主分片用于解决数据水平扩展的问题,通过分片,可以将数据分布到集群内的所有节点之上
- 一个分片是一个运行的ES实例
- 分片数在索引创建时指定,后续不允许修改,除非Reindex
- 副本用以解决数据高可用的问题,副本是主分片的拷贝
- 副本分片数,可以动态调整
- 增加副本数,还可以在一定程度上提高服务的可用性(读取的吞吐)
- 主分片用于解决数据水平扩展的问题,通过分片,可以将数据分布到集群内的所有节点之上
-
分片的设定
- 分片数设置过大
- 导致后续无法增加节点实现水平扩展
- 单个分片数据量过大,导致数据重新分片耗时
- 分片数设置过小,7.0之后,默认主分片是1,解决了over-sharding的问题
- 影响搜索结果的相关性打分,影响统计结果的准确性
- 单个节点上过多分片,会导致资源浪费,同时会影响性能
- 分片数设置过大
9、ES数据架构
9.1. 基本概念
- Index: 一个ES集群中可以按需创建任意数目的索引。
- Document:文档是索引和搜索的原子单位,它是包含了一个或多个域(Field)的容器。
- Node:集群是由一个或者多个拥有相同cluster.name配置的节点组成
- 主节点:负责管理集群范围内的所有变更 (写操作)
- 数据节点:存储数据和其对应的倒排索引。默认每一个节点都是数据节点(包括主节 点)
- 协调节点:如果node.master和node.data属性均为false,此节点称为协调节点,用来 响应客户请求,均衡每个节点的负载。
- Shard:一个索引中的数据保存在多个分片中,相当于水平分表。
- 分片是数据的容器,文档保存在分片内,分片又被分配到集群内的各个节点里
- 索引建立的时候就已经确定了主分片数(默认5分片),但是副本分片数可以随时修改。
- Replaction:
- 一个分片可以是主分片或者副本分片
- 主分片可以用来写入和读取数据
- 副本分片负责读取数据 主分片和副本分片的状态决定了集群的健康状态,相同的副本分片不会存在于同一个节点中
9.2. ES数据Write流程
-
名词类比HBase
- Shard ---- Region
- Lucene ----- buffer ---- 系统缓存
- Segment ----- MemStore
- 写出Segment ---- stroefile
- TransLog ---- Hlog
-
Shard和Replicaion的路由规则
- 每个Index由多个Shard组成,每个Shard有一个主节点和多个副本节点,副本个数可配。
- 但每次写入的时候,写入请求会先根据 _routing 规则选择发给哪个Shard
- Index Request中可以设置使用哪个Filed的值作为路由参数。
- Index设置 > Mapping配置 > id的Hash值 —> 选出 Primary Shard
- 请求会发数据送给Primary Shard,在Primary Shard上执行成功后,再从Primary Shard上将请求同时发送给多个Replica Shard。
-
数据安全策略
- Elasticsearch里为了减少磁盘IO保证读写性能,一般是每隔一段时间才会把Lucene的 Segment写入磁盘持久化
- Elasticsearch学习了数据库中的处理方式:增加CommitLog模块,Elasticsearch中叫 TransLog。
- 写入请求到达Shard后,先写buffer文件,创建好索引,此时索引还在内存里面,接着去写 TransLog 。
- 写完TransLog后,刷新TransLog数据到磁盘上,写磁盘成功后,请求返回给用户。
- 写buffer后,文档并不是可被搜索的,需要通过Refresh把内存的对象转成完整的Segment后,然后再次reopen后才能被搜索 。发生断电,则这些文档可能会丢失。
- 一般这个时间设置为1秒钟,导致写入Elasticsearch的文档,最快要1秒钟才可被从搜索到。
- 每隔一秒将生成一个新的segment,而translog文件将越来越大。
- 每隔30分钟或者translog文件变得很大,则执行一次fsync操作。此时所有在文件系统 缓存中的segment将被写入磁盘,而translog将被删除
9.3. ES写入数据完整流程
- 红色:Client Node(协调节点)
- 绿色:Primary Node(主分片节点)
- 蓝色:Replica Node(副本分片节点)
9.4. ES数据Update流程
- ES的索引是不能修改的,因此更新和删除操作并不是直接在原索引上直接执行。
- update —》 delect+add
- 收到Update请求后,从Segment或者TransLog中读取同id的完整Doc,记录版本号为V1 = 345
- 将版本V1的全量Doc和请求中的部分字段Doc合并为一个完整的Doc,同时更新内存中的 VersionMap 。
- 获取到完整Doc后,Update请求就变成了Post/Put请求。
- 加锁。 再次从versionMap中读取该id的最大版本号V2 = 346
- 检查版本是否冲突(V1==V2),如果冲突,则回退到开始的“Update doc”阶段,重新执行。如果不冲 突,则执行最新的Add请求。
- 在Index Doc阶段,首先将Version + 1得到V3,再将Doc加入到Lucene中去,Lucene中会先删同 id下的已存在doc id,然后再增加新Doc。写入Lucene成功后,将当前V3更新到versionMap中。
- 释放锁,部分更新的流程就结束了。
9.5. ES数据Delete流程
如果是删除请求的话,提交的时候会生成一个.del文件,里面将某个doc标识为 deleted状态,那么搜索的时候根据.del文件就知道这个doc被删除了,客户端搜索的时候,发现数据在.del文件中标志为删除就不会搜索出来了。
合并刷出segment到磁盘上时才会正删除文件。
9.6. ES数据Read流程
- 查询的过程大体上分为查询(query)和取回(fetch)两个阶段。
- 这个节点的任务是广播查询请求到所有相关分片,并将它们的响应整合成全局排序后的结果集合, 这个结果集合会返回给客户端
- 查询过程
- 当一个节点接收到一个搜索请求,则这个节点就变成了协调节点。 如果客户端要求返回结果排序中从第from名开始的数量为size的结果集,则每个节点都需要生成一个from+size大小的结果集
- 分片仅会返回一个轻量级的结果给协调节点,包含结果集中的每一个文档的ID和进行排序所需要的信息
- 协调节点会将所有分片的结果汇总,并进行全局排序,得到最终的查询排序结果
- 取回过程
- 协调节点会确定实际需要返回的文档,并向含有该文档的分片发送get请求;
- 分片获取文档返回给协调节点;协调节点将结果返回给客户端。
- 相关性计算
- 判别文档与搜索条件的相关程度
- TFIDF
- BM25评分算法
9.7. 实时性
Elasticsearch的主要应用场景就是实时,但Elasticsearch本身并非实时而是near-real-time(近实 时)。Index的实时性是由refresh控制的,默认是1s,最快可到100ms,那么也就意味着Index doc成功后,需要等待一秒钟后才可以被搜索到。
一般这个时间设置为1秒钟,导致写入Elasticsearch的文档最快要1秒钟才可被从搜索到,所以 Elasticsearch在搜索方面是NRT(Near Real Time)近实时的系统。
9.8. 可靠性
- 搜索系统对可靠性要求都不高,丢失数据通过备份找回。
- 通过设置TransLog的Flush频率可以控制可靠性,要么是按请求,每次请求都 Flush;要么是按时间,每隔一段时间Flush一次。
- 一般为了性能考虑,会设置为每隔5秒或者1分钟Flush一次,Flush间隔时间越长,可靠性就会越 低。