查看原文
其他

ES下零停机修改mapping数据迁移解决方案

运维菜鸟 运维研习社 2022-11-05


ES是一个基于RESTful web接口并且构建在Apache Lucene之上的开源分布式搜索引擎,同时ES还是一个分布式文档数据库,其中每个字段均可被索引,而且每个字段的数据均可被搜索,能够横向扩展至数以百计的服务器存储以及处理PB级的数据,可以在极短的时间内存储、搜索和分析大量的数据。通常作为具有复杂搜索场景情况下的核心存储


ES就是为高可用和可扩展而生的


一方面可以通过升级硬件来完成系统扩展,称为垂直或向上扩展(Vertical Scale/Scaling Up)


另一方面,增加更多的服务器来完成系统扩展,称为水平扩展或者向外扩展(Horizontal Scale/Scaling Out)


尽管ES能够利用更强劲的硬件,但是垂直扩展毕竟还是有它的极限。真正的可扩展性来自于水平扩展,通过向集群中添加更多的节点来分担负载,增加可靠性。ES天生就是分布式的,它知道如何管理多个节点来完成扩展和实现高可用性。意味应用不需要做任何的改动


基于以上原因,es应用越来越广,今天介绍下怎么做es数据迁移,迁移优化及利用索引别名不停机切换索引


什么时候需要es数据迁移?

1、当你的数据量过大,而你的索引最初创建的分片数量不足,导致数据入库较慢的情况,此时需要扩大分片的数量

2、当数据的mapping需要修改,但是大量的数据已经导入到索引中了,重新导入数据到新的索引太耗时;但是在ES中,一个字段的mapping在定义并且导入数据之后是不能再修改的

以上场景的时候,我们只能重建索引,重新导入数据,如果是从其他数据源写入es的,那你需要重新跑你的脚本,如果是直接写入es的,那你是不是可能需要导出文档,再导入

不需要,es从2.3版本开始,就引入了 {ref}/docs-reindex.html[Reindex API],它能够对文档进行重建索引,而不需要引入插件或第三方工具

ES提供了_reindex这个API。相对于我们重新导入数据肯定会快不少,实测速度大概是bulk导入数据的5-10倍,具体要看系统性能


数据迁移怎么做?

查看源索引详细信息

新建目标索引(新索引)

查看新建的新索引

为新索引创建新的mapping

新索引创建完成后,开始从旧索引通过reindex进行数据迁移

通过post _reindex,指定源索引,目标索引

如果你是通过kibana的tools执行的,开始执行后,如果数据量大,肯定会在kibana返回504超时,不用管,后台迁移还在执行,这个504是因为kibana的超时时间到了,返回的,不影响,通过_cat/indices/index?v查看索引数据统计就可以


有时候会涉及到数据合并,那么可以设置version_type  "version_type": "internal"或者不设置,则Elasticsearch强制性的将文档转储到目标中,覆盖具有相同类型和ID的任何内容:


有朋友会说,es的快照比reindex要快很多,确实,下次我们聊es的快照功能,但是快照无法实现mapping的修改,以及分片的修改,它只能作为数据备份恢复,既然说到reindex慢,那有没有办法优化?


reindex底层是scroll实现,scroll是什么呢?

scroll 可以理解为关系型数据库里的 cursor,因此,scroll 并不适合用来做实时搜索,而更适用于后台批处理任务,比如群发。

scroll 可以分为初始化和遍历两步,初始化时将所有符合搜索条件的搜索结果缓存起来,可以想象成快照,在遍历时,从这个快照里取数据,也就是说,在初始化后对索引插入、删除、更新数据都不会影响遍历结果。

from + size 和 scroll 都需要执行多次 fetch 阶段,但是相比于 from + size 方式,scroll 只做一次 query 阶段,一次将所有满足条件的结果都取出来,缓存到内存中,然后每次请求都是先在内存的快照中找到需要的 docid,然后去 shards 中获取数据。也就是说,from + size 会 query 多次,分页越深 query 的条数越多;而 scroll 一次会将全量数据取出,分页的深度对其没有影响

scroll虽然比frm+size的方式提高了效率,但是还是要完全遍历,性能还是不高,这也是reindex默认情况下慢的最大原因

所以提出了Sliced scroll的方式,也就是并行的scroll,通过传递slice参数,达到分块独立获取数据的目的

reindex支持sliced scroll以并行重建索引,举例:

slices的分片方式分两种,一种是手动分片,一种是自动分片,上图的方式是自动分片,手动分片见官方文档

slices大小设置注意事项:

1)slices大小的设置可以手动指定,或者设置slices设置为auto,auto的含义是:针对单索引,slices大小=分片数;针对多索引,slices=分片的最小值。
2)当slices的数量等于索引中的分片数量时,查询性能最高效。slices大小大于分片数,非但不会提升效率,反而会增加开销。
3)如果这个slices数字很大(例如500),建议选择一个较低的数字,因为过大的slices 会影响性能。

除了scroll并行的方式提升reindex的性能外,还有一个很重要的参数可以优化,那就是reindex批量操作的大小

默认情况下reindex使用1000进行批量操作,可以在source中通过size参数进行调整

批量大小值不是随便填写,具体如何做?

批量大小取决于数据、分析和集群配置,但一个好的起点是每批处理5-15 MB。

注意,这是物理大小。文档数量不是度量批量大小的好指标。例如,如果每批索引1000个文档:

1)每个1kb的1000个文档是1mb。

2)每个100kb的1000个文档是100 MB。

这些是完全不同的体积大小。

2、逐步递增文档容量大小的方式调优。

1)从大约5-15 MB的大容量开始,慢慢增加,直到你看不到性能的提升。然后开始增加批量写入的并发性(多线程等等)。

2)使用kibana、cerebro或iostat、top和ps等工具监视节点,以查看资源何时开始出现瓶颈。如果您开始接收EsRejectedExecutionException,您的集群就不能再跟上了:至少有一个资源达到了容量。

除了以上两种方式,还有两种方式,分别是禁用ES副本和增加refresh间隔

我们知道,ES在数据写入的时候,会写入多个副本,在进行大批量数据导入的时候,这个会严重影响写入速度,所以我们可以先关闭ES副本,导入后,再开启副本操作

对于refresh间隔时间,由于我们是做导入操作,所以不需要急于索引刷新操作,可以将索引的refresh_interval禁用,完成后开启

综合以上调优,reindex的速度能提升10倍以上。

解决了迁移的问题,那么迁移完后,正常我们可以修改调用索引,改为使用新索引,进行一个切换。有些时候,我们不想进行停机切换索引,怎么操作呢?


索引别名 _alias

在前面提到的,重建索引的问题是必须更新应用中的索引名称。索引别名就是用来解决这个问题的!

索引 别名 就像一个快捷方式或软连接,可以指向一个或多个索引,也可以给任何一个需要索引名的API来使用。别名 带给我们极大的灵活性,允许我们做下面这些:

  • 在运行的集群中可以无缝的从一个索引切换到另一个索引

  • 给多个索引分组 (例如, last_three_months)

  • 给索引的一个子集创建 视图

怎样使用别名在零停机下从旧索引切换到新索引。

有两种方式管理别名: _alias 用于单个操作, _aliases 用于执行多个原子级操作。

假设你的应用有一个叫 my_index 的索引。事实上, my_index 是一个指向当前真实索引的别名。真实索引包含一个版本号:my_index_v1 , my_index_v2 等等。

首先,创建索引 my_index_v1 ,然后将别名 my_index 指向它:

创建索引 my_index_v1 。

PUT /my_index_v1 

设置别名 my_index 指向 my_index_v1 

PUT /my_index_v1/_alias/my_index

你可以检测这个别名指向哪一个索引:

GET /*/_alias/my_index

或哪些别名指向这个索引:

GET /my_index_v1/_alias/*

两者都会返回下面的结果:

{    

    "my_index_v1" : { 

                "aliases" : { 

                            "my_index" : { }

            }

      }

}

一个别名可以指向多个索引,所以我们在添加别名到新索引的同时必须从旧的索引中删除它。这个操作需要原子化,这意味着我们需要使用 _aliases 操作:

POST /_aliases

 {    

        "actions": [ 

                { "remove": { "index": "my_index_v1", "alias": "my_index" }},

                { "add":    { "index": "my_index_v2", "alias": "my_index" }}

    ]

 }

你的应用已经在零停机的情况下从旧索引迁移到新索引了。

持续更新,欢迎扫码关注,敬请期待!




扫描二维码关注我们吧



温馨提示

如果你喜欢本文,请分享到朋友圈,想要获得更多信息,请关注我。



您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存