EleasticSearch核心原理详细分析
一、前言
1、大规模数据如何检索?
当系统数据量上了10亿、100亿条的时候,我们在做系统架构的时候通常会从以下角度去考虑:
1)用什么数据库好?(MySQL、sybase、Oracle、达梦、神通、MongoDB、Hbase…)
2)如何解决单点故障;(lvs、F5、A10、Zookeep、MQ)
3)如何保证数据安全性;(热备、冷备、异地多活)
4)如何解决检索(查询)难题;(数据库代理中间件:mysql-proxy、Cobar、MaxScale等;)
5)如何解决统计分析问题;(离线、近实时)
2、传统数据库的应对解决方案?
对于关系型数据,我们通常采用以下或类似架构去解决查询瓶颈和写入瓶颈:
解决要点:
1)通过主从 备份解决数据安全性问题;
2)通过数据库代理中间件心跳监测,解决单点故障问题;
3)通过代理中间件将查询语句分发到各个slave节点进行查询,并汇总结果
4)通过分表分库解决读写效率问题
数据库,不适合大规模数据检索,IO瓶颈
3、非关系型数据库的解决方案?
对于Nosql数据库,以redis为例,其它原理类似:
解决要点:
1)通过副本备份保证数据安全性;
2) 通过节点竞选机制解决单点问题;
3)先从配置库检索分片信息,然后将请求分发到各个节点,最后由 路由节点合并汇总结果
nosql(考虑因素:速度) 不适合锁数据检索,关键字搜索
4、完全把数据放入内存怎么样?
完全把数据放在内存中是不可靠的,实际上也不太现实,当我们的数据达到PB级别时,按照每个节点 96G内存计算,在内存完全装满的数据情况下,我们需要的机器是:1PB=1024T=1048576G
节点数=1048576/96=10922个
实际上,考虑到数据备份,节点数往往在2.5万台左右。成本巨大决定了其不现实!
从前面我们了解到,把数据放在内存也好,不放在内存也好,都不能完完全全解决问题。
全部放在内存速度问题是解决了,但成本问题上来了。 为解决以上问题,从源头着手分析,通常会从以
下方式来寻找方法:
1、存储数据时按有序存储;
2、将数据和索引分离;
3、压缩数据;
4、将数据放入内存
二、全文检索技术
1、什么是全文检索?
什么叫做全文检索呢?这要从我们生活中的数据说起。
我们生活中的数据总体分为两种:结构化数据和非结构化数据。
- 结构化数据:指具有固定格式或有限长度的数据,如数据库,元数据等。
- 非结构化数据:指不定长或无固定格式的数据,如 互联网数据、邮件,word文档等。
对非结构化数据顺序扫描很慢,对结构化数据的搜索却相对较快,那么把我们的非结构化数据想办法弄得有一定结构不就行了吗?
这就是全文检索的基本思路,也即将非结构化数据中的一部分信息提取出 来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的 目的。这部分从非结构化数据中提取出的然后重新组织的信息,我们称之索引 。
非结构化数据又一种叫法叫全文数据。
按照数据的分类,搜索也分为两种:
- 对结构化数据的搜索: 如对数据库的搜索,用SQL语句。再如对元数据的搜索,如利用windows搜索对文件名,类型,修改时间进行搜索等。
- 对非结构化数据的搜索: 如用Google和百度可以搜索大量内容数据。
对非结构化数据也即全文数据的搜索主要有两种方法:顺序扫描法和反向索引法。
- 顺序扫描法:所谓顺序扫描法,就是顺序扫描每个文档内容,看看是否有要搜索的关键字,实现查找文档的功能,也就是根据文档找词。
- 反向索引法(倒排索引):所谓反向索引,就是提前将搜索的关键字建成索引,然后再根据索引查找文档,也就是根据词找文档。
这种先建立索引 ,再对索引进行搜索文档的过程就叫 **全文检索(**Full-text Search) 。
把网页数据变成结构化数据?
2、全文检索场景
搜索引擎
站内搜索
系统文件搜索
3、全文检索相关技术
- Lucene:如果使用该技术实现,需要对Lucene的API和底层原理非常了解,而且需要编写大量的 Java代码。
- Solr:使用java实现的一个web应用,可以使用rest方式的http请求,进行远程API的调用。
- ElasticSearch(ES):可以使用rest方式的http请求,进行远程API的调用。
4、Solr和ES的比较
ElasticSearch vs Solr 检索速度
-
当单纯的对已有数据进行搜索时,Solr更快。
-
当实时建立索引时, Solr会产生io阻塞,查询性能较差, Elasticsearch具有明显的优势。
-
随着数据量的增加,Solr的搜索效率会变得更低,而Elasticsearch却没有明显的变化。
-
大型互联网公司,实际生产环境测试,将搜索引擎从Solr转到Elasticsearch以后的平均查询速度有了50倍的提升。
总结:
二者安装都很简单;
- Solr 利用 Zookeeper 进行分布式管理,而 Elasticsearch 自身带有分布式协调管理功能;
- Solr 支持更多格式的数据,而 Elasticsearch 仅支持json文件格式;
- Solr 官方提供的功能更多,而 Elasticsearch 本身更注重于核心功能,高级功能多有第三方插件提 供;
- Solr 在传统的搜索应用中表现好于 Elasticsearch,但在处理实时搜索应用时效率明显低于Elasticsearch。
最终的结论:
Solr 是传统搜索应用的有力解决方案,但 Elasticsearch 更适用于新兴的实时搜索应用
三、全文检索的流程
百度搜索流程
索引不会重复,索引库不会无穷大,文档会无限大,无限多条, 倒排链表对应出现的索引的文明内容了,根据得分来算展示位置,
1、流程总览
全文检索的流程分为两大流程:索引创建、搜索索引
索引创建:将现实世界中所有的结构化和非结构化数据提取信息,创建索引的过程。
搜索索引:就是得到用户的查询请求,搜索创建的索引,然后返回结果的过程。
想搞清楚全文检索,必须要搞清楚下面三个问题:
- 索引库里面究竟存些什么?(Index)
- 如何创建索引?(Indexing)
- 如何对索引进行搜索?(Search)
英文索引创建流程
四、ElasticSearch介绍
1、ES概述
2、ES是什么?
1)ES = elasticsearch简写, Elasticsearch是一个开源的高扩展的分布式全文检索引擎.
2)Elasticsearch也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能。但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单
Elasticsearch是面向文档型数据库,一条数据在这里就是一个文档,用JSON作为文档序列化的格式, 比如下面这条用户数据:
{ “name” : “John”,
“sex” : “Male”,
“age” : 25,
“birthDate”: “1990/05/01”,
“about” : “I love to go rock climbing”,
“interests”: [ “sports”, “music” ] }
3、为什么要使用ES?
-
ES国内外使用优秀案例
- 2013年初,GitHub抛弃了Solr,采取ElasticSearch 来做PB级的搜索。 “GitHub使用ElasticSearch 搜索20TB的数据,包括13亿文件和1300亿行代码”。
- 维基百科:启动以elasticsearch为基础的核心搜索架构。
- 百度:百度目前广泛使用ElasticSearch作为文本数据分析,采集百度所有服务器上的各类指标数据 及用户自定义数据,通过对各种数据进行多维分析展示,辅助定位分析实例异常或业务层面异常。目前覆盖百度内部20多个业务线(包括casio、云分析、网盟、预测、文库、直达号、钱包、风控等),单集群最大100台机器,200个ES节点,每天导入30TB+数据。
-
实际项目开发实战中,几乎每个系统都会有一个搜索的功能,当搜索做到一定程度时,维护和扩展起来 难度就会慢慢变大,所以很多公司都会把搜索单独独立出一个模块,用ElasticSearch等来实现。
近年ElasticSearch发展迅猛,已经超越了其最初的纯搜索引擎的角色,现在已经增加了数据聚合分析 (aggregation)和可视化的特性,如果你有数百万的文档需要通过关键词进行定位时,ElasticSearch 肯定是最佳选择。
当然,如果你的文档是JSON的,你也可以把ElasticSearch当作一种“NoSQL数据库”, 应用
ElasticSearch数据聚合分析(aggregation)的特性,针对数据进行多维度的分析。
4、ES有什么能力?
Elasticsearch 是一个分布式可扩展的实时搜索和分析引擎,一个建立在全文搜索引擎 ApacheLucene™ 基础上的搜索引擎.
实际项目开发实战中,几乎每个系统都会有一个搜索的功能,当数据达到很大且搜索要做到一定程度 时,维护和扩展难度就会越来越高,并且在全文检索的速度上、结果内容的推荐、分析以及统计聚合方 面也很难达到我们预期效果。
并且 Elasticsearch ,它不仅包括了全文搜索功能,还可以进行以下工作:
- 分布式实时文件存储,并将每一个字段都编入索引,使其可以被搜索。(实时的存储、检索数据)
- 实时分析的分布式搜索引擎。
- 可以扩展到上百台服务器,处理PB级别的结构化或非结构化数据。(集群只能支持:上百台 ---- 中等 规模的数据)
检索得分计算
五、ES的架构
1、网关Gateway层
2、DLD 的分布式框架
3、 自动发现Discovery、Script、插件
es是一个集群包含很多节点,discovery模块用来互相发现对方,然后组成一个集群包括选主,默认使用的是 Zen
4、通信(Transport)
节点间通信端口默认:9300-9400,默认内部是使用tcp协议进行交互
Mapping映射︰相当于数据库字段约束【 id int(约束) name varchar(50)约束这样的约束可以限定想写入数据库的写入数据类型】
六、ES集群架构
1、伪集群(单机Node)
1.1、默认节点
场景:
1)单node环境下,创建一个索引index,默认创建5个primary shard,5个replica shard(副本)
2)yellow 红未分配好 绿:健康
3)分片分配:把5个主分片分配到一台机器
4)伪集群可以正常工作的,但是一旦宕机,可能出现数据丢失的现象。而集群不可用。
伪集群启动命令:
bin/elasticsearch -Ecluster.name=c_cluster -Epath.data=my_cluster_node1 -Enode.name=node1 -Ehttp.port=5100 -d
bin/elasticsearch -Ecluster.name=c_cluster -Epath.data=cluster_node0 -Enode.name=node0 -d
1.2、规划节点
PUT /jack_index {
"number_of_shards": 3, #指定3个分片
"number_of_replicas": 1 #一个副本
}
总结:
- es是一个分布式搜索引擎,必须进行多机部署
- es索引存储采用分片进行存储
- es默认创建索引库,主分片数5个,副本个, 分片数量可以设置
2、集群结构
集群:es天然就是一个集群,
es集群特点:
- es集群有master节点,slave节点(一个集群只有一个master,多个slave node几点,理论上node可以无限个,但是,master节点维护着所有的node节点状态信息,元教据维护(索引),一旦node节点太多,master负担过重,导致整个集群性能下降.
- master每隔1秒向node节点发起请求(心跳检测),检测node节点是杏存活
- node节点每隔1s向master发送请求(心跳检测),检测master是否存活,如果master宕机,由其他slave节点升级为master
- 发起一个文档写入,文档最终被写入(主)分片,副本分片只做备份作用,副本分片可以进行数据读操作
ElasticSearch是一个分布式的,高效的搜索框架,底层封装lucence,分布式应对大数据量存储,检索, 关键是:让开发变得简单,隐藏了很多Lucene复杂操作
1)分片机制
2)cluster discovery
- shard分片负载
4)shard副本、请求路由、集群扩容、shard重新分配
2.1、Es集群节点分配
节点类型∶
主节点master
- 维护集群状态,维护元数据
- master节点中可以存储主分片,副本分片
副本节点_slave —在从节点可以实现教据写入
- 维护master状态
- 可以存储主分片,副本分片
协调节点:在默认情况下,么有做任何配配置,默认node.master =true,node.data=true,那么此节点具有三种身份:master slave,协调节点
2.1.1 master主节点 (五角星 表示)
整个集群只会有一个master节点,它将负责管理集群范围内的所有变更,例如增加、删除索引;或者增加、删除节点等。而master节点并不需要涉及到文档级别的变更和搜索等操作,所以当集群只拥有一个master节点的情况下,即使流量的增加它也不会成为瓶颈。
master节点需要从众多候选master节点中选择一个。
master节点的作用:
负责集群节点上下线,shard分片的重新分配。
创建、删除索引。
负责接收集群状态(
cluster state
)的变化,并推送给所有节点。集群节点都各有一份完整的 cluster state,只是master node负责维护。利用自身空闲资源,协调创建索引请求或者查询请求,将请求分发到相关node服务器。
master节点的配置如下(elasticsearch.yml)
node.master: true # 具有选举为master的资格
node.data: false #是否存数据
圆圈 代表slave副本节点
2.1.2data结点(数据节点)
负责存储数据,提供建立索引和搜索索引的服务。
data节点消耗内存和磁盘IO的性能比较大。
node.master:false
node.data: true
2.1.3 协调节点
不会被选作主节点,也不会存储任何索引数据。主要用于查询负载均衡。将查询请求分发给多个node服务 器,并对结果进行汇总处理。
3、ES集群核心概念
3.1、集群(cluster)
代表一个集群,集群中有多个节点(node),其中有一个为主节点,这个主节点是可以通过选举产生的, 主从节点是对于集群内部来说的。
ES的一个概念就是去中心化,字面上理解就是无中心节点,这是对于集群外部来说的,因为从外部来看ES 集群,在逻辑上是个整体,你与任何一个节点的通信和与整个ES集群通信是等价的。
ES集群是一个或多个节点的集合,它们共同存储了整个数据集,并提供了联合索引以及可跨所有节点的搜
索能力。多节点组成的集群拥有冗余能力,它可以在一个或几个节点出现故障时保证服务的整体可用性。
集群靠其独有的名称进行标识,默认名称为“elasticsearch”。节点靠其集群名称来决定加入哪个ES集 群,一个节点只能属一个集群。
3.2、节点(node)
一个节点是一个逻辑上独立的服务,可以存储数据,并参与集群的索引和搜索功能, 一个节点也有唯一 的名字,群集通过节点名称进行管理和通信.
-
主节点
-
数据节点 持有数据和倒排索引
-
客户端节点 (5.0之后被协调节点取代 )
-
部落节点
部落节点可以跨越多个集群,它可以接收每个集群的状态,然后合并成一个全局集群的状态,它可以读写 所有节点上的数据
3.3、索引(Index) !!!注意跟Lucene的索引不是一个概念
ES将数据存储于一个或多个索引中,索引是具有类似特性的文档的集合。类比传统的关系型数据库领域来 说,索引相当于SQL中的一个数据库,或者一个数据存储方案(schema)。索引由其名称(必须为全小写字符)进行标识,并通过引用此名称完成文档的创建、搜索、更新及删除操作并通过ElasticSearch内部 使用Lucene将数据写入索引或从索引中检索数据。一个ES集群中可以按需创建任意数目的索引。
3.4、文档类型(Type)
类型是索引内部的逻辑分区(category/partition),然而其意义完全取决于用户需求。因此,一个索 引内部可定义一个或多个类型(type)。一般来说,类型就是为那些拥有相同的域的文档做的预定义。例 如,在索引中,可以定义一个用于存储用户数据的类型,一个存储日志数据的类型,以及一个存储评论数 据的类型。类比传统的关系型数据库领域来说,类型相当于“表”。
注意!!!
6.0之后删除了Type的概念,一个索引中只能有一个类型,原因:type本来就跟表的概念不一样,table 在数据库中是独立存储的,ES中不同的type存储在同一个索引中的相同字段会映射到一起,例如:学生 表中的name和班级表中的name,索引中会指向同一处,而且数据类型不能不同。
3.5、文档(Document)
文档是Lucene索引和搜索的原子单位,它是包含了一个或多个域的容器,基于JSON格式进行表示。文档 由一个或多个域组成,每个域拥有一个名字及一个或多个值,有多个值的域通常称为“多值域”。每个文档 可以存储不同的域集,但同一类型下的文档至应该有某种程度上的相似之处。相当于数据库的“记录”
一个索引库只有一个type、一张表
put /Java/index/1 Java为库,index为type 1为id,,
注意:类型type 在elasticsearch 6.0 已废弃。
举个例子: 在索引库存储中,
存在如下情况: 学生表: name 属性, 用户表:name属性 在索引库中存储的索引指向同一个索引,既然这样,废弃类型。
3.6、映射(Mapping)
相当于数据库中的schema,用来约束字段的类型,不过 Elasticsearch 的 mapping 可以自动根据 数据创建 ES中,所有的文档在存储之前都要首先进行分析。用户可根据需要定义如何将文本分割成token、哪些 token应该被过滤掉,以及哪些文本需要进行额外处理等等。
开发经验∶
在开发中,先建立mapping映纣文件,建立此文件相当于建立数据库,建立表结果。
更方便开发方式:
自己向索引库写入数据,自动生成mapping映的文件,然后在修改。
3.7、分片和复制(shards and replicas)
一个索引可以存储超出单个结点硬件限制的大量数据。比如,一个具有10亿文档的索引占据1TB的磁盘空间,而任一节点可能没有这样大的磁盘空间来存储或者单个节点处理搜索请求,响应会太慢。为了解决这个问题,Elasticsearch提供了将索引划分成多片的能力,这些片叫做分片。
ES的“分片(shard)”机制可将一个索引内部的数据分布地存储于多个节点,它通过将一个索引切分为多个底层物理的Lucene索引完成索引数据的分割存储功能,这每一个物理的Lucene索引称为一个分片 (shard)。分片分布到不同的节点上。构成分布式搜索。
每个分片其内部都是一个全功能且独立的索引,因此可由集群中的任何主机存储。创建索引时,用户可指定其分片的数量,默认数量为5个。分片的数量只能在索引创建前指定,并且索引创建后不能更改。 Shard有两种类型:primary和replica,即主shard及副本shard。
Primary shard
用于文档存储,每个新的索引会自动创建5个Primary shard,当然此数量可在索引创建之前通过配置 自行定义,不过,一旦创建完成,其Primary shard的数量将不可更改。
Replica shard
是Primary Shard的副本,用于冗余数据及提高搜索性能。
每个Primary shard默认配置了一个Replica shard,但也可以配置多个,且其数量可动态更改。ES 会根据需要自动增加或减少这些Replica shard的数量。
副本的作用:
一是提高系统的容错性,当个某个 节点某个分片损坏或丢失时可以从副本中恢复。
二是提高es的查询效率,es会自动对搜索请求进行负载均 衡。