前言
ElasticSearch设计理念就是分布式检索框架。
底层是搜索引擎鼻祖Lucene。es对Lucend的操作都封装成了restful的api,通过http请求可以对其进行操作;同时实现了分布式来存储海量数据。
核心概念
index-索引
相当于mysql中的DB概念。es中存储数据的基本单位就是索引。比如需要在es中存储用户信息,就需要在es中创建一个索引user_idx,然后就可以将用户数据存到这个索引里边。
mapping-映射
mysql表有表结构,而mapping就相当于mysql中的表结构,定义了索引里边,每个字段的类型、字段使用的分词器等。
document-文档
相当于mysql中的一行数据,index里面单条记录称为document,每个document有多个field,每个field就代表了这个document中的一个字段,许多document构成一个index。
同一个index里面的document,不要求有相同的结构,但是最好保持相同,这样有利于提高搜索效率。
type-类型
type可以看做是mysql中的表,而且这个概念在6.x 版只允许每个 Index 包含一个 Type;在ES7.X以后,就逐步移除了。
就如type的本意分类,在index里边,document也可以分类,比如衣服,可以按大人、小孩分类,也可以按春装、冬装分类,是虚拟的逻辑分组,用来过滤document。
如果是性质完全不同的数据,比如衣服和家电,应该存成两个index。
核心原理
es之所以可以实现快速查找,核心就是倒排索引。有倒排索引,就有正向索引。
正向索引,就像我们的记忆一样,比如问自己,哪些歌词带“月”呢?—我们的思维方式是,脑中记忆了很多首歌,一首首回想那首带“月”,当脑海中歌词量大的时候,所以就会很慢的到结果了。
倒排索引就神奇了,存储歌词的时候,会以“月”为key,带月的歌词作为value,类似这样:
这样的话,当需要记起带月的歌词的时候,就很快了。
倒排索引简单实例
倒排索引可以构建的简单些,也可以复杂些,相对复杂的倒排索引,存储的内容更多,更方便于查找。
比如存储下边5句话,建立倒排索引,存储的每个内容,会有一个文档编号:
将每条内容进行分词后,切分成单词,并编号处理,为每个单词赋予一个唯一的单词编号,同时记录哪些文档包含这个单词。在如此处理后,可以得到如下内容,第二栏是切分后的单词,第一栏是单词id,第三栏是文档id,标识这些文档均包含该单词。
上边是构建的一个相对简单的倒排索引,再复杂写的倒排索引,还可以包含单词的频率,以及在文档中的位置,可以实现快速定位,如下所示,第三栏文档频率代表文档集合中有多少个文档包含该单词;第四栏代表倒排列表,内容包含DocId、TF、POS,DocId表示单词出现过的文档id、TF标识单词在某个文档出现的次数、POS表示单词在文档中的位置。
这样就是一个相对复杂的,也相对比较完备的倒排索引系统了。
搭建es集群
es开箱即可使用,实现分布式,不需要依赖第三方,内置分布式组件。
1、配置master节点
下载解压,修改config\elasticsearch文件,注意空格
# 集群名
cluster.name: es-cluster
# 节点名
node.name: es-master
# 该节点是否有资格选举为master
node.master: true
network.host: 127.0.0.1
然后执行bin\elasticsearch,即可启动
2、配置slave1节点
cluster.name: es-cluster
node.name: es-slave1
node.master: true
network.host: 127.0.0.1
http.port: 8200
# 和主节点保持心跳
discovery.zen.ping.unicast.hosts: ["120.0.0.1"]
3、配置slave2节点
cluster.name: es-cluster
node.name: es-slave2
node.master: true
network.host: 127.0.0.1
http.port: 7200
# 和主节点保持心跳
discovery.zen.ping.unicast.hosts: ["120.0.0.1"]
es集群管理平台–cerebro
cerebro一款全能的ES工具,安装配置简单,功能强大。可以监控集群、配置集群、操作ES数据;
下载地址:github下载
安装及启动
解压后,我们需要修改conf目录下的application.conf文件
hosts = [
{
host = "http://localhost:9200"
name = "es-test"
}
# Example of host with authentication
#{
# host = "http://some-authenticated-host:9200"
# name = "Secured Cluster"
# auth = {
# username = "username"
# password = "secret-password"
# }
#}
]
然后启动, ./bin/cerebro 默认9000端口 ,如果端口有冲突,可以使用-Dhttp.port指定端口启动
/bin/cerebro -Dhttp.port=8800 -Dhttp.address=0.0.0.0
启动界面如下:
界面介绍
输入节点访问地址即可进入:
在overview栏,我们可以在第一列看到es的三个节点,剩下的五列是5个index,及每个index对应的分片分布状态。
在nodes栏,我们可以看到es的三个节点的状态。
es分布式高级特性
分布式特性
es支持集群模式,是一个分布式系统,其好处主要有两个:
- 增大系统容量,如内存,磁盘,使得es集群可以支持PB级别的数据;
- 提高系统可用性,即使部分节点停止服务,整个集群依然可以正常服务;
es集群由多个es实例组成:
- 不同集群通过集群名字来区分,可通过cluster.name来进行修改,默认为elasticsearch;
- 每个es实例本质上是一个JVM进程,有自己的名字,可以通过node.name来进行修改;
可视化插件可以用我们上边介绍的Cerebro,也可以用Elasicsearch-head。
副本和分片
为什么需要分片和备份? 假设一个索引的数据量很大,就会造成硬盘的存储压力很大,同时搜索速度也会出现瓶颈。比如,一个具有10亿文档的索引占据1TB的磁盘空间,而任一节点都没有这样大的磁盘空间;或者单个节点处理搜索请求,响应太慢。
因此ElasticSearch将索引分成若干份,每个部分就是一个shard。那么,就可以将索引分成多个分片存储,从而分摊压力。分片还允许用户对其进行水平地扩展和拆分,以及分布式的操作,可以提高搜索以及其他操作的效率。
分片数默认为5个,分片储存了部分数据,可以分布在任意节点上;
从上图我们可以看到,实线是5个主分片,虚线是5个副分片,副分片肯定和主分片不在同一节点,保证es的高可用;
副分片的数据由主分片同步,可以有多个,从而提高读取的吞吐量;
每个分片推荐大小为10G-30G;分片数量推荐=节点数量*1~3倍
状态
集群健康状态可以通过颜色来判断:
green 健康状态,指所有主副分片都正常分配;
yellow 指所有主分片都正常分配,但是有副分片未正常分配;
red 有主分片未分配;
三种状态只是代表分片的工作状态,并不是代表整个es集群是否能够对外提供服务。
故障转移
es集群有三个几点,三个主副分片,如果一个节点宕机导致服务终止,此时集群会如何处理呢?
分布式存储
es存储数据最终会存储到分片上,但是如何决定存储到哪个分片呢?选择分片的依据是文档到分片的映射算法。而这套算法的目的就是使得文档均匀分布在所有分片上,以充分利用资源。
算法包括随机选择或者round robin算法;
算法公式如下:
shard = hash(routing)%number_of_primary_shards
注:hash算法可以保证将数据均匀地分散在分片中
routing是一个关键参数,默认是文档id,也可以自行指定
number_of_primary_shards是主分片数
该算法与主分片数相关,所以**分片数一旦确定以后便不能更改**
文档创建流程
- client向node3发起创建文档的请求;
- node3通过routing计算该文档应该存储在分片1上,查询cluster state后确定分片1的主分片P1在node2上,然后转发创建文档的请求到node2;
- P1接收并执行创建文档的请求后,将同样的请求发送到分片1的副分片;
- 分片1 的副分片接收并执行创建文档请求后,通知P1成功的结果;
文档读取的流程
- client向node3发起读取文档的请求;
- node3通过routing计算该文档应该存储在分片1上,查询cluster state后获取分片1的主副分片列表,然后以轮询的机制获取一个shard,比如这里轮询到副分片,就转发读取文档的请求到副分片所在的实例;
- 分片1 的副分片接收并读取文档的请求后,将结果返回给node3;
- node3返回结果给client;
参考文档:什么是倒排索引