什么是副本分片? |
副本分片的主要目的就是为了故障转移,若是持有主分片的节点挂掉了,一个副本分片就会晋升为主分片的角色。node
在索引写入时,副本分片作着与主分片相同的工做。新文档首先被索引进主分片而后再同步到其它全部的副本分片。增长副本数并不会增长索引容量。python
不管如何,副本分片能够服务于读请求,若是你的索引也如常见的那样是偏向查询使用的,那你能够经过增长副本的数目来提高查询性能,但也要为此,增长额外的硬件资源。linux
Elasticsearch内部分片处理机制 |
逆向索引shell
与传统的数据库不一样,在Elasticsearch中,每一个字段里面的每一个单词都是能够被搜索的。如teacher:“zls,bgx,lidao,oldboy,alex”咱们在搜索关键字oldboy时,全部包含oldboy的文档都会被匹配到Elasticsearch的这个特性也叫作全文搜索。数据库
为了支持这个特性,Elasticsearch中会维护一个叫作“invertedindex”(也叫逆向索引)的表,表内包含了全部文档中出现的全部单词,同时记录了这个单词在哪一个文档中出现过。json
例:vim
当前有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用户在建立索引时通用会考虑一个重要问题是:我须要建立多少个分片?
分片分配是个很重要的概念, 不少用户对如何分片都有所疑惑, 固然是为了让分配更合理. 在生产环境中, 随着数据集的增加, 不合理的分配策略可能会给系统的扩展带来严重的问题。
同时, 这方面的文档介绍也很是少。不少用户只想要明确的答案而不只仅一个数字范围, 甚至都不关心随意的设置可能带来的问题。
首先,咱们须要了解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 集群运行正常