草庐IT

Elasticsearch ES数据迁移方法及注意事项

普通网友 2023-12-14 原文

Elastic数据迁移方法及注意事项

需求

ES集群Cluster_A里的数据(某个索引或某几个索引),需要迁移到另外一个ES集群Cluster_B中。

环境

Linux:Centos7 / Centos6.5/ Centos6.4
Elastic:5.2.0

总结的方法

  1. 查询并导出数据

  2. 拷贝ES物理目录/文件

  3. ES快照数据备份和恢复

迁移方法

分别进行以上方法的详细介绍:

查询并导出数据

理论

通过ES提供的查询API,写各种程序,把数据导出csv,或者把数据查询出来,直接入库到新的ES集群中。

实践

#coding=utf-8
 
import os
import sys
import pyes
 
 
index_list = [
    ["index_A", "type_A"],
    ["index_B", "type_B"],
    ["index_C", "type_C"],
]
 
 
ES_URL = "http://192.168.1.1:9200/"
NEW_ES_URL = "http://192.168.2.1:8200/"
 
def main():
    for _index, _type in index_list:
        conn = pyes.es.ES(ES_URL)
        search = pyes.query.MatchAllQuery().search(bulk_read=10000)
        hits = conn.search(search, _index, _type, scan=True, scroll="30m", model=lambda _,hit: hit)
         
        conn2 = pyes.es.ES(NEW_ES_URL)
        count = 0 
        for hit in hits:
            conn2.index(hit['_source'], _index, _type, hit['_id'], bulk=True)
            count += 1
            if count % 10000 == 0:
                print count
                conn2.flush()
        conn2.flush()
        conn2 = None
 
        conn = None
 
 
if __name__ == '__main__':
    main()

注意事项

  1. 需要安装python的pyes模块,注意pyes的版本,此处的版本为:pyes.0.20.1

  2. 用了查询ES的scroll方式,也有一种直接通过ES的DSL查询语句用分页from和size查询,但是ES的分页查询到了千万级别之后,from就会慢的出奇,甚至报错,不信的同学去尝试吧,等着功亏一篑….

  3. 客户现场的数据级别是物理存储大概在5T(一个副本),条数大概1百亿。现场使用该方法亲测之后,未解决ES迁移的问题。pyes在约到后面查询越慢,最后ES报错……

总结

  1. 百万、千万级别条数的数据,可以尝试该方法。

拷贝ES物理目录/文件

理论

ES的文件存在磁盘中,把物理文件一模一样拷贝一份到新的集群环境中,达到数据迁移的效果。

实践

1. 找到ES的存储目录,一般可以到elasticsearch.yml中找到path.data的配置
 
2. 集群下一般会有多个节点,所以ES的存储目录也就有多个
 
 
3. 一般ES的存储目录下,会存储一个集群名字一样的文件夹,需要拷贝的就是这个文件夹.
 
 
4. 环境如下:
旧集群:
集群名字:Cluster_A
分片数:6
机器A:一个节点 192.168.1.1
node0  数据存储目录:/opt/data1,/opt/data2
机器B:三个节点 192.168.1.2
node1  数据存储目录:/opt/data1,/opt/data2
node2  数据存储目录:/opt/data3,/opt/data4
node3  数据存储目录:/opt/data5,/opt/data6
 
新的集群:
集群名字:Cluster_A
分片数:6
机器A:一个节点 192.168.2.1
node0  数据存储目录:/opt/data1,/opt/data2
机器B:三个节点 192.168.2.2
node1  数据存储目录:/opt/data1,/opt/data2
node2  数据存储目录:/opt/data3,/opt/data4
node3  数据存储目录:/opt/data5,/opt/data6
 
 
5. 迁移代码如下:
新集群机器A:192.168.2.1如下操作

scp –r root@192.168.1.1:/opt/data1/Cluster_A /opt/data1/
scp –r root@192.168.1.1:/opt/data2/Cluster_A /opt/data2/

 
新集群机器B:192.168.2.2如下操作

scp –r root@192.168.1.2:/opt/data1/Cluster_A /opt/data1/
scp –r root@192.168.1.2:/opt/data2/Cluster_A /opt/data2/
scp –r root@192.168.1.2:/opt/data3/Cluster_A /opt/data3/
scp –r root@192.168.1.2:/opt/data4/Cluster_A /opt/data4/
scp –r root@192.168.1.2:/opt/data5/Cluster_A /opt/data5/
scp –r root@192.168.1.2:/opt/data6/Cluster_A /opt/data6/

ES快照数据备份和恢复

理论

使用ES官网提供的快照备份方法,将旧集群ES的索引进行备份,拷贝备份出来的所有文件,在新的集群中进行恢复。

官网写的非常简单:先创建仓库(repository),再往仓库里添加一个快照(snapshot),查看备份状态,That’s all。但是实践需要麻烦很多了。

实践

1. 旧的集群备份出来的东西,需要拷贝到新集群机器上。解决两个问题:一是旧集群没有足够的空间存储这些东西;二是反正备份出来都需要拷贝到新的集群中。此处想到一个方法,将新集群机器的目录远程Mount到旧集群机器上。
 
 
2. 挂载目录,2.1)和2.2)可以任选一种方式
 
 
3. 使用sshfs进行挂载:

// 在每台机器上安装sshfs
yum install fuse sshfs
 
// 每台机器上创建Mount共享目录
mkdir /opt/backup_es
 
// 旧集群的每台机器上挂载共享目录(分别挂载了新机器的/opt/data07目录到/opt/backup_es)
sshfs root@192.168.2.1:/opt/data07 /opt/backup_es -o allow_other
sshfs root@192.168.2.2:/opt/data07 /opt/backup_es -o allow_other
 
// 测试运行ES的用户是否有对共享目录的写权限
sudo -u elastic touch /opt/backup_es
 
// 在旧机器上将共享目录的权限付给ES的运行用户
chown elastic:elastic -R /opt/backup_es

 
2. 使用Mount nfs进行挂载:

// 在新集群的机器上(192.168.2.1, 192.168.2.2)添加共享的文件夹和客户端可以访问的IP地址
vi /etc/exports
/opt/data07 192.168.1.1(rw,no_root_squash)
/opt/data07 192.168.1.2(rw,no_root_squash)
 
// 查看共享文件夹和
exportfs -rv
 
// 重启启动新集群机器的NFS服务
services nfs restart
 
// 旧集群的每台机器上创建共享目录
mkdir /opt/backup_es
 
// 旧集群机器上进行Mount挂载
mount -t nfs 192.168.2.1:/opt/data07 /opt/backup_es
mount -t nfs 192.168.2.2:/opt/data07 /opt/backup_es
 
// 在旧机器上将共享目录的权限付给ES的运行用户
chown elastic:elastic -R /opt/backup_es

 
3. 创建ES仓库

// 创建ES仓库my_backup
http://192.168.1.1:9200/_plugin/head/的复合查询,通过PUT进行发送请求:
PUT _snapshot/my_backup 
{
    "type": "fs", 
    "settings": {
        "location": "/opt/backup_es",
        "compress": true
    }
}
 
// 查看仓库的状态
http://192.168.1.1:9200/_snapshot

 
4. 创建快照备份

// 针对具体的index创建快照备份(可以指定1个快照1个索引,或1个快照多个索引)
// 后面会依据快照的名称来进行恢复
http://192.168.1.1:9200/
PUT _snapshot/my_backup/snapshot_name_A
{
    "indices": "index_A, index_B"
}

成功之后,备份已经异步开始了。
 
 
5. 查看备份的状态

// 查看备份状态
http://192.168.1.1:9200/_snapshot/my_backup/snapshot_name_A/_status

细心的同学会看到ES会同时进行几个分片的备份,而且显示备份的数据情况。
有心的同学会看到,旧集群上共享的两个目录/opt/backup_es会均分备份出来的数据。这一点ES还是比较强大的,赞一个。应该还可以指定多个目录(作者没有试过,但是应该也是OK的,这样就可以挂载多个目录,解决磁盘空间不足的问题了)
 
 
6. 最后,就是等,直至所有的的备份都完成。
备份完成后,查看旧集群每台机器的/opt/backup_es目录,查看备份出的东东。
取消挂载
 
 
7. 在新集群中恢复

// 在新集群每台机器上将共享目录的权限付给ES的运行用户
chown elastic:elastic -R /opt/data07
 
// 停止ES,设置elasticsearch.yml的参数
    path.repo: /opt/data07
 
// 启动ES,在新集群创建仓库
http://192.168.2.1:9200/_plugin/head/的复合查询,通过PUT进行发送请求:
PUT _snapshot/my_backup 
{
    "type": "fs", 
    "settings": {
        "location": "/opt/data07",
        "compress": true
    }
}

 
8. 在新集群中恢复数据

// 使用RESTful API进行备份的恢复
http://192.168.1.1:9200/
POST
_snapshot/my_backup/snapshot_name_A/_restore
 
// 查看恢复的状态
http://192.168.1.1:9200/
GET
_snapshot/my_backup/snapshot_name_A/_status

 
9. 等,直至恢复完成。

注意事项

  1. 索引很大,需要有足够的空间存储备份出来的数据,挂载磁盘和设置path.repo来解决该问题。

  2. 在简历仓库的时候,会报错,找不到快照目录/opt/backup_es
    需要在elasticsearch.yml中设置path.repo: /opt/backup_es

  3. 挂载的磁盘需要赋权限,让ES的用户能读写。Sshfs的时候加上 -oallow_other;Mount的时候需要对目录进行赋权限chown

  4. Mount nfs的时候需要注意配置:vi /etc/exports

    /opt/data07192.168.1.1(rw,no_root_squash)
    /opt/data07192.168.1.2(rw,no_root_squash)

  5. 新集群中如果有索引和备份出来的索引有冲突(索引已存在),恢复不成功。
    解决:可以将旧的索引重命名,然后导入新集群中。导入成功后,将两个索引建立一个别名。

  6. 恢复期间,整个集群会变成红色(集群不可用),最好半夜的时候进行。

有关Elasticsearch ES数据迁移方法及注意事项的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  5. ruby-on-rails - Ruby on Rails 迁移,将表更改为 MyISAM - 2

    如何正确创建Rails迁移,以便将表更改为MySQL中的MyISAM?目前是InnoDB。运行原始执行语句会更改表,但它不会更新db/schema.rb,因此当在测试环境中重新创建表时,它会返回到InnoDB并且我的全文搜索失败。我如何着手更改/添加迁移,以便将现有表修改为MyISAM并更新schema.rb,以便我的数据库和相应的测试数据库得到相应更新? 最佳答案 我没有找到执行此操作的好方法。您可以像有人建议的那样更改您的schema.rb,然后运行:rakedb:schema:load,但是,这将覆盖您的数据。我的做法是(假设

  6. Ruby 方法() 方法 - 2

    我想了解Ruby方法methods()是如何工作的。我尝试使用“ruby方法”在Google上搜索,但这不是我需要的。我也看过ruby​​-doc.org,但我没有找到这种方法。你能详细解释一下它是如何工作的或者给我一个链接吗?更新我用methods()方法做了实验,得到了这样的结果:'labrat'代码classFirstdeffirst_instance_mymethodenddefself.first_class_mymethodendendclassSecond使用类#returnsavailablemethodslistforclassandancestorsputsSeco

  7. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  8. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  9. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  10. ruby - Highline 询问方法不会使用同一行 - 2

    设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案

随机推荐