|
Elasticsearch 是一种开源搜索引擎和分析商店,被各种应用程序使用,从电子商务商店的搜索到使用 ELK 堆栈(“Elasticsearch、Logstash、Kibana”的缩写)的内部日志管理工具。作为分布式数据库,您的数据被划分为“分片”,然后分配给一个或多个服务器。
由于这种分片,对 Elasticsearch 集群的读取或写入请求需要在多个节点之间进行协调,因为在单个服务器上没有数据的“全局视图”。虽然这使得 Elasticsearch 具有高度可扩展性,但它也使得它的设置和调整比其他流行的数据库(如 MongoDB 或 PostgresSQL,它们可以在单个服务器上运行)复杂得多。
当出现可靠性问题时,如果您的 Elasticsearch 设置有问题或不稳定,救火工作可能会很紧张。您的事件可能会影响客户,从而对收入和您的商业声誉产生负面影响。快速补救措施很重要,但在发生事故或中断期间花费大量时间在线研究解决方案并不是大多数工程师的奢侈。本指南旨在作为工程师运行的常见问题的备忘单,这些问题可能会导致 Elasticsearch 出现问题以及需要查找的内容。
作为通用工具,Elasticsearch 具有数千种不同的配置,使其能够适应各种不同的工作负载。即使在线发布,适用于一家公司的数据模型或配置也可能不适合您的公司。没有让 Elasticsearch 扩展的灵丹妙药,需要勤奋的性能测试和试错。
无响应的 Elasticsearch 集群问题 集群稳定性问题是最难调试的问题之一,尤其是在您的数据量或代码库没有任何变化的情况下。
检查集群状态的大小 它有什么作用? Elasticsearch 集群状态跟踪我们集群的全局状态,是控制流量和集群的核心。集群状态包括集群中节点的元数据、分片的状态以及它们如何映射到节点、索引映射(即架构)等。 集群状态通常不会经常改变。但是,某些操作(例如将新字段添加到索引映射)可以触发更新。 因为集群更新广播到集群中的所有节点,所以它应该很小(<100MB)。 较大的集群状态会很快使集群变得不稳定。发生这种情况的一种常见方式是通过映射爆炸(索引中的键太多)或索引太多。 要找什么 使用以下命令下载集群状态并查看返回的 JSON 的大小。
curl -XGET 'http://localhost:9200/_cluster/state' 怎么修 查看数据是如何被索引的。发生映射爆炸的一种常见方式是将高基数标识符用作 JSON 键。每次看到一个新键,比如“4”和“5”,集群状态都会更新。例如,下面的 JSON 将很快导致 Elasticsearch 出现稳定性问题,因为每个键都被添加到全局状态。 ? { ?"1": { ? ?"status": "ACTIVE" ?}, ?"2": { ? ?"status": "ACTIVE" ?}, ?"3": { ? ?"status": "DISABLED" ?} ? } 要解决这个问题,请将您的数据扁平化为 Elasticsearch 友好的内容:
{ ? [ ? ? { ? ? ? "id": "1", ? ? ? "status": "ACTIVE" ? ? }, ? ? { ? ? ? "id": "2", ? ? ? "status": "ACTIVE" ? ? }, ? ? { ? ? ? "id": "3", ? ? ? "status": "DISABLED" ? ? } ? ] } 检查 Elasticsearch 任务队列 它有什么作用? 当对 Elasticsearch 发出请求(索引操作、查询操作等)时,它首先被插入到任务队列中,直到工作线程可以提取它。 一旦一个工作池有一个线程空闲,它就会从任务队列中挑选一个任务并处理它。 这些操作通常由您通过:9200和:9300端口上的 HTTP 请求进行,但它们也可以在内部处理索引上的维护任务 在给定时间可能有数百或数千个正在进行的操作,但应该很快完成(如微秒或毫秒)。 要找什么 运行以下命令并查找长时间停止运行的任务,例如几分钟或几小时。 这意味着某些东西正在使集群挨饿并阻止它向前发展。 对于某些长时间运行的任务(例如移动索引)需要很长时间是可以的。但是,正常的查询和索引操作应该很快。
curl -XGET 'http://localhost:9200/_cat/tasks?detailed' 使用?detailed参数,您可以获得有关目标索引和查询的更多信息。 寻找任务始终位于列表顶部的模式。是同一个指数吗?是同一个节点吗? 如果是这样,则该索引的数据可能有问题或节点过载。 怎么修 如果请求量高于正常水平,则考虑优化请求的方法(例如使用批量 API 或更高效的查询/写入) 如果体积没有变化并且看起来是随机的,这意味着其他原因正在减慢集群的速度。任务的备份只是一个更大问题的症状。 如果您不知道请求来自何处,请将X-Opaque-Id标头添加到您的 Elasticsearch 客户端以确定哪些客户端正在触发查询。 检查 Elasticsearch 待处理任务 它有什么作用? 挂起的任务是对集群状态的挂起更新,例如创建新索引或更新其映射。 与之前的任务队列不同,挂起的更新需要多步握手才能将更新广播到集群中的所有节点,这可能需要一些时间。 在给定时间内,飞行中的任务应该几乎为零。请记住,像快照恢复这样的昂贵操作可能会导致它暂时激增。 要找什么 运行命令并确保没有或很少有任务在运行。
curl curl curl -XGET 'http://localhost:9200/_cat/pending_tasks' 如果它看起来是快速完成的持续不断的集群更新流,请查看可能触发它们的原因。是映射爆炸还是创建了太多索引? 如果只有几个,但好像卡住了,查看主节点的日志和指标,看是否有问题。例如,主节点是否遇到内存或网络问题,无法处理集群更新? 热门话题 它有什么作用? 热线程 API 是一个有价值的内置分析器,可以告诉您 Elasticseach 花费最多时间的地方。 这可以提供一些见解,例如 Elasticsearch 是否在索引刷新或执行昂贵的查询上花费了太多时间。 要找什么 调用热线程 API。为了提高准确性,建议使用?snapshots参数捕获许多快照。 curl -XGET 'http://localhost:9200/_nodes/hot_threads?snapshots=1000' 这将返回拍摄快照时看到的堆栈跟踪。 在许多不同的快照中寻找相同的堆栈。例如,您可能会看到文本5/10 snapshots sharing following 20 elements。这意味着线程在 5 个快照期间在该代码区域花费时间。 您还应该查看 CPU 百分比。如果代码区域同时具有高快照共享和高 CPU %,则这是一个热代码路径。 通过查看代码模块,拆解Elasticseach在做什么。 如果您看到 wait 或 park 状态,这通常是可以的。 怎么修 如果大量 CPU 时间花费在索引刷新上,则尝试将刷新间隔增加到超过默认的 1 秒。 如果您在缓存中看到大量内容,则可能是您的默认缓存设置不够理想,导致严重失误。 内存问题 检查 Elasticsearch 堆/垃圾收集 它有什么作用? 作为一个 JVM 进程,堆是存储大量 Elasticsearch 数据结构的内存区域,需要垃圾回收周期来修剪旧对象。 对于典型的生产设置,Elasticsearch 锁定所有mlockall在启动时使用的内存并禁用交换。如果你不这样做,现在就做。 如果某个节点的 Heap 始终高于 85% 或 90%,这意味着我们即将耗尽内存。 要找什么 collecting in the last在 Elasticsearch 日志中搜索。如果存在这些,则意味着 Elasticsearch 在垃圾收集上花费了更高的开销(这占用了其他生产任务的时间)。 只要 Elasticsearch 没有将其大部分 CPU 周期用于垃圾收集(计算花费在收集上的时间相对于所提供的总时间的百分比),偶尔使用其中一些是可以的。 在垃圾收集上花费 100% 时间的节点已停滞,无法向前推进。 出现超时等网络问题的节点实际上可能是由于内存问题。这是因为节点无法在垃圾回收周期内响应传入请求。 怎么修 最简单的方法是添加更多节点以增加集群可用的堆。但是,Elasticsearch 需要时间将分片重新平衡到空节点。 如果只有一小部分节点具有高堆使用率,您可能需要更好地平衡您的客户。例如,如果您的分片大小差异很大或具有不同的查询/索引带宽,则您可能为同一组节点分配了太多的热分片。要移动分片,请使用重新路由 API。只需调整分片感知敏感度以确保它不会被移回。
curl -XPOST -H "Content-Type: application/json" localhost:9200/_cluster/reroute -d ' { "commands": [ ? ? { ? ? ? "move": { ? ? ? ? "index": "test", "shard": 0, ? ? ? ? "from_node": "node1", "to_node": "node2" ? ? ? } ? ? } ? ] }' 如果您要向 Elasticsearch 发送大量请求,请尝试减小批量大小,使每个批量都在 100MB 以下。虽然较大的批次有助于减少网络开销,但它们需要分配更多内存来缓冲请求,这些内存在请求完成和下一个 GC 周期之前无法释放。 检查 Elasticsearch 旧内存压力 它有什么作用? 旧内存池包含在多个垃圾收集周期中幸存下来的对象,并且是长期存在的对象。 如果旧内存超过 75%,您可能需要注意它。当它填满超过 85% 时,将发生更多的 GC 周期,但无法清理对象。 要找什么 查看旧池使用/旧池最大值。如果超过 85%,那就令人担忧了。 怎么修 您是否迫不及待地加载大量现场数据?这些在内存中驻留了很长时间。 您是否正在执行许多长时间运行的分析任务?某些任务应该卸载到为 map/reduce 操作设计的分布式计算框架,如 Apache Spark。 检查 Elasticsearch 字段数据大小 它有什么作用? FieldData 用于计算聚合等字段上的terms聚合 通常,在第一次对其执行聚合之前,字段的字段数据不会加载到内存中。 但是,如果设置了,这也可以在索引刷新时预先计算eager_load_ordinals。 要找什么 查看索引或所有索引字段数据大小,如下所示:
curl -XGET 'http://localhost:9200/index_1/_stats/fielddata' 如果我们在错误的数据类型上使用索引,它可能具有非常大的字段数据结构。您是否在非常高的基数字段(如 UUID 或跟踪 ID)上执行聚合?Fielddata 不适合非常高基数的字段,因为它们会创建大量的字段数据结构。 您是否有很多字段eager_load_ordinals设置或分配大量到字段数据缓存?这会导致在刷新时间而不是查询时间生成字段数据。虽然它可以加快聚合速度,但如果您在索引刷新时计算许多字段的字段数据并且从不在查询中使用它,则它不是最佳选择。
|