Elasticsearch重要文章之三:重要配置项的修改
Elasticsearch已经有很好的默认值,特别是涉及到性能相关的配置或者选项。如果你有什么拿不准的,最好就不要动它。我们已经目睹了数十个因为错误的设置而导致集群毁灭,因为它的管理者总认为他改动一个配置或者选项就可以带来100倍的提升。
注意:请阅读全文,所有的配置项都同等重要,和描述顺序无关,请阅读所有的配置选项,并应用到你的集群中。
其它数据库可能需要调优,但总得来说,Elasticsearch不需要。如果你遇到了性能问题,最好的解决方法通常是更好的数据布局或者更多的节点。在Elasticsearch中有很少的”神奇的配置项”,如果存在,我们也已经帮你优化了。
指定名字
Elasticsearch默认启动的集群名字叫elasticsearch,你最好给你的生产环境的集群改个名字,改名字的目的很简单,就是防止某个人的笔记本加入到了集群,造成意外。简单修改成elasticsearch_production ,会省掉多次心痛~。
你可以在你的elasticsearch.yml中修改:
cluster.name: elasticsearch_production
同样,修改节点的名字也是明智的,就像你现在可能发现的那样,Elasticsearch会在你的节点启动的时候随机给它指定一个名字。这在你开发 的时候可能觉得很萌,但是当凌晨3点钟,你还在尝试会议哪台物理机是Tagak the Leopard Lord.的时候,你就不觉得萌了。
更重要的是,这些名师是在启动的时候产生的,每次启动节点,它都会得到一个新的名字,这可以使日志混淆,因为所有节点的名称都是不断变化的。
这些可能性都是很无聊的,我们建议你给每个及诶点一个有意义的名字-一个清楚的,描述性的名字,同样你可以在elasticsearch.yml中配置:
node.name: elasticsearch_005_data
路径
默认情况下,Eleasticsearch会把插件、日志以及你最重要的数据放在安装目录下。这会带来不幸的事故。即如果你重新安装Elasticsearch的时候就可能不小心把安装目录覆盖了,如果你不小心,你就可能把你的全部数据删掉了。
不要笑,这种情况,我们见过很多次了。
最好的选择就是把你的数据目录配置到安装目录以外的地方,同样你也可以选择转移你的插件和日志目录。
可以更改如下:
path.data: /path/to/data1,/path/to/data2
# Path to log files:
path.logs: /path/to/logs
# Path to where plugins are installed:
path.plugins: /path/to/plugins
注意:你可以通过逗号分隔指定多个目录。
数据可以保存到多个不同的目录,每个目录如果是挂载在不同的硬盘,做一个人RAID 0是一个简单而有效的方式。Elasticsearch会自动把数据分隔到不同的目录,以便提高性能。
最小主节点数
minimum_master_nodes的设定对你的集群的稳定及其重要,当你的集群中有两个masters的时候,这个配置有助于防止集群分裂。
如果你发生了一个集群分裂,你集群就会处在丢失数据的危险中,因为master节点是被认为是这个集群的最高统治者,它决定了什么时候新的索引可以 创建,多少分片要移动等等。如果你有两个master节点,你的数据的完整性将得不到保证,因为你有两个master节点认为他们有集群的控制权。
这个配置就是告诉Elasticsearch当没有足够master候选节点的时候,就不要进行master选举,等master候选节点足够了才进行选举。
该配置必须应该配置成master候选节点的法定个数(大多数个),法定个数就是(master候选节点个数*2)+1. 这里有几个例子:
*如果你有10个节点(能保存数据,同时能成为master) 法定数就是6
*如果你有3个候选master,和100个数据节点,法定数就是2,你只要数数那些可以做master的节点数就可以了。
*如果你有两个节点,你遇到难题了,法定数当然是2,但是这意味着如果有一个节点挂掉,你整个集群就不可用了。设置成1可以保证集群的功能,但是就无法保证集群分裂了,想这样的情况,你最好至少保证有3个节点。
elasticsearch.yml中这样配置:
discovery.zen.minimum_master_nodes: 2
但是由于ELasticsearch是动态的,你可以很容易的添加和删除节点,这会改变这个法定个数,如果你不得不修改索引的节点的配置并且重启你的整个集群为了让配置生效,这将是非常痛苦的一件事情。
基于这个原因,minimum_master_nodes (还有一些其它配置),允许通过API调用的方式动态进行配置,当你的集群在线运行的时候,你可以这样修改配置:
PUT /_cluster/settings
{
“persistent” : {
“discovery.zen.minimum_master_nodes” : 2
}
}
这将成为一个永久的配置,并且无论你配置项里配置的如何,这个将优先生效。当你添加和删除master节点的时候,你需要更改这个配置。
集群恢复方面的配置项
当你集群重启时,几个配置项影响你的分片恢复的表现。首先,我们必须明白,如果什么也没配置将会发生什么。
想象一下假设你有10个节点,每个节点保存一个分片,主分片或者副分片,也就是有一个有5个主分片/1个副本 的索引。你需要停止整个集群进行休整(举个例子,为了安装一个新的驱动程序)。当你重启你的集群,很自然会出现5个节点已经起动了,还有5个还没启动的场景。
假设其它五个节点出问题,或者他们根本没有收到立即重启的命令。无论什么原因,你只要五个节点在线上。这五个节点会相互通信,选出一个master,从而形成一个集群,他们注意到数据不再均匀分布,因为有个节点在集群中丢失了,他们之间会立马启动分片复制。
最后,你的其它5个节点打开加入了集群,这些节点会发现他们的数据已经成为其它节点的副本了,所以他们删除本地数据(因为这份数据要么是多余的,要么是过时的)。然后整个集群重新进行平衡,因为集群的大小已经从5变成了10。
在整个过程中,你的节点会消耗磁盘和网盘,来回移动数据,因为没有更好的理由。对于有上T数据的大集群,这种数据的传输需要很长时间。如果等待所有的节点重启好了,整个集群再上线,所有的本地的数据都不需要移动。
现在我们知道问题的所在了,我们可以修改一个小配置就可以缓解这个事情,首先我们要给ELasticsearch一个严格的限制:
gateway.recover_after_nodes: 8
这将放置Elasticsearch进行数据恢复,在发现8个节点(数据节点或者master节点)之前。这个值的设定取决于个人喜好: 整个集群提供服务之前你希望有多少个节点在线?我们设置为8, 这意味着至少要有8个节点,该集群才可用。
现在我们要告诉Ealsticsearch集群中应该有多少个节点,并且我们希望集群需要多久等待所有节点:
gateway.expected_nodes: 10
gateway.recover_after_time: 5m
这意味着Elasticsearch会采取如下操作:
*至少等待8个节点上线
*等待5分钟,或者10个节点上线后,才进行数据恢复,这取决于哪个条件先达到。
这三个设置可以在集群重启的时候避免过多的分片交换。这可能会让数据恢复从数个小时缩短为几秒钟。
这些配置只能设置在config/elasticsearch.yml文件中,或者是在命令行里(这些配置是无法东塔修改的),它们只在整个集群重启的时候有实质性作用。
最好使用单播代替组播
Elasticsearch默认是被配置成使用多播发现节点。多播就是通过在你的网络中发送UDP的ping请求以发现节点,其它Elasticsearch会收到这些ping请求并且进行响应,这样随后就会形成一个集群。
多播对于开发环境是很好的,你不需要做什么事情,打开一些节点,他们自然的会发现对方形成一个集群。
正是因为这种易用性,你在生产环境中必须禁掉它。否在你得到的结果就是一个节点意外的加入到了你的生产环境,因为他们收到了一个错误的组播信号。对于组播 本身并没有错。组播会导致一些愚蠢的问题,并且导致集群变的脆弱(例如:一个网络工程师正在捣鼓网络,而没有告诉你,你会发现所有的节点突然发现不了对方 了)。
在生产环境中,建议使用单播代替组播,也就是说为Elasticsearch提供一些它应该去尝试连接的节点列表。一旦这个节点联系到组播列表中的一员,它就会得到整个集群所有节点的状态,然后它会联系master节点,并加入集群。
这意味着你的单播列表不需要包含你的集群中的所有节点,它只需要包含足够一个新节点联系上其中一个并且说上话就ok了。如果你使用master候选节点作为单播列表,你只要列出三个就可以了。这个配置在elasticsearch.yml文件中:
discovery.zen.ping.multicast.enabled: false
discovery.zen.ping.unicast.hosts: [“host1″, “host2:port”]
备注:请确认你已经关闭了组播(discovery.zen.ping.multicast.enabled: false),否则它会和单播同时存在。
参考地址:https://www.elastic.co/guide/en/elasticsearch/guide/current/_important_configuration_changes.html