gpt4 book ai didi

elasticsearch - 适用于具有大量聚合的大型集群的ElasticSearch设置

转载 作者:行者123 更新时间:2023-11-29 02:44:20 24 4
gpt4 key购买 nike

上下文和当前状态

我们正在将集群从Cassandra迁移到完整的ElasticSearch集群。我们正在以平均每秒〜250-300个文档索引索引文档。在ElasticSearch 1.2.0中,它表示每天〜8Go。

{
"generic":
{
"id": "twi471943355505459200",
"type": "twitter",
"title": "RT @YukBerhijabb: The Life is Choice - https://m.facebook.com/story.php?story_fbid=637864496306297&id=100002482564531&refid=17",
"content": "RT @YukBerhijabb: The Life is Choice - https://m.facebook.com/story.php?story_fbid=637864496306297&id=100002482564531&refid=17",
"source": "<a href=\"https://twitter.com/download/android\" rel=\"nofollow\">Twitter for Android</a>",
"geo": null,
"link": "http://twitter.com/rosi_sifah/status/471943355505459200",
"lang": "en",
"created_at": 1401355038000,
"author": {
"username": "rosi_sifah",
"name": "Rosifah",
"id": 537798506,
"avatar": "http://pbs.twimg.com/profile_images/458917673456238592/Im22zoIV_normal.jpeg",
"link": "http://twitter.com/rosi_sifah"
}
},
"twitter": {
// a tweet JSON
}
}

我们的用户将请求保存在SQL数据库中,当他们要求仪表板时,我们希望通过查询(从数据库检索)来请求ES集群,并且 使用新的ES聚合框架在的基础上进行一些聚合。

每个仪表板都会显示一个明确的,用户选择的日期范围,因此我们始终使用

"range": {
"generic.created_at": {
"from": 1401000000000,
"to": 1401029019706
}
}

以及ES查询。

我们以这种方式指定了 _routing :

"_routing":{
"required":true,
"path":"generic.id"
},

_id 与:

"_id": {
"index": "not_analyzed",
"store": "false",
"path": "generic.id"
}

在大约5天内,我们已将 6.7百万个文档(约40Go)存储在一个索引中。我们已经了解了按天划分索引的良好做法。因此,现在我们的索引按天划分([索引名称]-[YYYY-MM-DD])。

当前每个索引有5个分片和1个副本,我们有一个集群,该集群由3台机器组成,每台机器都有8个内核,16Go RAM和8To HDD。我们计划使用另一台计算机作为网关(8核,16Go RAM,1To HDD)。

除了集群配置之外,默认情况下我们还保留了ES配置。

问题
  • 对于我们要建立索引的每个文档,我们明确表示要建立的索引
    使用。目前,我们使用当天的日期。我们应该使用日期
    为了防止热点文件?因为目前
    表示来自不同日期的文件(在
    created_at)可以使用当天的相同索引。
  • 每天5个分片是否足以(或太多)容纳2160万个文档?
  • 如果我们希望所有聚合查询在不到1秒的时间内处理,我们应该设置多少个副本?
  • 我们应该更改路线吗?由于我们不知道在汇总到集群的每个请求之前将处理哪些文档(因为查询是用户定义的)
  • 我们应该在该集群中放入哪种硬件(多少台计算机,什么配置)以支持6个月的文档?

  • [更新]

    这是一些查询示例:

    词云

    GET idx-2014-05-01/stream/_search?search_type=count
    {
    "query":{
    "bool": {
    "must": [{
    "query_string" : {
    "query" : "(generic.lang:fr OR generic.lang:en) AND (generic.content:javascript)"
    }},{
    "range": {
    "generic.created_at": {
    "from": 1401000000000,
    "to": 1401029019706
    }
    }}
    ]
    }
    },
    "aggs":{
    "words":{
    "terms":{
    "field": "generic.content",
    "size": 40
    }
    }
    }
    }

    直方图

    GET idx-2014-05-01/stream/_search?search_type=count
    {
    "query":{
    "bool": {
    "must": [{
    "query_string" : {
    "query" : "generic.content:apple"
    }},{
    "range": {
    "generic.created_at": {
    "from": 1401000000000,
    "to": 1401029019706
    }
    }}
    ]
    }
    },
    "aggs":{
    "volume":{
    "date_histogram":{
    "field": "generic.created_at",
    "interval":"minute"
    }
    }
    }
    }

    必须使用的语言

    GET idx-2014-05-01/stream/_search?search_type=count
    {
    "query":{
    "bool": {
    "must": [{
    "query_string" : {
    "query" : "(generic.lang:fr OR generic.lang:en) AND (generic.content:javascript)"
    }},{
    "range": {
    "generic.created_at": {
    "from": 1401000000000,
    "to": 1401029019706
    }
    }}
    ]
    }
    },
    "aggs":{
    "top_source":{
    "terms":{
    "field": "generic.lang"
    }
    }
    }
    }

    最佳答案

    让我在我所有答案/评论的开头加上建议,以尝试尽可能地自己测试这些方案。尽管Elasticsearch具有很好的可扩展性,但仍有许多折衷会受到文档大小和类型,接收和查询量,硬件和操作系统的严重影响。尽管有许多错误的答案,但很少有一个正确的答案。

    我将这种响应建立在几个 Activity 集群的基础上,这些集群中(目前)有大约一百万个 Activity 文档,再加上一些近期的基准测试,我们的执行量约为您的四倍(基准测试期间每天摄取约8000万个文档)。

    1)首先,即使您只有一个索引(包含5个分片和每个分片1个副本),也不会创建具有3个节点的热点。 Elasticsearch会将每个副本的主副本分离到一个不同的节点,并且通常会尝试平衡分片的负载。默认情况下,Elasticsearch将对ID进行哈希处理以选择要索引到的分片(然后将其复制到副本中)。即使使用路由,只有具有每天创建大量文档(即索引范围)的单个ID时,您才会遇到热点问题。即使那样,除非这些ID占总容量的很大一部分,而且它们的数量很少,以至于您只能在其中一个或两个分片上集簇,否则这将不是问题。

    只有您可以根据使用情况来确定这一点-我建议您对现有数据集进行一些分析,以查找过大的集中度,并建议您对可能的查询进行分析。

    我有一个更大的问题是您查询的性质。您既没有显示完整的查询,也没有显示完整的架构(我看到的是“generic.id”,但未在文档架构中看到,并且您的查询显示了在某个时间范围内拉起每个文档-是正确的吗?)。当查询被用于路由的字段上的精确匹配所绑定(bind)时,用于索引的自定义路由最有用。因此,如果我有一个包含每个人文档的索引,而我的查询模式是在单个查询中仅检索单个用户的文档,那么按用户ID进行自定义路由将对提高查询性能和减少总体群集负载非常有用。

    要考虑的第二件事是摄取与查询的总体平衡。每天您要接收超过2000万个文档-您每天要执行多少个查询?如果该数字<<<摄取率,您可能需要考虑是否需要自定义路线。此外,如果查询性能良好或良好,则可能不希望增加其他复杂性。

    最后,根据摄取日期与created_at进行索引。我们也为此感到挣扎,因为在接收新文档方面有些滞后。目前,我们已经按摄取日期进行存储,因为它更易于管理,并且一次查询多个索引不是一个大问题,尤其是如果您自动创建1周,2周,1个月,2个月等的别名时。更大的问题是分布是什么-如果您要在几周或几个月后提交文档,也许您想更改为created_at的索引编制,但这将需要使这些索引保持联机状态并保持相当长的一段时间。

    我们目前每天使用多个文档索引,基本上是“-”格式。实际上,这目前意味着每天5个索引。这使我们在将数据移入和移出群集时更具选择性。并非对您的建议,只是我们学到的东西对我们有用。

    2)这是关于ES的绝佳思路-每天创建一个新索引,随着时间的推移,您可以进行调整以增加每个索引的分片数量。虽然无法为现有索引更改它,但您每天都在创建一个新索引,并且可以基于实际生产分析来做出决定。当然,您希望监视这个数字,并准备随着/如果每天摄入量增加而增加分片的数量。这不是最简单的折衷方案-每个分片都是一个Lucene实例,该实例可能具有多个文件。每个索引有更多的碎片不是免费的,因为碎片会随着时间增加。假设您的用例为6个月,则在3个节点(182天x 5个主副本和每天5个副本)中打开了1800多个分片。每个分片可能打开多个文件。随着群集中的总分片数量增加到这些范围,我们发现了一定程度的开销以及对节点上资源使用的影响。您的里程可能会有所不同,但是当您计划一次保留182个索引(6个月)时,我会谨慎地增加每个索引的分片数量-这是一个倍数。如果您对默认分片计数进行任何更改,我肯定会提前对其进行基准测试。

    3)没有任何其他人可以为您提前预测查询性能。它基于群集的总体负载,查询复杂性,查询频率,硬件等。它非常适合您的环境。您将必须对此进行基准测试。就个人而言,鉴于您已经加载了数据,我将使用ES快照并还原以在测试环境中显示此数据。尝试使用默认的1个副本进行尝试,看看它如何进行。添加副本分片对于数据冗余非常有用,并且可以帮助在整个群集中分散查询,但代价不菲-存储量增加50%加上每个额外的副本分片,将为其运行的节点带来额外的接收成本。如果您需要冗余并可以节省容量,那就太好了;如果您没有足够的查询量来真正利用它,那就太好了。

    4)您的问题不完整(以“我们永不结束”),因此我无法直接回答-但是更大的问题是,为什么要自定义路由?当然,它可以带来很大的性能优势,但是仅当您可以根据用于路由的字段将一组文档分开时,它才有用。从示例数据和部分查询来看,还不是很清楚。就我个人而言,我将在没有任何自定义路由的情况下对其进行测试,然后对其进行尝试,以查看其是否具有重大影响。

    5)另一个问题需要您自己做一些工作。您需要(至少)跟踪JVM堆使用情况,总内存和cpu使用情况,磁盘使用情况以及随时间推移的磁盘io Activity 。我们这样做,并且设置了阈值以在出现问题之前就发出警报,以便我们可以尽早将新成员添加到集群中。请记住,将节点添加到群集时,ES将尝试重新平衡群集。如果您使一个节点陷入问题(堆耗尽,JVM错误,硬件故障,网络故障等),则只有三个具有较大初始文档集的节点运行生产会引起问题。 ES将会变黄并在改组时在那呆一段时间。

    就大文件数量和高摄取量而言,我个人会更早地开始添加节点。有了更多的节点后,如果您将某个节点取出进行维护,就不会有什么问题了。关于现有配置,每个节点如何获得8 TB的HDD?假设每天摄入8GB数据,对于6个月的数据来说似乎已经过时了。考虑到数据量和索引/分片数量,我非常怀疑您将要移到更多节点,这甚至会进一步减少每个节点的存储需求。

    我绝对希望通过在只有1或2个节点的群集上循环大量获取和正常查询频率的循环来基准化每个节点的最大文档数量,并查看失败的地方(性能,堆耗尽或其他问题) )。然后,我计划将每个节点的文档数量保持在该数量以下。

    所有这些都让我大吃一惊,并说我怀疑您是否会对3个16GB节点上的40亿个文档感到满意。即使它成功(再次测试,测试,测试),失去一个节点也将是一件非常大的事情。我个人比较喜欢较小的节点,但更喜欢其中的许多节点。

    其他想法-我们最初以3个Amazon EC2 m1.xlarge实例(4个核心,15 GB内存)为基准,这些实例在提取几天后就可以正常工作,每天有80M文档,平均文档大小比您看上去要大。最大的问题是打开的索引和分片的数量(我们每天创建数百个新索引,每天可能增加几千个分片,这正在产生问题)。此后,我们添加了几个具有30GB内存和8个内核的新节点,然后又添加了80M文档进行测试。我们当前的生产方法是保留相对较大的节点而不是中等大小的节点。

    更新:

    关于基准测试硬件,如上所述,它已在运行ubuntu 12.04 LTS和ES 1.1.0的3个Amazon EC2 m1.xlarge虚拟实例上进行了基准测试。我们每天运行大约8000万个文档(从以前使用的MongoDB数据库中提取数据)。每个实例通过Amazon EBS拥有1 TB的存储,我认为配置IOPS为1000 IOPS。我们跑了大约4-5天。我们似乎每天将CPU限制为80M,并相信更多的节点会增加我们的摄取率。随着基准测试的运行以及索引和分片数量的增加,我们发现内存压力也在增加。我们创建了大量的索引和分片(每1 M个文档大约4个-5索引,或者每天大约400个索引,每个索引5个主分片和1个副本分片)。

    关于索引别名,我们通过cron条目创建了1周,2周等的索引别名滚动,以便我们的应用程序可以访问已知的索引别名,并且始终从今天开始按设定的时间运行。我们正在使用索引别名rest api创建和删除它们:

    http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-aliases.html

    关于elasticsearch - 适用于具有大量聚合的大型集群的ElasticSearch设置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23931654/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com