max_result_window会影响es性能_Elasticsearch 最佳性能优化

本文转自: http://wangnan.tech/post/elkstack-es03/,作者: Ghost Stories
侵删。

批量提交

在 CRUD 章节,我们已经知道 ES 的数据写入是如何操作的了。喜欢自己动手的读者可能已经迫不及待的自己写了程序开始往 ES 里写数据做测试。这时候大家会发现:程序的运行速度非常一般,即使 ES 服务运行在本机,一秒钟大概也就能写入几百条数据。

这种速度显然不是 ES 的极限。事实上,每条数据经过一次完整的 HTTP POST 请求和 ES indexing 是一种极大的性能浪费,为此,ES 设计了批量提交方式。在数据读取方面,叫 mget 接口,在数据变更方面,叫 bulk 接口。mget 一般常用于搜索时 ES 节点之间批量获取中间结果集,对于 Elastic Stack 用户,更常见到的是 bulk 接口。

bulk 接口采用一种比较简朴的数据积累格式,示例如下:

1# curl -XPOST http://127.0.0.1:9200/_bulk -d'
2{ "create" : { "_index" : "test", "_type" : "type1"  } }
3{ "field1" : "value1" }
4{ "delete" : { "_index" : "test", "_type" : "type1" } }
5{ "index" : { "_index" : "test", "_type" : "type1", "_id" : "1" } }
6{ "field1" : "value2" }
7{ "update" : { "_id" : "1", "_type" : "type1", "_index" : "test"} }
8{ "doc" : { "field2" : "value2"} }
9'

格式是,每条 JSON 数据的上面,加一行描述性的元 JSON,指明下一行数据的操作类型,归属索引信息等。

采用这种格式,而不是一般的 JSON 数组格式,是因为接收到 bulk 请求的 ES 节点,就可以不需要做完整的 JSON 数组解析处理,直接按行处理简短的元 JSON,就可以确定下一行数据 JSON 转发给哪个数据节点了。这样,一个固定内存大小的 network buffer 空间,就可以反复使用,又节省了大量 JVM 的 GC。

事实上,产品级的 logstash、rsyslog、spark 都是默认采用 bulk 接口进行数据写入的。对于打算自己写程序的读者,建议采用 Perl 的 Search::Elasticsearch::Bulk 或者 Python 的 elasticsearch.helpers.* 库。

bulk size

在配置 bulk 数据的时候,一般需要注意的就是请求体大小(bulk size)。

这里有一点细节上的矛盾,我们知道,HTTP 请求,是可以通过 HTTP 状态码 100 Continue 来持续发送数据的。但对于 ES 节点接收 HTTP 请求体的 Content-Length 来说,是按照整个大小来计算的。所以,首先,要确保 bulk 数据不要超过 http.max_content_length 设置。

那么,是不是尽量让 bulk size 接近这个数值呢?当然不是。

依然是请求体的问题,因为请求体需要全部加载到内存,而 JVM Heap 一共就那么多(按 31GB 算),过大的请求体,会挤占其他线程池的空间,反而导致写入性能的下降。

再考虑网卡流量,磁盘转速的问题,所以一般来说,建议 bulk 请求体的大小,在 15MB 左右,通过实际测试继续向上探索最合适的设置。

注意:这里说的 15MB 是请求体的字节数,而不是程序里里设置的 bulk size。bulk size 一般指数据的条目数。不要忘了,bulk 请求体中,每条数据还会额外带上一行元 JSON。

以 logstash 默认的 bulk_size => 5000 为例,假设单条数据平均大小 200B ,一次 bulk 请求体的大小就是 1.5MB。那么我们可以尝试 bulk_size => 50000;而如果单条数据平均大小是 20KB,一次 bulk 大小就是 100MB,显然超标了,需要尝试下调至 bulk_size => 500

gateway

gateway 是 ES 设计用来长期存储索引数据的接口。一般来说,大家都是用本地磁盘来存储索引数据,即 gateway.type 为 local

数据恢复中,有很多策略调整我们已经在之前分片控制小节讲过。除开分片级别的控制以外,gateway 级别也还有一些可优化的地方:

  • gateway.recover_after_nodes
    该参数控制集群在达到多少个节点的规模后,才开始数据恢复任务。这样可以避免集群自动发现的初期,分片不全的问题。

  • gateway.recover_after_time
    该参数控制集群在达到上条配置设置的节点规模后,再等待多久才开始数据恢复任务。

  • gateway.expected_nodes
    该参数设置集群的预期节点总数。在达到这个总数后,即认为集群节点已经完全加载,即可开始数据恢复,不用再等待上条设置的时间。

注意:gateway 中说的节点,仅包括主节点和数据节点,纯粹的 client 节点是不算在内的。如果你有更明确的选择,也可以按需求写:

  • gateway.recover_after_data_nodes

  • gateway.recover_after_master_nodes

  • gateway.expected_data_nodes

  • gateway.expected_master_nodes

共享存储上的影子副本

虽然 ES 对 gateway 使用 NFS,iscsi 等共享存储的方式极力反对,但是对于较大量级的索引的副本数据,ES 从 1.5 版本开始,还是提供了一种节约成本又不特别影响性能的方式:影子副本(shadow replica)。

首先,需要在集群各节点的 elasticsearch.yml 中开启选项:

1node.enable_custom_paths: true

同时,确保各节点使用相同的路径挂载了共享存储,且目录权限为 Elasticsearch 进程用户可读可写。

然后,创建索引:

 1# curl -XPUT 'http://127.0.0.1:9200/my_index' -d '
2{
3    "index" : {
4        "number_of_shards" : 1,
5        "number_of_replicas" : 4,
6        "data_path": "/var/data/my_index",
7        "shadow_replicas": true
8    }
9}'10

针对 shadow replicas ,ES 节点不会做实际的索引操作,而是单纯的每次 flush 时,把 segment 内容 fsync 到共享存储磁盘上。然后 refresh 让其他节点能够搜索该 segment 内容。

如果你已经决定把数据放到共享存储上了,采用 shadow replicas 还是有一些好处的:

  1. 可以帮助你节省一部分不必要的多副本分片的数据写入压力;

  2. 在节点出现异常,需要在其他节点上恢复副本数据的时候,可以避免不必要的网络数据拷贝。

但是请注意:主分片节点还是要承担一个副本的写入过程,并不像 Lucene 的 FileReplicator 那样通过复制文件完成,所以达不到完全节省 CPU 的效果。

shadow replicas 只是一个在某些特定环境下有用的方式。在资源允许的情况下,还是应该使用 local gateway。而另外采用 snapshot 接口来完成数据长期备份到 HDFS 或其他共享存储的需要。

集群状态维护

我们都知道,ES 中的 master 跟一般 MySQL、Hadoop 的 master 是不一样的。它即不是写入流量的唯一入口,也不是所有数据的元信息的存放地点。所以,一般来说,ES 的 master 节点负载很轻,集群性能是可以近似认为随着 data 节点的扩展线性提升的。

但是,上面这句话并不是完全正确的。

ES 中有一件事情是只有 master 节点能管理的,这就是集群状态(cluster state)。

集群状态中包括以下信息:

  • 集群层面的设置

  • 集群内有哪些节点

  • 各索引的设置,映射,分析器和别名等

  • 索引内各分片所在的节点位置

这些信息在集群的任意节点上都存放着,你也可以通过 /_cluster/state 接口直接读取到其内容。注意这最后一项信息,之前我们已经讲过 ES 怎么通过简单地取余知道一条数据放在哪个分片里,加上现在集群状态里又记载了分片在哪个节点上,那么,整个集群里,任意节点都可以知道一条数据在哪个节点上存储了。所以,数据读写才可以发送给集群里任意节点。

至于修改ÿ

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值