搜索和分析是当今应用软件的基本特征。可伸缩性和近实时处理大数据的能力是移动app、web和数据分析应用的基本要求之一。
自动补全文本字段、搜索建议、位置和地理空间搜索和多维导航是满足业务需求的可用标准。
调优是基本的、必要的和至关重要的!任何系统调优都必须基于性能测试;这就是为什么对于任何使用ES的人来说,对监控和指标变化有清楚地了解十分重要。
这三章系列教程介绍了性能调优的一些技巧和方法,逐步解释了与之最相关的系统配置的设置和指标。
集群状态(索引和分片的容量规划)
如果1个分片太少,而1000个分片又太多,那我怎样才能知道我需要多少个分片?这个问题在通常情况下是没法儿回答的。
有很多因素会影响:比如硬件条件、文档大小和复杂度、索引和分析文档的方式、查询类型、聚合方式、数据模型等等。
在ES创建大量的索引和分片很简单,但是每个索引和分片的创
ES为其无模式化提供了便利。弹性搜索提供了
schemaless
的灵活性。 我们可以向索引添加任何多字段的JSON文档,而无需告诉ES关于这些字段的任何内容。 这些新的字段 - 它们被命名什么,它们是什么类型,以及它们所在的索引 - 都会被自动添加到ES的索引映射和集群状态中。 开销最大的是 Cluster State
大小的管理,其中包含集群中每个索引的所有映射。
$ curl -XGET 'http://localhost:9200/_cluster/state'
以下是拥有三个模板和五个索引单节点集群API的响应:
{ "cluster_name": "elasticsearch", "version": 6, "state_uuid": "skxF0gCYTAGQAUU-ZW4_GQ", "master_node": "VyKDGurkQiygV-of4B1ZAQ", "blocks": {}, "nodes": { "VyKDGurkQiygV-of4B1ZAQ": { "name": "Siege", "transport_address": "127.0.0.1:9300", "attributes": {} } }, "metadata": { "cluster_uuid": "QMSq7EOfToS-v5dKc0GdUA", "templates": { "template_one": { "template": "template_one_*", "order": 0, "settings": { ... }, "mappings": { ... } }, "template_two": { ... }, "template_three": { ... } }, "indices": { "index_one": { "state": "open", "settings": { ... }, "mappings": { ... }, "aliases": [ ... ] }, "index_2": { ... }, "index_3": { ... }, "index_4": { ... }, "index_5": { ... } } }, "routing_table": { "indices": { "index_one": { "shards": { "0": [ { "state": "STARTED", "primary": true, "node": "VyKDGurkQiygV-of4B1ZAQ", "relocating_node": null, "shard": 0, "index": "index_one", "version": 18, "allocation_id": { "id": "hAZf59wDSNS7im1wOdToHA" } } ] } }, "index_two": { ... }, "index_three": { ... }, "index_four": { ... }, "index_five": { ... } } }, "routing_nodes": { "unassigned": [ { "state": "UNASSIGNED", "primary": true, "node": null, "relocating_node": null, "shard": 0, "index": "index_three", "version": 0, "unassigned_info": { "reason": "CLUSTER_RECOVERED", "at": "2017-02-08T18:46:11.027Z" } }, { ... } ], "nodes": { "VyKDGurkQiygV-of4B1ZAQ": [ { "state": "STARTED", "primary": true, "node": "VyKDGurkQiygV-of4B1ZAQ", "relocating_node": null, "shard": 0, "index": "index_one", "version": 18, "allocation_id": { "id": "hAZf59wDSNS7im1wOdToHA" } }, { ... }, { ... } ] } } }
$ curl -XGET 'http://localhost:9200/_cluster/state/{metrics}/{indices}'
version
- 显示集群的当前版本.
master_node
-显示所选的主节点部分
nodes
- 显示响应的节点部分 routing_table
- 显示响应的路由部分。如果我们提供一个逗号分隔的索引列表,那么返回的结果将只包含列出的索引。
metadata
-显示响应的元数据。如如果我们提供一个逗号分隔的索引列表,那么返回的结果将只包含列出的索引。blocks
- 显示响应的块部分。
我们可以规划集群状态、大小和容量以决定主分片的数量:
ES为组合复杂的集群拓扑提供了大量的工具。我们可以使用拥有健壮节点的异构集群来托管热数据,并且使用更便宜的节点存储历史数据,例如使用节点熟悉和分片分片过滤。集群中的不同节点有不同的角色(数据节点/主节点-客户端节点与否)和属性(比如区域)。划分主节点和数据节点的异构好处是我们只需要三个主选取节点并设置minimum_master_nodes为2。无论我们向集群中添加多少数据节点我们都不用改变设置。建立一个合适的集群拓扑可以有效避免脑裂 split brain。
为了创建一个独立的主选取节点:
node.master: truenode.data: falsenode.ingest: false
node.master 默认是开启的
关闭node.data (默认开启).
关闭node.ingest (默认开启).
数据节点持有我们索引中的文档。数据节点处理例如CRUD、搜索和聚合登数据类的操作。这些操作是IO、内存、CPU密集型的。监控资源很重要并且在负载过重时需要加载更多的数据节点。拥有专用数据节点的主要好处是主数据和数据角色的分离。
为了创建一个独立的数据节点:
node.master: falsenode.data: truenode.ingest: false
关闭node.master(默认开启).
node.data 默认开启
关闭node.ingest(默认开启).
摄取节点可以执行预处理管道,有一个或多个摄取处理器组成。根据摄取过程和所需的资源执行的不同类型,只执行特定任务的摄取节点是有意义的。
为了创建一个独立的主选取节点:
node.master: falsenode.data: falsenode.ingest: true
关闭 node.master(默认开启).
关闭node.data(默认开启).
node.ingest默认开启
协调节点
如果我们不管处理主节点职责、保存数据和预处理文档的能力,那么我们就可以有一个只能路由请求、处理搜索减少阶段和分发批量索引的协调节点。实际上,协调节点就像一个智能负载均衡器一样。
为了创建一个独立的协调节点:node.master: falsenode.data: falsenode.ingest: false
关闭node.master(默认开启).
关闭node.data(默认开启).
关闭node.ingest(默认开启).
Swapping
是将一页内容复制到硬盘预先分配的空间的过程,称为交互空间,以释放内存页。物理内存和交互空间的组合大小是可用的虚拟内存值。
交换对性能和节点稳定十分不利,因不惜一切禁止。它会导致持续几分钟而不是几毫米的gc,并可能导致节点响应缓慢,甚至是断开与集群的连接。与内容相比,磁盘是很慢的。内存是纳秒级而磁盘是毫秒级;所以访问磁盘的速度可能比访问物理内存要慢数万倍。发生的交换越多,进程就会越慢,因为应该避免交换。
当JVM执行一个major gc时会涉及堆中的每一页。如果这些页面中的任何一个被交换到磁盘,它们不得不交换回内存。这会导致大量的磁盘抖动而ES更愿意使用服务请求。禁止交换的几种方法之一是设置ES的bootstrap.mlockall请求JVM通过mlockall将堆锁在内存中。然而,在有些情况下ES无法锁定堆(例如ES没有无限的memlock )。内存锁定检查可用于验证bootstrap.mlockall
是否开启,也可确认JVM是否成功的锁定了堆。
以下是三种禁用交换的方法:
mlockall
属性允许ES节点禁止交换内存(注意这这对Linux/Unix系统适用)。这个属性可以在 config/elasticsearch.yml
文件中加入以下这行:
bootstrap.mlockall:true在 5.x releases中 ,这个变量改成了
bootstrap.memory_lock: true
.
mlockall
默认是关闭的,意味着ES节点允许交换。一旦添加了该字段,需要重启节点。重启ES之后可以通过以下请求返回的mlockall
值来确认是否应用成功。
curl -XGET localhost:9200/_nodes?filter_path=**.mlockall
正确的返回应该是
{"nodes":{"VyKDGurkQiygV-of4B1ZAQ":{"process":{"mlockall":true}}}}
如果我们发现mlockall是false,那意味着mlockall 请求失败。我们将会看到无法锁定JVM内存的提示信息。Linux/Unix最可能的原因是ES用户没有权限锁定内存,可以通过下面的方式授权:
启动ES前设置ulimit -l unlimited
为root,或者在 /etc/security/limits.conf
设置 memlock
为 unlimited
RPM or Debian 在系统配置文件中设置MAX_LOCKED_MEMORY
为 unlimited
(或者参阅下面的系统使用systemd)
如果使用systemd Systems设置LimitMEMLOCK
to infinity in the systemd configuration
, .
可以完全禁用交换。一般ES是作为一个服务部署在资源上,而它的内容是由JVM变量控制的。这不需要进行交换。在Linux系统中我们可以通过运行sudo swapoff -a临时禁用交换。而要永久禁用的话需要编辑 /etc/fstab
文件,并注释掉包含单词swap的任何行。
另外一个Linux系统可选的操纵是确保sysctl
中vm.swappiness
值设为1。这降低了内核交换的倾向,并且在正常情况下不该出现交换,但在紧急情况下任然运行交换。