第二章·Elasticsearch内部分片及分片处理机制介绍
一、副本分片介绍
什么是副本分片? |
副本分片的主要目的就是为了故障转移,如果持有主分片的节点挂掉了,一个副本分片就会晋升为主分片的角色。
在索引写入时,副本分片做着与主分片相同的工作。新文档首先被索引进主分片然后再同步到其它所有的副本分片。增加副本数并不会增加索引容量。
无论如何,副本分片可以服务于读请求,如果你的索引也如常见的那样是偏向查询使用的,那你可以通过增加副本的数目来提升查询性能,但也要为此,增加额外的硬件资源。
Elasticsearch内部分片处理机制 |
逆向索引
与传统的数据库不同,在Elasticsearch中,每个字段里面的每个单词都是可以被搜索的。如teacher:“zls,bgx,lidao,oldboy,alex”我们在搜索关键字oldboy时,所有包含oldboy的文档都会被匹配到Elasticsearch的这个特性也叫做全文搜索。
为了支持这个特性,Elasticsearch中会维护一个叫做“invertedindex”(也叫逆向索引)的表,表内包含了所有文档中出现的所有单词,同时记录了这个单词在哪个文档中出现过。
例:
当前有4个文档
txt1:“zls,bgx,lidao”
txt2:“zls,oldboy,alex”
txt3:“bgx,lidao,oldboy”
txt4:“oldboy,alex”
那么Elasticsearch会维护下面一个数据结构表:
Term | txt1 | txt2 | txt3 | txt4 |
---|---|---|---|---|
zls | Y | Y | ||
bgx | Y | Y | ||
lidao | Y | Y | ||
oldboy | Y | Y | Y | |
alex | Y | Y |
随意搜索任意一个单词,Elasticsearch只要遍历一下这个表,就可以知道有些文档被匹配到了。
逆向索引里面不止记录了单词与文档的对应关系,它还维护了很多其他有用的数据。如:每个文档一共包含了多少个单词,单词在不同文档中的出现频率,每个文档的长度,所有文档的总长度等等。这些数据用来给搜索结果进行打分,如搜索zls时,那么出现zls这个单词次数最多的文档会被优先返回,因为它匹配的次数最多,和我们的搜索条件关联性最大,因此得分也最多。
逆向索引是不可更改的,一旦它被建立了,里面的数据就不会再进行更改。这样做就带来了以下几个好处:
1.没有必要给逆向索引加锁,因为不允许被更改,只有读操作,所以就不用考虑多线程导致互斥等问题。
2.索引一旦被加载到了缓存中,大部分访问操作都是对内存的读操作,省去了访问磁盘带来的io开销。
3.因为逆向索引的不可变性,所有基于该索引而产生的缓存也不需要更改,因为没有数据变更。
4.使用逆向索引可以压缩数据,减少磁盘io及对内存的消耗。
Segment |
既然逆向索引是不可更改的,那么如何添加新的数据,删除数据以及更新数据?为了解决这个问题,lucene将一个大的逆向索引拆分成了多个小的段segment。每个segment本质上就是一个逆向索引。在lucene中,同时还会维护一个文件commit point,用来记录当前所有可用的segment,当我们在这个commit point上进行搜索时,就相当于在它下面的segment中进行搜索,每个segment返回自己的搜索结果,然后进行汇总返回给用户。
引入了segment和commit point的概念之后,数据的更新流程如下图:

1.新增的文档首先会被存放在内存的缓存中
2.当文档数足够多或者到达一定时间点时,就会对缓存进行commit
a. 生成一个新的segment,并写入磁盘
b. 生成一个新的commit point,记录当前所有可用的segment
c. 等待所有数据都已写入磁盘
3.打开新增的segment,这样我们就可以对新增的文档进行搜索了
4.清空缓存,准备接收新的文档
二、Elasticsearch如何合理分配索引分片
为什么要考虑副本分片数量? |
大多数ElasticSearch用户在创建索引时通用会考虑一个重要问题是:我需要创建多少个分片?
分片分配是个很重要的概念, 很多用户对如何分片都有所疑惑, 当然是为了让分配更合理. 在生产环境中, 随着数据集的增长, 不合理的分配策略可能会给系统的扩展带来严重的问题。
同时, 这方面的文档介绍也非常少。很多用户只想要明确的答案而不仅仅一个数字范围, 甚至都不关心随意的设置可能带来的问题。
首先,我们需要了解ES中以下几个名词,是做什么的:
集群(cluster):由一个或多个节点组成, 并通过集群名称与其他集群进行区分
节点(node):单个ElasticSearch实例. 通常一个节点运行在一个隔离的容器或虚拟机中
索引(index):在ES中, 索引是一组文档的集合(就是我们所说的一个日志)
分片(shard):因为ES是个分布式的搜索引擎, 所以索引通常都会分解成不同部分, 而这些分布在不同节点的数据就是分片. ES自动管理和组织分片, 并在必要的时候对分片数据进行再平衡分配, 所以用户基本上不用担心分片的处理细节,一个分片默认最大文档数量是20亿.
副本(replica):ES默认为一个索引创建5个主分片, 并分别为其创建一个副本分片. 也就是说每个索引都由5个主分片成本, 而每个主分片都相应的有一个copy.
对于分布式搜索引擎来说, 分片及副本的分配将是高可用及快速搜索响应的设计核心.主分片与副本都能处理查询请求, 它们的唯一区别在于只有主分片才能处理索引请求.
谨慎分片 |
副本对搜索性能非常重要, 同时用户也可在任何时候添加或删除副本。额外的副本能给你带来更大的容量, 更高的呑吐能力及更强的故障恢复能力。
当在ElasticSearch集群中配置好你的索引后, 你要明白在集群运行中你无法调整分片设置。既便以后你发现需要调整分片数量, 你也只能新建创建并对数据进行重新索引(reindex)(虽然reindex会比较耗时, 但至少能保证你不会停机)。
主分片的配置与硬盘分区很类似, 在对一块空的硬盘空间进行分区时, 会要求用户先进行数据备份, 然后配置新的分区, 最后把数据写到新的分区上。
在分片时,主要考虑数据集的增长趋势,一定要做到不要过度分片,并不是分片越多越好,从ES社区用户对这个热门主题(分片配置)的分享数据来看, 用户可能认为过度分配是个绝对安全的策略(这里讲的过度分配是指对特定数据集, 为每个索引分配了超出当前数据量(文档数)所需要的分片数)。
稍有富余是好的, 但过度分配分片却是大错特错. 具体定义多少分片很难有定论, 取决于用户的数据量和使用方式. 100个分片, 即便很少使用也可能是好的;而2个分片, 即便使用非常频繁, 也可能是多余的.
我们要熟知以下几点内容:
1.每分配一个分片,都会有额外的成本。
2.每个分片本质上就是一个Lucene索引,因此会消耗相应的文件句柄,内存和CPU资源。
3.每个搜索请求会调度到索引的每个分片中。如果分片分散在不同的节点倒是问题不太。但当分片开始竞争相同的硬件资源时,性能便会逐步下降。
4.ES使用词频统计来计算相关性。当然这些统计也会分配到各个分片上。如果在大量分片上只维护了很少的数据,则将导致最终的文档相关性较差。
大规模数据集场景 |
如果真的担心数据的快速增长, 我们建议你多关心这条限制: ElasticSearch推荐的最大JVM堆空间是30~32G, 所以把你的分片最大容量限制为30GB, 然后再对分片数量做合理估算. 例如, 你认为你的数据能达到200GB, 我们推荐你最多分配7到8个分片.
总之, 不要现在就为你可能在三年后才能达到的10TB数据做过多分配. 如果真到那一天, 你也会很早感知到性能变化的.
尽管本部分并未详细讨论副本分片, 但我们推荐你保持适度的副本数并随时可做相应的增加. 如果你正在部署一个新的环境, 也许你可以参考我们的基于副本的集群的设计.这个集群有三个节点组成, 每个分片只分配了副本. 不过随着需求变化, 你可以轻易的调整副本数量.
对大数据集, 我们非常鼓励你为索引多分配些分片--当然也要在合理范围内. 上面讲到的每个分片最好不超过30GB的原则依然使用.
不过, 你最好还是能描述出每个节点上只放一个索引分片的必要性. 在开始阶段, 一个好的方案是根据你的节点数量按照1.5~3倍的原则来创建分片. 例如:如果你有3个节点, 则推荐你创建的分片数最多不超过9(3x3)个.
随着数据量的增加,如果你通过集群状态API发现了问题,或者遭遇了性能退化,则只需要增加额外的节点即可. ES会自动帮你完成分片在不同节点上的分布平衡.
再强调一次, 虽然这里我们暂未涉及副本节点的介绍, 但上面的指导原则依然使用: 是否有必要在每个节点上只分配一个索引的分片. 另外, 如果给每个分片分配1个副本, 你所需的节点数将加倍. 如果需要为每个分片分配2个副本, 则需要3倍的节点数.
总结 |
再次声明, 数据分片也是要有相应资源消耗,并且需要持续投入.
当索引拥有较多分片时, 为了组装查询结果, ES必须单独查询每个分片(当然并行的方式)并对结果进行合并. 所以高性能IO设备(SSDs)和多核处理器无疑对分片性能会有巨大帮助. 尽管如此, 你还是要多关心数据本身的大小,更新频率以及未来的状态. 在分片分配上并没有绝对的答案, 只希望大家能从本博客中受益.
三、分片操作实战
分片 |
正如上文中提到,创建分片,不超过3倍,在本课程中,我们有两个节点,所以我们可以设置6个分片。
#在每个节点上执行,分配1个副本6个分片
[root@elkstack01 ~]# curl -XPUT 10.0.0.51:9200/_template/my_template -d'
{ "template": "*",
"settings": {
"index": {
"number_of_shards": 6,
"number_of_replicas": 1
}
}
}'
#返回结果为true,分片成功
{"acknowledged":true}
测试提交数据 |
打开浏览器,访问:http://10.0.0.51:9100/

验证索引及页面详解 |

主节点和副本节点的区别 |
主节点的职责:
统计各node节点状态信息、集群状态信息统计、索引的创建和删除、索引分配的管理、关闭node节点等。
副本节点的职责:
同步数据,等待机会成为Master(当主节点宕机或者重启时)。
四、集群检测实战
检测集群状态 |
在linux中,我们可以通过curl命令获取集群的状态.
[root@elkstack02 ~]# curl –sXGET http://10.0.0.51:9200/_cluster/health?pretty=true
执行结果如下图所示:
获取到的是一个json格式的返回值,那就可以通过python对其中的信息进行分析,例如对status进行分析,如果等于green(绿色)就是运行在正常,等于yellow(黄色)表示副本分片丢失,red(红色)表示主分片丢失。

python脚本检测 |
#编写python脚本
[root@elkstack01 ~]# vim es_cluster_status.py
#!/usr/bin/env python
#coding:utf-8
#Author:_DriverZeng_
#Date:2017.02.12
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr
import subprocess
body = ""
false = "false"
clusterip = "10.0.0.51"
obj = subprocess.Popen(("curl -sXGET http://"+clusterip+":9200/_cluster/health?pretty=true"),shell=True, stdout=subprocess.PIPE)
data = obj.stdout.read()
data1 = eval(data)
status = data1.get("status")
if status == "green":
print "\033[1;32m 集群运行正常 \033[0m"
elif status == "yellow":
print "\033[1;33m 副本分片丢失 \033[0m"
else:
print "\033[1;31m 主分片丢失 \033[0m"
#执行结果如下
[root@elkstack01 ~]# python es_cluster_status.py
集群运行正常
第二章·Elasticsearch内部分片及分片处理机制介绍的更多相关文章
- <Mastering KVM Virtualization>:第二章 KVM内部原理
在本章中,我们将讨论libvirt.QEMU和KVM的重要数据结构和内部实现.然后,我们将深入了解KVM下vCPU的执行流程. 在这一章,我们将讨论: libvirt.QEMU和KVM的内部运作方式. ...
- 第二章 深入分析Java I/O的工作机制(待续)
Java的I/O类库的基本架构 磁盘I/O工作机制 网络I/O工作机制 NIO的工作方式 I/O调优 设计模式解析之适配器模式 设计模式解析之装饰器模式 适配器模式与装饰器模式的区别
- 第二章、前端之css
目录 第二章.前端之css 一.css介绍 二.css语法 三.css几种引入方式 四.css选择器 五.css属性相关 六.css盒子模型 第二章.前端之css 一.css介绍 css(Cascad ...
- 学习Zookeeper之第3章Zookeeper内部原理
第 3 章 Zookeeper 内部原理 3.1 选举机制 3.2 节点类型 3.3 stat 结构体 3.4 监听器原理 1)监听原理详解 2)常见的监听 3.5 写数据流程 第 3 章 Z ...
- 实例展示elasticsearch集群生态,分片以及水平扩展.
elasticsearch用于构建高可用和可扩展的系统.扩展的方式可以是购买更好的服务器(纵向扩展)或者购买更多的服务器(横向扩展),Elasticsearch能从更强大的硬件中获得更好的性能,但是纵 ...
- 第43章:MongoDB-集群--Sharding(分片)--多机的搭建
①环境准备 服务器规划 服务器[192.168.0.75] 服务器[192.168.0.84] 服务器[192.168.0.86] mongos mongos mongos config server ...
- 第41章:MongoDB-集群--Sharding(分片)
①Sharding分片概念 分片(sharding)是指将数据库拆分,将其分散在不同的机器上的过程.将数据分散到不同的机器上,不需要功能强大的服务器就可以存储更多的数据和处理更大的负载. 分片是每个分 ...
- 第01章 ElasticSearch简介
本章内容 Apache Lucene是什么. Lucene的整体架构. 文本分析过程是如何实现的. Apache Lucene的查询语言及其使用方法. ElasticSearch的基本概念. ELas ...
- 简学Python第二章__巧学数据结构文件操作
#cnblogs_post_body h2 { background: linear-gradient(to bottom, #18c0ff 0%,#0c7eff 100%); color: #fff ...
随机推荐
- linux定时脚本:删除linux/HDFS上过期文件
一.定时删除linux上定时的文件 显示20分钟前的文件 -exec ls -l {} \; 删除20分钟前的文件 -exec rm {} \; 显示20天前的文件 -exec ls -l {} \; ...
- Java内部类(2):普通的成员内部类
在成员内部类中要注意两点 第一:成员内部类中不能存在任何static的变量和方法: 第二:成员内部类是依附于外围类的,所以只有先创建了外围类才能够创建内部类. 接下来是两个例子(关键字:.this . ...
- [ES6 系列] 你真的了解ES6吗(一)
前言 无论是我们日常开发还是面试跳坑, ES6 已经变得越来越重要,那么你是否对它足够熟悉呢 ES6 将会是专栏接下来的一个系列,从最基础的概念或者有趣的问题开始逐渐深入,探究 ES6 常用的特性以及 ...
- 算法题--Z字形变换
题目描述 将一个给定字符串根据给定的行数,以从上往下.从左到右进行 Z 字形排列. 比如输入字符串为 "LEETCODEISHIRING" 行数为 3 时,排列如下: L C I ...
- 又做了个新的Blog
http://inkhin.com 服务器比较渣,访问不了的请见谅.
- 通过火狐谋智查询API
谋智中文版网址 https://developer.mozilla.org 示例 site: developer.mozilla.org window 通过百度高级用法查API site: 网址 搜索 ...
- 自学电脑游戏第四天(Swing)
继续之前的 3.组合框(JComboBox) 例题:利用JComboBox设计一个选择城市的程序. import java.awt.*; import javax.swing.*; public cl ...
- ARST第四周打卡
Algorithm : 做一个 leetcode 的算法题 ////////////////////////////////////////////////////////////////////// ...
- JZOJ.1150【贪心算法】IQ
欢迎转载,请附上原链接https://www.cnblogs.com/Code-Garden/p/11276741.html(也没人会看) 一道对我来说较难的贪心题 题目描述 根据世界某权威学会的一项 ...
- GCD and LCM HDU - 4497(质因数分解)
Problem Description Given two positive integers G and L, could you tell me how many solutions of (x, ...