热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

从400+节点Elasticsearch集群的运维中,我们总结了这些经验

Meltwater每天要处理数百万量级的帖子数据,因此需要一种能处理该量级数据的存储和检索技术。

从400+节点Elasticsearch集群的运维中,我们总结了这些经验

Meltwater 每天要处理数百万量级的帖子数据,因此需要一种能处理该量级数据的存储和检索技术。

从400+节点Elasticsearch集群的运维中,我们总结了这些经验

从 0.11.X 版本开始我们就已经是 Elasticsearch 的忠实用户了。在经历了一些波折之后,最终我们认为做出了正确的技术选型。

Elasticsearch 用于支持我们的主要媒体监控应用,客户通过该应用可以检索和分析媒体数据,比如新闻文章、(公开的)Facebook 帖子、Instagram 帖子、博客和微博。我们通过使用一个混合 API 来收集这些内容,并爬取和稍作加工,使得它们可被 Elasticsearch 检索到。

本文将分享我们所学到的经验、如何调优 Elasticsearch,以及要绕过的一些陷阱。

数据量

每天都有数量相当庞大的新闻和微博产生;在高峰期需要索引大约 300 多万社论文章,和近 1 亿条社交帖子数据。其中社论数据长期保存以供检索(可回溯到 2009 年),社交帖子数据保存近 15 个月的。当前的主分片数据使用了大约 200 TB 的磁盘空间,副本数据大约 600 TB。

我们的业务每分钟有 3 千次请求。所有的请求通过一个叫做“search-service”的服务,该服务会依次完成所有与 Elasticsearch 集群的交互。大部分检索规则比较复杂,包括在面板和新闻流中。比如,一个客户可能对 Tesla 和 Elon Musk 感兴趣,但希望排除所有关于 SpaceX 或 PayPal 的信息。用户可以使用一种与 Lucene 查询语法类似的灵活语法,如下:

Tesla AND "Elon Musk" NOT (SpaceX OR PayPal) 

我们最长的此类查询有 60 多页。重点是:除了每分钟 3 千次请求以外,没有一个查询是像在 Google 里查询“Barack Obama”这么简单的;这简直就是可怕的野兽,但 ES 节点必须努力找出一个匹配的文档集。

从400+节点Elasticsearch集群的运维中,我们总结了这些经验

版本

我们运行的是一个基于 Elasticsearch 1.7.6 的定制版本。该版本与 1.7.6 主干版本的唯一区别是,我们向后移植(backport)了 roaring bitsets/bitmaps 作为缓存。该功能是从 Lucene 5 移植到 Lucene 4 的,对应移植到了 ES 1.X 版本。Elasticsearch 1.X 中使用默认的 bitset 作为缓存,对于稀疏结果来说开销非常大,不过在 Elasticsearch 2.X 中已经做了优化。

为何不使用较新版本的 Elasticsearch 呢?主要原因是升级困难。在主版本间滚动升级只适用于从 ES 5 到 6(从 ES 2 到 5 应该也支持滚动升级,但没有试过)。因此,我们只能通过重启整个集群来升级。宕机对我们来说几乎不可接受,但或许可以应对一次重启所带来的大约 30-60 分钟宕机时间;而真正令人担心的,是一旦发生故障并没有真正的回滚过程。

截止目前我们选择了不升级集群。当然我们希望可以升级,但目前有更为紧迫的任务。实际上该如何实施升级尚未有定论,很可能选择创建另一个新的集群,而不是升级现有的。

节点配置

我们自 2017 年 6 月开始在 AWS 上运行主集群,使用 i3.2xlarge 实例作为数据节点。之前我们在 COLO(Co-located Data Center)里运行集群,但后续迁移到了 AWS 云,以便在新机器宕机时能赢得时间,使得我们在扩容和缩容时更加弹性。

我们在不同的可用区运行 3 个候选 master 节点,并设置 discovery.zen.minimum_master_nodes 为 2。这是避免脑裂问题 split-brain problem 非常通用的策略。

我们的数据集在存储方面,要求 80% 容量和 3 个以上的副本,这使得我们运行了 430 个数据节点。起初打算使用不同层级的数据,在较慢的磁盘上存储较旧的数据,但是由于我们只有相关的较低量级旧于 15 个月的数据(只有编辑数据,因为我们丢弃了旧的社交数据),然而这并未奏效。每个月的硬件开销远大于运行在 COLO 中,但是云服务支持扩容集群到 2 倍,而几乎不用花费多少时间。

你可能会问,为何选择自己管理维护 ES 集群。其实我们考虑过托管方案,但最后还是选择自己安装,理由是: AWS Elasticsearch Service 暴露给用户的可控性太差了, Elastic Cloud 的成本比直接在 EC2 上运行集群要高 2-3 倍。

为了在某个可用区宕机时保护我们自身,节点分散于 eu-west-1 的所有 3 个可用区。我们使用 AWS plugin 来完成该项配置。它提供了一个叫做 aws_availability_zone 的节点属性,我们把 cluster.routing.allocation.awareness.attributes 设置为 aws_availability_zone。这保证了 ES 的副本尽可能地存储在不同的可用区,而查询尽可能被路由到相同可用区的节点。

这些实例运行的是 Amazon Linux,临时挂载为 ext4,有约 64GB 的内存。我们分配了 26GB 用于 ES 节点的堆内存,剩下的用于磁盘缓存。为何是 26GB?因为 JVM 是在一个黑魔法之上构建的。

我们同时使用 Terraform 自动扩容组来提供实例,并使用 Puppet 完成一切安装配置。

索引结构

因为我们的数据和查询都是基于时间序列的,所以使用了 time-based indexing,类似于 ELK (elasticsearch, logstash, kibana) stack。同时也让不同类型的数据保存在不同的索引库中,以便诸如社论文档和社交文档类数据最终位于不同的每日索引库中。这样可以在需要的时候只丢弃社交索引,并增加一些查询优化。每个日索引运行在两个分片中的一个。

该项设置产生了大量的分片(接近 40k)。有了这么多的分片和节点,集群操作有时变得更特殊。比如,删除索引似乎成为集群 master 的能力瓶颈,它需要把集群状态信息推送给所有节点。我们的集群状态数据约 100 MB,但通过 TCP 压缩可减少到 3 MB(可以通过 curl localhost:9200/_cluster/state/_all 查看你自己集群的状态数据)。Master 节点仍然需要在每次变更时推送 1.3 GB 数据(430 节点 x 3 MB 状态大小)。除了这 1.3 GB 数据外,还有约 860 MB 必须在可用区(比如 最基本的通过公共互联网)之间传输。这会比较耗时,尤其是在删除数百个索引时。我们希望新版本的 Elasticsearch 能优化这一点,首先从 ES 2.0 支持仅发送集群状态的差分数据这一特性开始。

性能

如前所述,我们的 ES 集群为了满足客户的检索需求,需要处理一些非常复杂的查询。

为应对查询负载,过去几年我们在性能方面做了大量的工作。我们必须尝试公平分享 ES 集群的性能测试,从下列引文就可以看出。

不幸的是,当集群宕机的时候,不到三分之一的查询能成功完成。我们相信测试本身导致了集群宕机。—— 摘录自使用真实查询在新 ES 集群平台上的第一次性能测试

为了控制查询执行过程,我们开发了一个插件,实现了一系列自定义查询类型。通过使用这些查询类型来提供 Elasticsearch 官方版本不支持的功能和性能优化。比如,我们实现了 phrases 中的 wildcard 查询,支持在 SpanNear 查询中执行;另一个优化是支持“*”代替 match-all-query;还有其他一系列特性。

Elasticsearch 和 Lucene 的性能高度依赖于具体的查询和数据,没有银弹。即便如此,仍可给出一些从基础到进阶的参考:

  • 限制你的检索范围,仅涉及相关数据。比如,对于每日索引库,只按相关日期范围检索。对于检索范围中间的索引,避免使用范围查询 / 过滤器。
  • 使用 wildcards 时忽略前缀 wildcards- 除非你能对 term 建立倒排索引。双端 wildcards 难以优化。
  • 关注资源消耗的相关迹象 数据节点的 CPU 占用持续飙高吗?IQ 等待走高吗?看看 GC 统计。这些可以从 profilers 工具或者通过 JMX 代理获得。如果 ParNewGC 消耗了超过 15% 的时间,去检查下内存日志。如果有任何的 SerialGC 停顿,你可能真的遇到问题了。
  • 如果遇到垃圾回收问题,请不要尝试调整 GC 设置。 这一点经常发生,因为默认设置已经很合理了。相反,应该聚焦在减少内存分配上。具体怎么做?参考下文。
  • 如果遇到内存问题,但没有时间解决,可考虑下 Azul Zing。这是一个很贵的产品,但仅仅使用它们的 JVM 就可以提升 2 倍的吞吐量。不过最终我们并没有使用它,因为我们无法证明物有所值。
  • 考虑使用缓存,包括 Elasticsearch 外缓存和 Lucene 级别的缓存。在 Elasticsearch 1.X 中可以通过使用 filter 来控制缓存。之后的版本中看起来更难一些,但貌似可以实现自己用于缓存的查询类型。我们在未来升级到 2.X 的时候可能会做类似的工作。
  • 查看是否有热点数据(比如某个节点承担了所有的负载)。可以尝试均衡负载,使用分片分配过滤策略 shard allocation filtering,或者尝试通过集群重新路由 cluster rerouting 来自行迁移分片。我们已经使用线性优化自动重新路由,但使用简单的自动化策略也大有帮助。
  • 搭建测试环境(我更喜欢笔记本)可从线上环境加载一部分代表性的数据(建议至少有一个分片)。使用线上的查询回放加压(较难)。使用本地设置来测试请求的资源消耗。
  • 综合以上各点,在 Elasticsearch 进程上启用一个 profiler。这是本列表中最重要的一条。我们同时通过 Java Mission Control 和 VisualVM 使用飞行记录器。在性能问题上尝试投机(包括付费顾问 / 技术支持)的人是在浪费他们(以及你自己)的时间。排查下 JVM 哪部分消耗了时间和内存,然后探索下 Elasticsearch/Lucene 源代码,检查是哪部分代码在执行或者分配内存。
  • 一旦搞清楚是请求的哪一部分导致了响应变慢,你就可以通过尝试修改请求来优化(比如,修改 term 聚合的执行提示,或者切换查询类型)。修改查询类型或者查询顺序,可以有较大影响。如果不奏效,还可以尝试优化 ES/Lucene 代码。这看起来太夸张,却可以为我们降低 3 到 4 倍的 CPU 消耗和 4 到 8 倍的内存使用。某些修改很细微(比如 indices query),但其他人可能要求我们完全重写查询执行。最终的代码严重依赖于我们的查询模式,所以可能适合也可能不适合他人使用。 - 除非你能对 term 建立倒排索引。双端 wildcards 难以优化。
  • 从400+节点Elasticsearch集群的运维中,我们总结了这些经验

图表说明:响应时间。有 / 没有 重写 Lucene 查询执行。同时也表明不再有节点每天发生多次内存不足的情况。

顺便说明下,因为我知道会面临一个问题:从上一次性能测试我们知道通过升级到 ES 2.X 能小幅提升性能,但是并不能改变什么。话虽如此,但如果你已经从 ES 1.X 集群迁移到了 ES 2.X,我们很乐意听取关于你如何完成迁移的实践经验。

如果读到了这里,说明你对 Elasticsearch 是真爱啊(或者至少你是真的需要它)。

英文原文链接:http://underthehood.meltwater.com/blog/2018/02/06/running-a-400+-node-es-cluster/


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 我们


推荐阅读
  • 投融资周报 | Circle 达成 4 亿美元融资协议,唯一艺术平台 A 轮融资超千万美元 ... [详细]
  • 在对WordPress Duplicator插件0.4.4版本的安全评估中,发现其存在跨站脚本(XSS)攻击漏洞。此漏洞可能被利用进行恶意操作,建议用户及时更新至最新版本以确保系统安全。测试方法仅限于安全研究和教学目的,使用时需自行承担风险。漏洞编号:HTB23162。 ... [详细]
  • 零拷贝技术是提高I/O性能的重要手段,常用于Java NIO、Netty、Kafka等框架中。本文将详细解析零拷贝技术的原理及其应用。 ... [详细]
  • 在多线程并发环境中,普通变量的操作往往是线程不安全的。本文通过一个简单的例子,展示了如何使用 AtomicInteger 类及其核心的 CAS 无锁算法来保证线程安全。 ... [详细]
  • 近期在研究逆向工程,因此尝试了一些CTF题目。通过合天网络安全实验室的CTF实战演练平台(http://www.hetianlab.com/CTFrace.html),我对Linux逆向工程的掌握还不够深入,因此暂时跳过了RE300题目。首先从逆向100开始,将文件后缀名修改为.apk进行初步分析。这一过程不仅帮助我熟悉了基本的逆向技巧,还加深了对Android应用结构的理解。 ... [详细]
  • 本文详细介绍了 InfluxDB、collectd 和 Grafana 的安装与配置流程。首先,按照启动顺序依次安装并配置 InfluxDB、collectd 和 Grafana。InfluxDB 作为时序数据库,用于存储时间序列数据;collectd 负责数据的采集与传输;Grafana 则用于数据的可视化展示。文中提供了 collectd 的官方文档链接,便于用户参考和进一步了解其配置选项。通过本指南,读者可以轻松搭建一个高效的数据监控系统。 ... [详细]
  • 在CentOS 7环境中安装配置Redis及使用Redis Desktop Manager连接时的注意事项与技巧
    在 CentOS 7 环境中安装和配置 Redis 时,需要注意一些关键步骤和最佳实践。本文详细介绍了从安装 Redis 到配置其基本参数的全过程,并提供了使用 Redis Desktop Manager 连接 Redis 服务器的技巧和注意事项。此外,还探讨了如何优化性能和确保数据安全,帮助用户在生产环境中高效地管理和使用 Redis。 ... [详细]
  • 您的数据库配置是否安全?DBSAT工具助您一臂之力!
    本文探讨了Oracle提供的免费工具DBSAT,该工具能够有效协助用户检测和优化数据库配置的安全性。通过全面的分析和报告,DBSAT帮助用户识别潜在的安全漏洞,并提供针对性的改进建议,确保数据库系统的稳定性和安全性。 ... [详细]
  • 在Linux系统中避免安装MySQL的简易指南
    在Linux系统中避免安装MySQL的简易指南 ... [详细]
  • 深入解析C语言中结构体的内存对齐机制及其优化方法
    为了提高CPU访问效率,C语言中的结构体成员在内存中遵循特定的对齐规则。本文详细解析了这些对齐机制,并探讨了如何通过合理的布局和编译器选项来优化结构体的内存使用,从而提升程序性能。 ... [详细]
  • 在《Linux高性能服务器编程》一书中,第3.2节深入探讨了TCP报头的结构与功能。TCP报头是每个TCP数据段中不可或缺的部分,它不仅包含了源端口和目的端口的信息,还负责管理TCP连接的状态和控制。本节内容详尽地解析了TCP报头的各项字段及其作用,为读者提供了深入理解TCP协议的基础。 ... [详细]
  • 本文探讨了如何通过编程手段在Linux系统中禁用硬件预取功能。基于Intel® Core™微架构的应用性能优化需求,文章详细介绍了相关配置方法和代码实现,旨在帮助开发人员有效控制硬件预取行为,提升应用程序的运行效率。 ... [详细]
  • 本文探讨了利用Python实现高效语音识别技术的方法。通过使用先进的语音处理库和算法,本文详细介绍了如何构建一个准确且高效的语音识别系统。提供的代码示例和实验结果展示了该方法在实际应用中的优越性能。相关文件可从以下链接下载:链接:https://pan.baidu.com/s/1RWNVHuXMQleOrEi5vig_bQ,提取码:p57s。 ... [详细]
  • 今天我开始学习Flutter,并在Android Studio 3.5.3中创建了一个新的Flutter项目。然而,在首次尝试运行时遇到了问题,Gradle任务 `assembleDebug` 执行失败,退出状态码为1。经过初步排查,发现可能是由于依赖项配置不当或Gradle版本不兼容导致的。为了解决这个问题,我计划检查项目的 `build.gradle` 文件,确保所有依赖项和插件版本都符合要求,并尝试更新Gradle版本。此外,还将验证环境变量配置是否正确,以确保开发环境的稳定性。 ... [详细]
  • 在拉斯维加斯举行的Interop 2011大会上,Bitcurrent的Alistair Croll发表了一场主题为“如何以云计算的视角进行思考”的演讲。该演讲深入探讨了传统IT思维与云计算思维之间的差异,并提出了在云计算环境下应具备的新思维方式。Croll强调了灵活性、可扩展性和成本效益等关键要素,以及如何通过这些要素来优化企业IT架构和运营。 ... [详细]
author-avatar
突然丶丶想你
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有