Meltwater每天要处理数百万的post数据,因此需要一种能够处理这种海量数据的存储和检索技术。我们从0.11.X版本开始就是Elasticsearch的忠实用户。在经历了一些波折之后,我们终于认为我们做出了正确的技术选择。Elasticsearch用于支持我们的主要媒体监控应用程序,使客户能够检索和分析媒体数据,例如新闻文章、(公共)Facebook帖子、Instagram帖子、博客和推文。我们使用混合API收集这些内容,并对其进行爬网和轻微处理,以便Elasticsearch可以检索它。本文将分享我们学到的知识、如何调优Elasticsearch以及要避免的一些陷阱。数据量每天都有海量的新闻、微博产生;高峰期需要索引超过300万篇社论文章和近亿条社交帖子数据。其中,社论数据存储时间较长(可追溯到2009年),社交帖子数据存储近15个月。目前主分片数据使用磁盘空间约200TB,副本数据约600TB。我们的业务每分钟有3000个请求。所有请求都经过一个名为“search-service”的服务,该服务依次完成与Elasticsearch集群的所有交互。大多数搜索规则都比较复杂,并且包含在面板和新闻源中。例如,客户可能对Tesla和ElonMusk感兴趣,但希望排除有关SpaceX或PayPal的所有信息。用户可以使用类似于Lucene的查询语法的灵活语法,如下所示:TeslaAND"ElonMusk"NOT(SpaceXORPayPal)我们最长的此类查询超过60页。关键是:除了每分钟3k请求之外,没有任何查询像Google中的“BarackObama”这样简单;这是一头可怕的野兽,但ES节点必须努力工作才能找到匹配的文档集。版本我们正在运行基于Elasticsearch1.7.6的自定义版本。此版本与1.7.6主干版本之间的唯一区别是我们将roaringbitsets/bitmapsbackported作为缓存。该功能从Lucene5移植到Lucene4,对应ES1.X版本。Elasticsearch1.X使用默认的bitset作为缓存,这对于稀疏结果来说非常昂贵,但在Elasticsearch2.X中已经进行了优化。为什么不使用更新版本的Elasticsearch?主要原因是升级难。主要版本之间的滚动升级只适用于ES5到6(ES2到5应该也支持滚动升级,但没试过)。因此,我们只能通过重启整个集群来升级。停机时间对我们来说几乎是不可接受的,但也许可以处理重启后30-60分钟的停机时间;真正令人担忧的是,在发生故障时没有真正的回滚过程。到目前为止,我们选择不升级集群。我们当然希望能够升级,但眼下还有更紧迫的任务。目前尚不清楚升级将如何实际实施,很可能会选择创建另一个新集群而不是升级现有集群。节点配置自2017年6月以来,我们一直在AWS上运行主集群,使用i3.2xlarge实例作为数据节点。我们以前在COLO(Co-locatedDataCenter)跑集群,后来迁移到AWS云上,在新机器宕机的时候争取时间,让我们在扩容和缩容的时候更加灵活。我们在不同可用区运行3个候选主节点,并将discovery.zen.minimum_master_nodes设置为2。这是避免裂脑问题的非常通用的策略。我们的数据集在存储方面需要80%的容量和3个以上的副本,这使我们运行430个数据节点。最初打算使用不同的数据层,将较旧的数据存储在较慢的磁盘上,但由于我们只有15个月以上的相关较低量级数据(仅在我们丢弃旧的社交数据时编辑数据),但这并没有奏效。每月的硬件开销比跑在COLO里高很多,但是云服务支持把集群扩容到2倍,几乎不用时间。你可能会问为什么选择自己管理和维护ES集群。其实我们也考虑过托管方案,但最终还是选择了自己安装。原因是:AWSElasticsearchService暴露给用户的可控性太差,ElasticCloud的成本比直接在EC2上跑集群要高2-3倍。为了在其中一个可用区出现故障时保护我们自己,节点分布在eu-west-1中的所有3个可用区中。我们为此配置使用AWS插件。它提供了一个名为aws_availability_zone的节点属性,我们将cluster.routing.allocation.awareness.attributes设置为aws_availability_zone。这样可以保证ES的副本尽可能存放在不同的可用区,查询尽可能路由到同一可用区的节点。这些实例运行的是AmazonLinux,临时挂载为ext4,内存约为64GB。我们为ES节点分配了26GB的堆内存,其余的用于磁盘缓存。为什么是26GB?因为JVM是建立在黑魔法之上的。我们还使用Terraform自动缩放组为所有内容提供实例和Puppet。索引结构因为我们的数据和查询都是基于时间序列的,所以使用了基于时间的索引,类似于ELK(elasticsearch、logstash、kibana)stack。它还将不同类型的数据保存在不同的索引存储库中,因此编辑文档和社交文档等数据最终会出现在不同的日常索引存储库中。这允许您在需要时删除社交索引并添加一些查询优化。每个每日索引都在两个分片之一上运行。此设置会产生大量分片(接近40k)。有这么多分片和节点,集群操作有时会变得特别。例如,删除索引似乎是集群主控的容量瓶颈,它需要将集群状态信息推送到所有节点。我们的集群状态数据大约是100MB,但是可以通过TCP压缩减少到3MB(可以通过curllocalhost:9200/_cluster/state/_all查看自己集群的状态数据)。主节点每次更改仍需要推送1.3GB的数据(430个节点x3MB状态大小)。除了这1.3GB的数据之外,还必须在可用区之间传输大约860MB的数据(例如,最基本的是通过公共互联网)。这可能很耗时,尤其是在删除数百个索引时。我们希望新版本的Elasticsearch能够对此进行优化,从ES2.0开始支持只发送集群状态差异数据的特性。性能前面提到,我们的ES集群为了满足客户的检索需求,需要处理一些非常复杂的查询。针对查询负载,这几年我们在性能上做了很多工作。我们必须尝试公平地参与ES集群的性能测试,从以下引用中可以看出。不幸的是,当集群关闭时,只有不到三分之一的查询成功完成。我们认为测试本身导致集群宕机。—摘自使用真实查询在新的ES集群平台上进行的第一次性能测试为了控制查询执行过程,我们开发了一个实现一系列自定义查询类型的插件。使用这些查询类型可提供官方Elasticsearch版本不支持的功能和性能优化。比如我们在phrase中实现了通配符查询,支持在SpanNear查询中执行;另一个优化是支持“*”而不是match-all-query;还有一系列其他功能。Elasticsearch和Lucene的性能高度依赖于特定的查询和数据,没有灵丹妙药。尽管如此,还是可以提供一些高级参考的基础知识:将搜索限制在相关数据中。例如,对于每日索引库,仅按相关日期范围进行搜索。避免对检索范围中间的索引使用范围查询/过滤器。使用通配符时忽略前缀通配符——除非你可以在术语上建立倒排索引。两端通配符很难优化。观察资源消耗迹象数据节点的CPU使用率是否不断飙升?智商是不是等着上去了?查看GC统计信息。这些可以从分析器工具或通过JMX代理获得。如果ParNewGC占用的时间超过15%,请检查内存日志。如果有任何SerialGC暂停,您实际上可能遇到了问题。如果您在垃圾回收方面遇到问题,请不要尝试调整GC设置。这种情况经常发生,因为默认设置已经很合理了。相反,专注于减少内存分配。怎么做?见下文。如果您有内存问题但没有时间修复它们,请考虑使用AzulZing。这是一种昂贵的产品,但仅使用其JVM即可获得2倍的吞吐量。最后我们没有使用它,因为我们无法证明物有所值。考虑在Elasticsearch外部和Lucene级别使用缓存。在Elasticsearch1.X中,可以使用过滤器来控制缓存。在以后的版本中看起来更难,但似乎可以实现您自己的缓存查询类型。将来升级到2.X时,我们可能会做类似的事情。检查是否有热点数据(例如某个节点承担了所有负载)。您可以尝试负载平衡、使用分片分配过滤或尝试集群重新路由来自行迁移分片。我们已经使用线性优化来自动重新路由,但使用简单的自动化策略也可以大有帮助。搭建一个测试环境(我比较喜欢notebook)从线上环境加载一些有代表性的数据(推荐至少一个shard)。使用在线查询回放来加压(难)。使用本地设置来测试请求的资源消耗。基于以上几点,在Elasticsearch进程上启用profiler。这是此列表中最重要的项目。我们将飞行记录器与JavaMissionControl和VisualVM一起使用。试图推测(包括付费顾问/技术支持)性能问题的人是在浪费他们(和你自己)的时间。检查JVM的哪一部分消耗了时间和内存,然后探索Elasticsearch/Lucene源代码以检查代码的哪一部分正在执行或分配内存。一旦弄清楚是请求的哪一部分导致了响应变慢,就可以尝试修改请求进行优化(比如修改词条聚合的执行提示,或者切换查询类型)。修改查询类型或查询顺序可以产生更大的影响。如果这不起作用,您还可以尝试优化您的ES/Lucene代码。这看起来有点夸张,但它可以使我们的CPU消耗减少3到4倍,内存使用减少4到8倍。有些修改是微妙的(例如索引查询),但其他修改可能需要我们完全重写查询执行。生成的代码在很大程度上取决于我们的查询模式,因此可能适合也可能不适合其他人使用。-除非你可以建立倒排索引。两端通配符很难优化。图表说明:响应时间。是/否重写Lucene查询执行。它还表明不再有节点一天多次耗尽内存。顺便说一下,因为我知道我将要面对一个问题:从上次性能测试我们知道通过升级到ES2.X我们可以稍微提高性能,但它不会改变任何东西。话虽如此,如果您已经从ES1.X集群迁移到ES2.X,我们很想听听您的实践经验。如果您已经走到这一步,那么您真的很喜欢Elasticsearch(或者至少您真的需要它)。英文原文链接:http://underthehood.meltwater.com/blog/2018/02/06/running-a-400+-node-es-cluster/
