某客户集群的一个节点磁盘使用率达到100%,集群写保护,被禁止写入了,ES集群存储是以节点为单位来计算集群容量的。那么本客户集群是多节点、低配置,集群索引设置1主1副。如下截图:
在选ES集群规模时,我们经常提到集群选型,规划先行。这里的规划就表示集群容量、节点选型、分片设置、索引管理、模板制定、数据建模等方面。这样执行的目的是尽量让集群规模符合用户业务预期,并保持集群的高计算、高可用能力。尽量不要让集群产生特别大的分片。那么为什么不能产生大的分片呢?
第一:大分片在数据读写方面并不具备性能优势,反而在返回结果方面因为要遍历集群所有的文档进而让master产生很大的压力;第二:大分片并不会给集群带来高计算能力。10个节点1个大分片远比10个节点10个分片计算能力要差很多;反而因为某一特定业务高峰时期索引被集中的读写所带来的集群某节点负载过高所带来的集群CPU、负载过高导致集群节点OOM进而自动下线的情况。
第三:节点重启状态下分片恢复速度极慢,甚至出现不能恢复、数据丢失的情况;
在本次客户集群维护过程中,基本都遇到了以上提到的这些问题。
基于以上,腾讯云官方建议ES集群的分片范围建议在30G-50G区间,一般我建议客户按照每个shard 40G/node.尽量避免集群出现特大分片或者单分片索引。
目前客户集群存在2个超大索引,1个1T、1个700G,客户的这几个索引不能删,而且还必须接着往里写数据。前端程序不能中断太久,要求快速解决这个问题。怎么解决?
从ES 6.6版本开始,官方推出在线切分索引shard的API -- Split ,因此我们可以通过此API将集群存量索引的主分片进行动态设置,一般用来增大索引的主分片数。具体可用参考API官网: https://www.elastic.co/guide/en/elasticsearch/reference/7.x/indices-split-index.html
这里,我大致总结一下该API的注意事项:split的过程:
1、创建一个新的目标index,其定义与源index相同,但是具有更多的primary shard。
2、将segment从源index硬链接到目标index。(如果文件系统不支持硬链接,则将所有segment都复制到新索引中,这是一个非常耗时的过程。)
3、创建低级文件后,再次对所有文档进行哈希处理,以删除属于不同shard的documents
4、恢复目标索引,就像它是刚刚重新打开的封闭索引一样。
5、 在切割的时候需要对源索引进行锁写,切割完后,再开启写入,切割过程中,如集群负载出现问题,等green后,可以删除切割成功的正在均衡分片的索引并及时扩容集群后再执行split操作。
6、 split API属于资源密集型工作,对集群的负载,比如CPU、磁盘、lOAD 负载比较高,在执行此操作前,建议用户对集群业务做一定的降低,并升级集群配置,一定要保证集群有足够的资源区执行此操作。集群配置低,不要此操作。《非常重要》
7、split API会对源分片所有内容进行复制,因此在执行此操作过程中,会发现时间耗时非常长,数据同步完后,会发现索引膨胀特别大,比如单分片索引切割成4个分片后,数据膨胀4倍,无需担心,这个是split操作的正常流程,后面可用手动进行段合并,让分片大小降下来。可以加上下面的参数:“expunge_only_deletes=true”,此命令也可以多次执行。可以通过_cat/recovery API或者celebro查看该操作进行的状态。另外,在执行段合并的命令时,分片大小也不会立即进行删除释放,而是根据其默认算法在一定的时间后自动进行合并操作,因此在手动执行段合并过程中看到的分片大小时大时小的状态也是正常的。过一段时间后,分片即可恢复正常大小状态。
8、在切的过程中,不要一次切太多分片,可以分批切割,这能减少此API切割带来的节点负载高而导致的OOM的情况。
9、 切割完后目标索引状态为只读,需要手动开启写入。
10、发现新生产的索引无问题后,可以将源超大分片的索引给关闭或者删除。这里是用户确认后就删除了。
那么这样,我们就完成了一个大分片的切割过程,这个过程比较复杂并且漫长,大概耗时2天左右。目标索引如下图所示:
split 会 copy 所有 segment 到新的 shard,目标索引数据会有很大的膨胀,forcemerge 之后就大小就正常。
split操作对集群资源有特别大要求,建议业务低峰期使用,避免数据丢失。谨慎操作。
split操作需要对源索引停写,对集群负载有要求,属于停机离线业务数据操作。
业务不能停、主分片需要调大,动态调整,可在业务低峰期考虑reindex API,但是如果操作数据特别大,也是一个比较漫长的过程。
首先,我们想以下几个问题:
问题一:上面提到了大分片带来各种问题,那么如何才能避免集群出现超大分片?
问题二:上面split新生产的目标索引 tenbus_target,如何关联到现有业务保证正常业务可持续性呢?
问题三:为什么上面的索引只切了4个分片不接着继续切成8或者16或者20?
问题四: 用户前端程序代码改造成本大,想接入原有索引继续读写怎么办?
针对上面的问题, 一般情况下,我们肯定会建议用户:把集群模板分片策略改一下,改成20或者30,然后重新生成一个索引,让新数据写入到一个新的索引。或者让用户改变现有策略,基于时间的方式生产索引,每周或者每月生产一个索引。这样也是一个办法。然而用户并不认可这种方式。因为它需要改动客户前端代码,改造成本大。
或者我们可以再用Split API再切,切成20个分片,然后接着让用户继续往里边读写。这样暂时是可以,但是迟早有一天这20个分片又会因为无尽的写入导致超大分片的产生。集群最终还是有问题。所以,这里没有再接着切。切分4个分片已经有很大的改善。
其次:上面提到的4个问题也是客户所最关心的4个需求,那么如何高效解决用户的问题、满足客户的需求,又能得到用户的认可呢?
方法论 使用 ES ILM+Rollover+Alias的方式给用户解决这一系列的问题
我们知道,从ES6.6版本开始,ES集群免费开放ILM功能。同时结合Rollover API,我们可以针对非时间序列的索引进行滚动操作,大概流程图如下:
这里,我大致操作步骤如下:
1,给用户指定2个ILM,每个ILM针对不同的业务索引模式,并进行测试匹配。
2,Rollover 设定,设置索引600G自动滚动更新到下一个索引。每个索引20个分片,一个副本。
3,Alias 别名指定源索引名,并关联现有存量索引。一个写入,一个只能读取
注意:这里的别名tenbus需要跟ILM别名、模板别名、索引别名保持一样。因为这样才能最大限度的保证用户无感知。
当然,在对客户业务再次接入恢复前,还需要对源索引的mapping、settings进行匹配设置,然后再让用户业务重新接入。
因此, 经过上面的操作,我们就已经顺利的完成了用户集群后续超级大分片的动态设置、集群索引的长期规划管理问题。同时用户侧代码自动接入别名,无需做任何改动,别名同时关联存量索引,那么这样就彻底解决了用户上面提到的所有需求。大大提升了用户满意度。
以上就是整个操作的流程。大家好好思考一下。
由于本次客户数据操作过程遇到的问题比较多,这里就没有一一详述,但是大致的思路基本就是这样。具体还是要多参考实际生产工作环境而定。这里只提供一种方法跟思路,那就是动态扩展索引分片数量、以及超大分片或者超大索引的解决办法问题,希望大家多动手、多总结。
另外,在操作解决客户问题过程中,遇到了很多问题、盲区,最后都是请教各大神才得以顺利解决用户需求,这里再次向各位前辈致敬,感谢。
同时,这篇文章还有很多知识点比如段合并、别名、ILM、索引设置、reindex索引等其他知识未做过多铺垫,各位请自行官网补全并动手实践。
最重要的是:本文已生产实践,共享大家。时间仓促,不足之处,欢迎批评指正。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。