导语 | 腾讯云Elasticsearch 被广泛应用于日志实时剖析、结构化数据分析、全文检索等场景中,本文将以情景植入的形式,向大家介绍与腾讯云客户单干过程中遇到的各种典型问题,以及相应的解决思路与办法,心愿与大家一起交换。文章作者:bellen,腾讯云大数据研发工程师。
一、背景
某中型互联网公司的游戏业务,应用了腾讯云的 Elasticsearch 产品,采纳 ELK 架构存储业务日志。
因为游戏业务自身的日志数据量十分大(写入峰值在 100w qps ),在服务客户的几个月中,咱们踩了不少坑。通过数次优化与调整,最初将客户的 ES 集群调整得比较稳定,防止了在业务顶峰时客户集群的读写异样,并且升高了客户的资金老本和应用老本。
二、与客户的首次交锋
解决方案架构师A:bellen, XX公司要上线一款新游戏,日志存储决定用 ELK 架构,他们决定在 XX云和咱们之间二选一,咱们首先去他们公司和他们交换一下,争取拿下!
bellen: 好,随时有空!
随后和架构师一起返回该公司,跟负责底层组件的运维部门的负责人进行沟通。
XX公司运维老大:不要讲你们的PPT了,先通知我你们能给咱们带来什么!
bellen:呃,咱们有很多劣势,比方能够灵便扩缩容集群,还能够一键平滑降级集群版本,并且提供有跨机房容灾的集群从而实现高可用......
XX公司运维老大:你说的这些别的厂商也有,我就问一个问题,咱们当初要存储一年的游戏日志,不能删除数据,每天就按 10TB 的数据量算,一年也得有个 3PB 多的数据,这么大的数量,都放在SSD云盘上,老本太高了。你们有什么计划既可能满足咱们存储这么大数据量的需要,同时可能升高咱们的老本吗?
bellen:咱们自身提供的有冷热模式的集群,热节点采纳 SSD 云硬盘,冷节点采纳 SATA 盘,采纳 ES 自带的 ILM 索引生命周期治理性能,定期把较老的索引从热节点迁徙到冷节点上,这样从整体上能够降低成本。
另外,也能够定期把更老的索引通过 snapshot 快照备份到 COS 对象存储中,而后删除索引,这样老本就更低了。
XX公司运维老大:存储到 COS 就是冷存储呗,咱们须要查问 COS 里的数据时,还得再把数据恢复到 ES 里?这样不行,速度太慢了,业务等不了那么长时间。咱们的数据不能删除,只能放在 ES 里!你们能不能给咱们提供一个 API , 让老的索引数据尽管存储在 COS 里,然而通过这个 API 仍然能够查问到数据,而不是先复原到 ES , 再进行查问?
bellen:呃,这个能够做,然而须要工夫。是否能够采纳 hadoop on COS 的架构,把存量的老的索引数据通过工具导入到 COS,通过 hive 去查问,这样老本会非常低,数据仍然是随时可查的。
XX公司运维老大:那不行,咱们只想用成熟的 ELK 架构来做,再减少 hadoop 那一套货色,咱们没那么多人力搞这个事。
bellen: 好吧,那能够先搞一个集群测试起来,看看性能怎么样。对于存量数据放在 COS 里然而也须要查问的问题,咱们能够先制定方案,尽快施行起来。
XX公司运维老大:行吧,咱们当初按每天 10TB 数据量预估,先购买一个集群,能撑 3 个月的数据量就行,能给一个集群配置的倡议吗?
bellen: 目前反对单节点磁盘最大 6TB , cpu 和内存的话能够放到 8 核 32G 单节点,单节点跑 2w qps 写入没有问题,前面也能够进行纵向扩容和横向扩容。
XX公司运维老大:好,咱们先测试一下。
三、集群顶不住压力了
N 天后,架构师 A 间接在微信群里反馈:bellen, 客户反馈这边的 ES 集群性能不行啊,应用 logstash 生产 kafka 中的日志数据,跑了快一天了数据还没追平,这是线上的集群,麻烦紧急看一下吧。
我一看,一脸懵,什么时候曾经上线了啊,不是还在测试中吗?
XX公司运维B: 咱们购买了 8 核 32G*10 节点的集群,单节点磁盘 6TB , 索引设置的10 分片 1 正本,当初应用 logstash 生产 kafka 中的数据,始终没有追平,kafka 中还有很多数据积压,感觉是 ES 的写入性能有问题。
随后我立刻查看了集群的监控数据,发现 cpu 和 load 都很高,jvm 堆内存使用率均匀都到了 90% ,节点 jvm gc 十分频繁了,局部节点因为响应迟缓,不停的离线又上线。
通过沟通,发现用户的应用姿态是 filebeat+kafka+logstash+elasticsearch , 以后曾经在 kafka 中存储了有10天的日志数据,启动了 20 台 logstash 进行生产,logstash 的 batch size 也调到了 5000,性能瓶颈是在 ES 这一侧。
客户 8 核 32G*10 节点的集群,实践上跑 10w qps 没有问题,然而 logstash 生产积压的数据往 ES 写入的 qps 远不止10w,所以是 ES 扛不住写入压力了,只能对 ES 集群进行扩容。
为了放慢存量数据的生产速度,先纵向扩容单节点的配置到 32 核 64GB,之后再横向减少节点,以保障 ES 集群可能最大反对 100w qps 的写入(这里须要留神的是,减少节点后索引的分片数量也须要调整)。
所以个别新客户接入应用 ES 时,必须要当时评估好节点配置和集群规模,能够从以下几个方面进行评估:
- 存储容量:要思考索引正本数量、数据收缩、ES 外部工作额定占用的磁盘空间(比方 segment merge )以及操作系统占用的磁盘空间等因素,如果再须要预留 50% 的闲暇磁盘空间,那么集群总的存储容量大概为源数据量的 4 倍;
- 计算资源:次要思考写入,2 核 8GB 的节点能够反对 5000 qps 的写入,随着节点数量和节点规格的晋升,写入能力根本呈线性增长;
- 索引和分片数量评估:个别一个 shard 的数据量在 30-50 GB为宜,能够以此确定索引的分片数量以及确定按天还是按月建索引。须要管制单节点总的分片数量,1GB 堆内存反对 20-30 个分片为宜。另外须要管制集群整体的分片数量,集群总体的分片数量个别不要超过 3w 。
四、logstash 生产 kafka 性能调优
下面遇到的问题是业务上线前没有对集群配置和规模进行正当的评估,导致上线后 ES 集群扛不住了。
通过正当的扩容解决,集群最终抗住了写入压力,然而新的问题又随之呈现了。因为 kafka 积压的数据比拟多,客户应用 logstash 生产 kafka 数据时,反馈有两个问题:
- 减少多台 logstash 生产 kafka 数据,生产速度没有线性晋升;
- kafka 的不同 topic 生产速度不平均、topic 内不同 partition 生产的速度也不平均。
通过剖析客户logstash的配置文件,发现问题呈现的起因次要是:
- topic 的 partition 数量少:尽管 logstash 机器数量多,然而却没有充分利用机器资源并行生产数据,导致生产速度始终上不去;
- 所有 logstash 的配置文件都雷同,应用一个 group 同时生产所有的 topic,存在资源竞争的问题。
剖析后,对 kafka 和 logstash 进行了如下优化:
- 进步 kafka topic 的分区数量;
- 对 logstash 进行分组:对于数据量较大的 topic,能够独自设置一个生产组进行生产,有一组 logstash 独自应用这个生产组对该 topic 进行生产;其它的数据量较小的 topic,能够共用一个生产组和一组 logstash ;
- 每组 logstash 中总的 consumer_threads 数量和生产组总的 partition 数量保持一致。比方有 3 个 logstash 过程,生产的 topic 的 partition 数量为 24, 那么每个 logstash 配置文件中的 consumer_threads 就设置为 8 。
通过上述优化,最终使得 logstash 机器资源都被充分利用上,很快生产完沉积的 kafka 数据,待生产速度追平生成速度后,logstash 生产 kafka 始终稳固运行,没有呈现积压。
另外,客户一开始应用的是 5.6.4 版本的 logstash,版本较老,应用过程中呈现因为单个音讯体过长导致 logstash 抛异样后间接退出的问题:
whose size is larger than the fetch size 4194304 and hence cannot be ever
通过把 logstash 降级至高版本 6.8 防止了这个问题( 6.x 版本的 logstash 修复了这个问题,防止了 crash )。
五、磁盘要满了,紧急扩容?
客户的游戏上线有一个月了,原先预估每天最多有 10TB 的数据量,理论则是在经营流动期间每天产生 20TB 的数据,原先 6TB*60=360TB 总量的数据盘使用率也达到了 80% 。
针对这种状况,咱们倡议客户应用冷热拆散的集群架构,在原先 60 个热节点的根底上,减少一批 warm 节点存储冷数据,利用 ILM( 索引生命周期治理)性能定期迁徙热节点上的索引到 warm 节点上。
通过减少 warm 节点的形式,客户的集群磁盘总量达到了 780TB, 能够满足最多三个月的存储需要。然而客户的需要还没有满足。
XX公司运维老大:给咱们一个能寄存一年数据的计划吧,总是通过加节点扩容磁盘的形式不是长久之计,咱们得天天盯着这个集群,运维老本很高!并且始终加节点,ES 会扛不住吧?
bellen: 能够尝试应用咱们新上线的反对本地盘的机型,热节点最大反对 7.2TB 的本地 SSD 盘,warm 节点最大反对 48TB 的本地 SATA 盘。
一方面热节点的性能相比云盘进步了,另外 warm 节点能够反对更大的磁盘容量。单节点能够反对的磁盘容量增大了,节点数量就不必太多了,能够防止踩到因为节点数量太多而触发的坑。
XX公司运维老大:当初用的是云盘,能替换老本地盘吗,怎么替换?
bellen: 不能间接替换,须要在集群中新退出带本地盘的节点,把数据从老的云盘节点迁徙到新的节点上,迁徙实现后再剔除掉旧的节点,这样能够保障服务不会中断,读写都能够失常进行。
XX公司运维老大:好,能够施行,尽快搞起来!
云盘切换为本地盘,是通过调用云服务后盾的 API 主动施行的。在施行之后,触发了数据从旧节点迁徙到新节点的流程。然而大概半个小时后,问题又呈现了:
XX公司运维B: bellen, 快看一下,ES 的写入快掉 0 了。
通过查看集群监控,发现写入 qps 间接由 50w 降到 1w,写入回绝率猛增。通过查看集群日志,发现是因为以后小时的索引没有创立胜利导致写入失败。
紧急情况下,执行了以下操作定位到了起因:
1. GET _cluster/health
发现集群衰弱状态是 green,然而有大概 6500个 relocating_shards, number_of_pending_tasks 数量达到了数万。
2. GET _cat/pending_tasks?v
发现大量的 "shard-started" 工作在执行中,工作优先级是 "URGENT" , 以及大量的排在前面的 "put mapping" 工作,工作优先级是 "HIGH" ; "URGENT" 优先级比 "HIGH" 优先级要高,因为大量的分片从旧的节点迁徙到新的节点上,造成了索引创立的工作被阻塞,从而导致写入数据失败。
3. GET _cluster/settings
为什么会有这么多的分片在迁徙中?通过 GET _cluster/settings 发现 "cluster.routing.allocation.node_concurrent_recoveries" 的值为 50 。而目前有 130 个旧节点在把分片迁徙到 130 个新节点中,所以有 130*50=6500 个迁徙中的分片。
而 "cluster.routing.allocation.node_concurrent_recoveries" 参数的值默认为 2 。应该是之前在执行纵向扩容集群时,为了放慢分片迁徙速度人为批改了这个值。因为集群一开始节点数量没有很多,索引同时迁徙中的分片也不会太多,所以创立新索引不会被阻塞。
4. PUT _cluster/settings
当初通过PUT _cluster/settings把 "cluster.routing.allocation.node_concurrent_recoveries" 参数批改为 2 。然而因为 "put settings" 工作的优先级也是 "HIGH" , 低于 "shard-started" 工作的优先级,所以更新该参数的操作还是会被阻塞, ES 报错执行工作超时。此时,进行了多次重试,最终胜利把 "cluster.routing.allocation.node_concurrent_recoveries" 参数批改为了 2 。
5. 勾销 exclude 配置
当初通过 GET _cluster/health 看到迁徙中的分片数量在逐步缩小,为了不减少新的迁徙工作,把执行数据迁徙的 exclude 配置勾销掉:
PUT _cluster/settings
6. 减速分片迁徙
同时调大分片复原时节点进行数据传输的每秒最大字节数(默认为40MB),减速存量的分片迁徙工作的执行:
PUT _cluster/settings
7. 提前创立索引
当初看到迁徙中的分片数量缓缓缩小,新索引曾经创立胜利了,写入恢复正常了。到下个整点时,发现新建索引还是比较慢,因为还有几百个分片在迁徙中,创立新索引大略耗时5分钟,这5分钟内写入也是失败的。
等几百个迁徙中的分片都执行结束后,新建索引就比拟快了,也不会再写入失败了。
然而问题是以后正在执行云盘节点切换为本地盘的流程,须要把数据从旧的130个节点上迁徙到新的130个节点上,数据迁徙的工作不能停,那该怎么办?
既然新创建索引比较慢,那就只好提前把索引都创立好,防止了在每个整点数据写入失败的状况。通过编写python脚本,每天执行一次,提前把第二天的每个小时的索引创立好,创立实现了再把 "cluster.routing.allocation.exclude._name" 更改为所有的旧节点,保证数据迁徙工作可能失常执行。
8. 后果展现
总量 400TB 的数据,大概通过 10 天左右,终于实现迁徙了。配合提前新建索引的python脚本,这10天内也没有呈现写入失败的状况。
通过了这次扩容操作,总结了如下教训:
分片数量过多时,如果同时进行迁徙的分片数量过多,会阻塞索引创立和其它配置更新操作。
所以在进行数据迁徙时,要保障 "cluster.routing.allocation.node_concurrent_recoveries" 参数和 "cluster.routing.allocation.cluster_concurrent_rebalance" 为较小的值。
如果必须要进行数据迁徙,则能够提前创立好索引,防止ES主动创立索引时耗时较久,从而导致写入失败。
六、10 万个分片?
在稳固运行了一阵后,集群又出问题了。
XX公司运维B: bellen , 昨晚凌晨 1 点钟之后,集群就没有写入了,当初 kafka 里有大量的数据沉积,麻烦尽快看一下?
通过cerebro查看集群,发现集群处于 yellow 状态,同时发现集群有大量的谬误日志:
{"message":"blocked by: [SERVICE_UNAVAILABLE/1/state not recovered /
而后再进一步查看集群日志,发现有 "master not discovered yet…" 之类的谬误日志,查看三个 master 节点,发现有两个 master 挂掉,只剩一个了,集群无奈选主。
登陆到挂了的 master 节点机器上,发现保活程序无奈启动 es 过程,第一直觉是 es 过程 oom了;此时也发现 master 节点磁盘使用率100%, 查看了 JVM 堆内存快照文件目录,发现有大量的快照文件,于是删除了一部分文件,重启 ES 过程,过程失常启动了;然而问题是堆内存使用率太高,gc 十分频繁,master 节点响应十分慢,大量的创立索引的工作都超时,阻塞在工作队列中,集群还是无奈恢复正常。
看到集群 master 节点的配置是 16 核 32GB 内存,JVM 理论只调配了 16GB 内存。此时只好通过对 master 节点原地减少内存到 64GB (虚拟机,应用的腾讯云 CVM, 能够调整机器规格,须要重启),master 节点机器重启之后,批改了 es 目录 jvm.options 文件,调整了堆内存大小,重新启动了 es 过程。
3 个 master 节点都恢复正常了,然而分片还须要进行复原。通过 GET _cluster/health 看到集群以后有超过 10w 个分片,而这些分片复原还须要一段时间。
通过调大 "cluster.routing.allocation.node_concurrent_recoveries", 增大分片复原的并发数量。实际上 5w 个主分片复原的是比拟快的了,然而正本分片的复原就绝对慢很多,因为局部正本分片须要从主分片上同步数据能力复原。此时能够采取的形式是把局部旧的索引正本数量调为0, 让大量正本分片复原的工作尽快完结,保障新索引可能失常创立,从而使得集群可能失常写入。
总结这次故障的根本原因是:集群的索引和分片数量太多,集群元数据占用了大量的堆内存,而 master 节点自身的 JVM 内存只有 16GB (数据节点有32GB), master 节点频繁 full gc 导致 master 节点异样,从而最终导致整个集群异样。
所以要解决这个问题,还是得从根本上解决集群的分片数量过多的问题。
目前日志索引是依照小时创立,60 分片 1 正本,每天有 24*60*2=2880 个分片,每个月就产生 86400 个分片,这么多的分片可能会带来重大的问题。有以下几种形式解决分片数量过多的问题:
- 能够在 ILM 的 warm phase 中开启 shrink 性能,对老的索引从 60 分片 shrink 到 5 分片,分片数量能够升高 12 倍;
- 业务能够把每小时创立索引批改为每两个小时或者更长,能够依据每个分片数量最多反对 50GB 的数据推算多长时间创立新索引适合;
- 对老的索引设置正本为 0,只保留主分片,分片数量可能再降落近一倍,存储量也降落近一倍;
- 定期敞开最老的索引,执行 {index}/_close 。
和客户沟通过后,客户示意能够承受前两种形式,后两种不能承受,因为思考到存在磁盘故障的可能性,必须要保留一个副原本保证数据的可靠性。另外还必须保障所有数据都是随时可查问的,不能敞开。
七、有点“坑”的 ILM
在上文中,尽管通过长期给 master 节点减少内存,抗住了 10w 分片,然而不能从根本上解决问题。
客户的数据是打算保留一年的,如果不进行优化,集群必然扛不住数十万个分片,所以接下来须要着重解决集群整体分片数量过多的问题。
前文也提到了,客户能够承受开启 shrink 以及升高索引创立粒度(通过调整后,每两个小时创立一个索引),这在肯定水平上缩小了分片的数量,可能使集群临时稳固一阵。
辅助客户在 kibana 上配置了如下的 ILM 策略:
在 warm phase , 把创立工夫超过 360 小时的索引从 hot 节点迁徙到 warm 节点上,放弃索引的正本数量为 1 。
之所以应用 360 小时作为条件,而不是 15天 作为条件,是因为客户的索引是按小时创立的。
如果以 15 天作为迁徙条件,则在每天凌晨都会同时触发 15 天前的 24个 索引,一共 24*120=2880 个分片同时开始迁徙索引,容易引发前文介绍的因为迁徙分片数量过多导致创立索引被阻塞的问题。
所以以 360 小时作为条件,则在每个小时只会执行一个索引的迁徙,这样把 24 个索引的迁徙工作打平,防止其它工作被阻塞的状况产生。
同时,也在 warm phase 阶段,设置索引 shrink ,把索引的分片数缩成 5 个。因为老的索引曾经不执行写入了,所以也能够执行 force merge , 强制把 segment 文件合并为 1 个,能够取得更好的查问性能。
另外,设置了 ILM 策略后,能够在索引模板里减少 index.lifecycle.name 配置,使得所有新创建的索引都能够和新增加的 ILM 策略关联,从而使得 ILM 可能失常运行。
客户应用的 ES 版本是 6.8.2 , 在运行 ILM 的过程中, 也发现一些问题:
新增加的策略只能对新创建的索引失效,存量的索引只能通过批量批改索引 settings 里的 index.lifecycle.name 执行策略。
如果一个策略进行了批改,那么所有存量的索引,不论是有没有执行过该策略,都不会执行批改后的策略,也即批改后的策略只对批改胜利后新创建的索引失效。
比方一开始的策略没有开启 shrink , 当初批改策略内容增加了 shrink 操作,那么只有之后新创建的索引在达到策略触发条件(比方索引曾经创立超过 360 个小时)后才会执行 shrink, 而之前的所有索引都不会执行 shrink ,此时若想对存量的索引也执行 shrink ,只可能通过脚本批量执行了。
在 warm phase 同时执行索引迁徙和 shrink 会触发 es 的 bug 。如下面图中的 ILM 策略,索引自身蕴含 60 分片 1 正本,初始时都在 hot 节点上,在创立实现 360 小时之后,会执行迁徙,把索引都迁徙到 warm 节点上,同时又须要把分片 shrink 到 5 ,在理论执行中,发现一段时间后有大量的 unassigned shards ,分片无奈调配的起因如下:
"deciders" : [
这是因为 shrink 操作须要新把索引残缺的一份数据都迁徙到一个节点上,而后在内存中构建新的分片元数据,把新的分片通过软链接指向到几个老的分片的数据,在 ILM 中执行 shrink 时, ILM 会对索引进行如下配置:
问题是索引蕴含正本,而主分片和正本分片又不能在同一个节点上,所以会呈现局部分片无奈调配的状况(不是全副,只有一部分)。这里应该是触发了 6.8 版本的 ILM 的 bug ,须要查看源码能力定位解决这个bug,目前还在钻研中。以后的 workaround 是通过脚本定期扫描呈现 unassigned shards 的索引,批改其 settings :
优先保障分片先从 hot 节点迁徙到 warm 节点,这样后续的 shrink 能力顺利执行。也可能执行失败,因为60个分片都在一个节点上,可能会触发 rebalance , 导致分片迁徙走, shrink 的前置条件又不满足,导致执行失败。
要齐全躲避这个问题,还得在 ILM 策略中设置,满足创立工夫超过 360 个小时的索引,正本间接调整为 0 ,然而客户又不承受,没方法。
八、本人实现SLM
上文介绍了 10w 个分片会给集群带来的影响和通过开启 shrink 来升高分片数量,然而依然有两个须要重点解决的问题:
- 索引一直新建,如何保障一年内,集群总的分片数量不高于 10w ,稳固在一个较低的水位?
- ILM 中执行 shrink 可能会导致局部分片未调配以及 shrink 执行失败,怎么彻底解决呢?
能够估算一下,按小时建索引, 60 分片 1 正本,一年的分片数为 24*120*365=1051200 个分片,执行 shrink 后分片数量 24*10*350 + 24*120*15 = 127200 (15天内的新索引为了保障写入性能和数据可靠性,依然放弃60分片1正本,旧的索引shrink为5分片1正本), 依然有超过 10w 个分片。
联合集群一年总的存储量和单个分片能够反对的数据量大小进行评估,咱们冀望集群总体的分片数量能够稳固为 6w~8w ,怎么优化呢?
能够想到的计划是执行数据冷备份,把比拟老的索引都冷备到其它的存储介质上比方 HDFS、S3、腾讯云的 COS 对象存储等。
但问题是这些冷备的数据如果也要查问,须要先复原到 ES 中才可查,复原速度比较慢,客户无奈承受。由此也产生了新的想法,目前老的索引依然是 1 正本,能够把老索引先进行冷备份,再把正本调为 0 ,这样做有以下几点益处:
- 集群整体分片数量能升高一半;
- 数据存储量也能升高一半,集群能够存储更多数据;
- 老的索引依然随时可查;
- 极其状况下,磁盘故障引起只有一个正本的索引数据无奈复原时,能够从冷备介质中进行复原。
通过和客户沟通,客户承受了上述计划,打算把老索引冷备到腾讯云的对象存储 COS 中,施行步骤为:
- 所有存量的老索引,须要批量解决,尽快地备份到 COS 中,而后批量批改正本数量为 0 ;
- 最近新建的索引,采纳按天备份的策略,联合 ILM , 批改策略,在 ILM 执行过程中批改索引正本数为 0 ( ILM 的 warm phase 和 cold phase 都反对设置正本数量)。
其中第一个步骤的施行能够通过脚本实现,本案例中就采纳了腾讯云 SCF 云函数进行施行,方便快捷可监控。施行要点有:
- 按天创立 snapshot ,批量备份每天产生的 24 个索引。如果是按月或者更大粒度创立快照,因数据量太大如果执行快照过程中呈现中断,则必须全部重来,耗时耗力;按小时创立快照也不实用,会造成快照数量太多,可能会踩到坑;
- 每创立一个快照,后续须要轮询快照的状态,保障前一个快照 state 为 "SUCCESS" 之后,再创立下一个快照。因为快照是按天创立的,快照名字能够为 snapshot-2020.06.01 , 该快照只备份 6 月 1 号的所有索引。而在查看到 snapshot-2020.06.01 快照执行胜利后,而后新建下一个快照时,须要晓得要对哪天的索引打快照,因而须要记录以后正在执行哪一个快照。有两种形式记录,一是把以后正在执行的快照日期后缀 "2020.06.01" 写入到文件中, 脚本通过定时工作轮询时,每次都读文件;另外一种形式是创立一个长期的索引,把 "2020.06.01" 写入到这个长期索引的一个 doc 中,之后对该 doc 进行查问或者更新。
- 创立快照时,能够把 "include_global_state" 置为 false, 不对集群的全局状态信息进行备份。
在施行完第一个步骤之后,就能够批量把对索引进行过备份的索引正本数都调为 0 。 这样一次性就能开释很多磁盘空间,并且显著升高了集群整体的分片数量。
接下来施行第二个步骤,须要每天执行一次快照,多创立工夫较久的索引进行备份。施行比较简单,能够通过 crontab 定时执行脚本或者应用腾讯云 SCF 执行。
之后,就能够批改 ILM 策略,开启 cold phase , 批改索引正本数量为 0 :
此处的 timing 是创立工夫 20 天后,须要保障在第二步骤中,对过来老索引数据备份先执行实现后才能够进入到 cold phase 。
通过老索引数据冷备并且升高索引正本,咱们能够把集群整体的分片数量维持在一个较低的水位。
然而还有另外一个问题待解决,也即 shrink 失败的问题。刚好,咱们能够利用对老索引数据冷备并且升高索引正本的计划,来彻底解决 shrink 失败的问题。
在前文有提到,shrink 失败归根结底是因为索引的正本数量为 1 。当初咱们能够把数据备份和升高正本提前,让老索引进入到 ILM 的 warm phase 中时曾经是 0 正本,之后再执行 shrink 操作就不会有问题了。
同时,因为正本升高了,索引从 hot 节点迁徙到 warm 节点迁徙的数据量也缩小了一半,从而升高了集群负载,两全其美。
因而,咱们须要批改 ILM 策略,在 warm phase 就把索引的正本数量调整为 0 , 而后去除 cold phase 。
另外一个可选的优化项是:对老的索引进行解冻。解冻索引是指把索引常驻内存的一些数据从内存中清理掉(比方 FST , 元数据等), 从而升高内存使用量。
而在查问曾经解冻的索引时,会从新构建出长期的索引数据结构寄存在内存中,查问结束再清理掉。须要留神的是,默认状况下是无奈查问曾经解冻的索引的,须要在查问时显式的减少 "ignore_throttled=false" 参数。
通过上述优化,咱们最终解决了集群整体分片数量过多和 shrink 失败的问题。在施行过程中引入了额定的定时工作脚本施行自动化快照,实际上在 7.4 版本的 ES 中,曾经有这个性能了,个性名称为 SLM (快照生命周期治理),并且能够联合 ILM 应用,在 ILM 中减少了 "wait_for_snapshot" 的 ACTION , 然而却只能在 delete phase 中应用,不满足咱们的场景。
客户非常喜爱的 Searchable Snapshots !
在上述场景中,咱们破费大量的精力去解决问题和优化应用形式,保障 ES 集群可能稳固运行,反对 PB 级别的存储。
溯本回原,如果咱们能有一个计划使得客户只须要把热数据放在 SSD 盘上,而后冷数据存储到 COS/S3 上,但同时又使冷数据可能反对按需随时可查,那咱们后面碰到的所有问题都迎刃而解了。能够设想失去的益处有:
- 只须要更小规模的集群和十分便宜的 COS/S3 对象存储就能够反对 PB 级别的数据量,客户的资金老本非常低;
- 小规模的集群只须要可能撑持热索引的写入和查问即可,集群整体的分片数不会太多,从而防止了集群不稳固景象的产生。
而这正是目前ES开源社区正在开发中的 Searchable Snapshots 性能。
从 [](https://www.elastic.co/guide/... Searchable Snapshots API 的官网文档上能够看到,咱们能够创立一个索引,将其挂载到一个指定的快照中,这个新的索引是可查问的,尽管查问工夫可能会慢点,然而在日志场景中,对一些较老的索引进行查问时,提早大点个别都是能够承受的。
所以我认为,Searchable Snapshots 解决了很多痛点,将会给 ES 带了新的凋敝!
结语
经验过上述运维和优化 ES 集群的实际,咱们总结了如下教训分享给大家:
第一:新集群上线前务必做好集群规模和节点规格的评估。
第二:集群整体的分片数量不能太多,能够通过调整应用形式并且借助 ES 自身的能力一直进行优化,使得集群总体的分片数维持在一个较低的水位,保障集群的稳定性。
第三:Searchable Snapshots 利器会给 ES 带来新的生命力,须要重点关注并钻研其实现原理。
从一开始和客户进行接触,理解客户诉求,逐渐解决 ES 集群的问题,最终使得 ES 集群可能保持稳定,这两头的经验让我真真正正的领悟到"实际出真知"这句话的真谛。只有一直实际,能力对异常情况迅速做出反馈,以及对客户提的优化需要迅速反馈。
看腾讯技术,学云计算常识,来云+社区