前言
全文检索
数据分类:
- 结构化数据:固定长度,格式,如mysql存的数据。
非结构化数据
:不定长,无固定格式。如word文档,日志等。半结构化数据
:前两者结合:如xml,html。
搜索分类:
- 结构化数据:关系型数据库
- 非结构化数据:
- 顺序扫描
全文检索
思考场景:假设我们要搜索诗句中带"前"的句子
name | content | author |
---|---|---|
静夜思 | 举头望明月,低头思故乡 | 李白 |
望庐山瀑布 | 日照香炉生紫烟,遥看瀑布挂前川 | 李白 |
如果是mysql
:
select * from poems where content like %前%;
这叫顺序扫描
法,需要遍历所有的记录进去匹配,效率低,而且可能得不到我们想要的结构。
什么是全文搜索引擎
计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。这种建立索引的方式叫倒排索引。
比如:百度网站搜索根据网页中的关键字生成索引,我们在搜索的时候输入关键字,它们会将该关键字即索引匹配到的所有网页。对于这些非结构化的数据文本,关系型数据库搜索不是能很好的支持。
倒排索引的示例
如用户如果要搜索 hello
对应会找到index
为1,2
的数据。
**个人理解:正向索引:通过key找value,通过value找key。**
es底层检索时底层使用倒排索引的方法。
Elasticsearch概述
Elasticsearch是用Java开发并且是一个开源的高扩展的分布式,restful全文搜索引擎。能够达到实时搜索,稳定,可靠,快速,扩展性很好,安装使用方便。
ElasticSearch与Lucene的关系
起源:Lucene。
特点:高性能,易扩展。
局限: 只能使用java开发;学习成本比较高;不支持水平扩展。
Elasticsearch
是构建找lucene
之上的分布式搜索引擎。
- 支持分布式,可水平扩展。
- 多语言调用。
- 完美的继承lucene核心库,设计rest-api,开箱即用。
- 分片和副本机制,解决高可用的问题。
ElasticSearch vs Solr
Solr
是第一个基于 Lucene
核心库功能完备的搜索引擎产品,诞生远早于 Elasticsearch
。
当单纯的对已有数据进行搜索时,Solr更快。当实时建立索引时, Solr会产生io阻塞,查询性能较差, Elasticsearch具有明显的优势。
总结:
Solr
利用Zookeeper
进行分布式管理,而Elasticsearch
自身带有分布式协调管理功能。Solr
支持更多格式的数据,比如JSON、XML、CSV
,而es
仅支持json
文件格式。Solr在传统的搜索应用中表现好于 es,但在处理实时搜索应用时效率明显低于 es
。Solr
是传统搜索应用的有力解决方案,但es
更适用于新兴的实时搜索应用。
应用场景
1.分布式的搜索引擎和数据分析引擎
- 搜索:百度的站内搜索,电商的搜索。
- 数据分析:比如最近一个月的销量前10的商品等。
2.应用性能监控
3.日志管理与分析
4.机器学习
Elasticsearch中的核心概念
ElasticSearch vs 关系型数据库
在7.0之前,一个 Index
可以设置多个Types
目前Type
已经被Deprecated
,7.0开始,一个索引只能创建一个Type - “_doc”
ElasticSearch的核心概念
index索引
一个索引就是一个拥有几分相似特征的文档的集合。比如说,你可以有一个客户数据的索引,另一个产品目录的索引,还有一个订单数据的索引。一个索引由一个名字来标识(必须全部是小写字母),并且当我们要对这个索引中的文档进行索引、搜索、更新和删除(CRUD)的时候,都要使用到这个名字。在一个集群中,可以定义任意多的索引。
Type字段类型
类似于数据库的表,已弃用。
document 文档
Elasticsearch是面向文档的,文档是所有可搜索数据的最小单位。
;- 文档会被序列化成JSON格式,保存在Elasticsearch中;
- 每个文档都有一个ID。
- 一篇文档包含了一系列字段,类似数据库表中的一条记录。
- JSON文档,格式灵活,不需要预先定义格式。
文档元数据
元数据,用于标注文档的相关信息:
_index
:文档所属的索引名_type
:文档所属的类型名_id
:文档唯—ld_source
: 文档的原始Json
数据_version
: 文档的版本号,修改删除操作_version
都会自增1。_seq_no
: 和_version
一样,一旦数据发生更改,数据也一直是累计的。Shard
级别严格递增,保证后写入的Doc
的_seq_no
大于先写入的Doc
的_seq_no
。高版本的更新使用`。_primary_term
:_primary_term
主要是用来恢复数据时处理当多个文档的_seq_no
一样时的冲突,避免Primary Shard
上的写入被覆盖。每当Primary Shard
发生重新分配时,比如重启,Primary
选举等,_primary_term
会递增1。
Field字段
相当于是数据表的字段|列。
ElasticSearch集群核心概念
Cluster集群
ES可以作为一个独立的单个搜索服务器。不过,为了处理大型数据集,实现容错和高可用性,ES可以运行在许多互相合作的服务器上。这些服务器的集合称为集群,集群内的节点的cluster.name
相同。
node节点
- 一个es实例即为一个节点,一台机器可以有多个节点,正常使用下每个实例都应该会部署在不同的机器上。
- 每一个节点都有名字,通过配置文件配置,或者**-E node.name=node1**指定。
ES的配置文件中可以通过node.master、 node.data
来设置节点类型。
node.master
:true/false
表示节点是否具有成为主节点的资格;node.data
:true/false
表示节点是否为存储数据;node.ingest
:true/false
表示节点是否为数据前置处理转换节点;
node
节点的组合方式:
- 主节点+数据节点: 默认方式,节点既可以作为主节点,又存储数据;
- 数据节点Data Node: 节点只存储数据,不参与主节点选举;
- 协调节点Coordinating Node: 不会成为主节点,也不存储数据,主要针对海量请求时进行负载均衡。
Master节点主要负责:
- 管理索引(创建索引、删除索引)、分配分片
- 维护元数据
- 管理集群节点状态
- 不负责数据写入和查询,比较轻量级
数据节点Data Node
:
- 数据节点主要负责:数据写入、数据检索;
- 节点启动后,默认就是数据节点。可以设置node.data:false禁止;
- 由
Master Node
决定如何把分片分发到数据节点上; 通过增加数据节点可以解决数据水平扩展和解决数据单点问题
;
协调节点Coordinating Node
- 负责接受Client的请求,
- 将请求分发到合适的节点,
- 最终把结果汇集到一起
- 每个节点默认都起到了
Coordinating Node
的职责
其他节点类型
Hot & Warm Node
(冷热数据节点)不同硬件配置的Data Node,用来实现Hot & Warm架构,降低集群部署的成本Ingest Node
数据前置处理转换节点,支持pipeline管道设置,可以使用
ingest对数据进行过滤、转换等操作Machine Learning Node
:负责跑机器学习的Job,用来做异常检测
增加节点水平扩展场景
- 当磁盘容量无法满足需求时,可以增加数据节点;磁盘读写压力大时,增加数据节点;
- 当系统中有大量的复杂查询及聚合时候,增加Coordinating节点,增加查询的性能;
读写分离架构
为什么要设计Hot&Warm
架构?
ES
数据通常不会有Update
操作;适用于索引数据,同时数据量比较大的场景。引入 Warm
节点,低配置大容量的机器存放老数据,以降低部署成本。
两类数据节点,
不同的硬件配置:
- Hot节点(通常使用SSD)︰索引不断有新文档写入。
- Warm节点(通常使用HDD)︰索引不存在新数据的写入,同时也不存在大量的数据查询。
使用Shard Filtering
实现Hot&Warm node
间的数据迁移,使用 node.attr
来指定node属性:hot
或是warm
。
Shards分片
一个索引可以存储超出单个节点硬件限制的大量数据。比如,一个具有10亿文档的索引
占据1TB
的磁盘空间,而任一节点
都没有这样大的磁盘空间;或者单个节点处理搜索请求,响应太慢为了解决这个问题,Elasticsearch
提供了将索引划分成多份的能力,这些份就叫做分片。
当创建一个索引的时候,可以指定你想要的分片的数量每个分片本身也是一个功能完善并且独立的“索引”,这个“索引”可以被放置到集群中的任何节点上。分片很重要,主要原因
- 允许水平分割/扩展你的内容容量;
- 增减节点时,
shard
会自动在nodes
中负载均衡; - 一个
文档
只能完整的存放在一个shard
上; - 允许在分片之上进行分布式的、并行的操作,进而提高性能/吞吐量;
至于一个分片怎样分布,它的文档怎样聚合回搜索请求,是完全由Elasticsearch
管理的,对于作为用户来说,这些都是透明的。
replica副本
就是shard的冗余备份,它的主要作用:
- 冗余备份,防止数据丢失;
- shard异常时负责容错和负载均衡;
节点,分片,副本的关系
补充
为什么不用传统数据库?
一般传统数据库,全文检索都实现的很鸡肋,一般也没人用数据库存文本字段。进行全文检索需要扫描整个表,如果数据量大的话即使对SQL
的语法优化收效甚微。建立了索引,但是维护起来也很麻烦,对于 insert
和 update
操作都会重新构建索引。
在一些生产环境中,使用常规的搜索方式(mysql),性能是非常差的:
- 搜索的数据对象是大量的非结构化的文本数据。
- 文件记录量达到数十万或数百万个甚至更多。
- 支持大量基于交互式文本的查询。
- 需求非常灵活的全文搜索查询。
- 对高度相关的搜索结果的有特殊需求,但是没有可用的关系数据库可以满足。
Elasticsearch比MySQL快的原因
- 基于分词后的全文检索:例如
select * from test where name like ‘%张三%’
,对于mysql
来说,因为索引失效,会进行全表检索;对es
而言分词后,每个字都可以利用FST
高速找到倒排索引
的位置,并迅速获取文档id
列表,大大的提升了性能,减少了磁盘IO。 - 精确检索:进行精确检索,有些时候可能
mysql
要快一些,当mysql
的非聚合索引引用上了聚合索引,无需回表,则速度上可能更快;es
还是通过FST
找到倒排索引的位置比获取文档id
列表,再根据文档id
获取文档并根据相关度进行排序。但是es
还有个优势,就是es
即天然的分布式能够在大量数据搜索时可以通过分片降低检索规模
,并且可以通过并行检索提升效率,用filter
时,更是可以直接跳过检索直接走缓存。