ElasticSearch基于snapshot和hdfs的备份和恢复

0 - 背景

任何一个存储数据的软件,都需要定期的备份数据。es replica提供了运行时的高可用保障机制,可以容忍少数节点的故障和部分数据的丢失,但是整体上却不会丢失任何数据,而且不会影响集群运行。但是replica没法进行灾难性的数据保护,比如说机房彻底停电,所有机器全部宕机,等等情况。对于这种灾难性的故障,我们就需要对集群中的数据进行备份了,集群中数据的完整备份。

要备份集群数据,就要使用snapshot api。这个api会将集群当前的状态和数据全部存储到一个外部的共享目录中去,比如NAS,或者hdfs。而且备份过程是非常智能的,第一次会备份全量的数据,但是接下来的snapshot就是备份两次snapshot之间的增量数据了。数据是增量进入es集群或者从es中删除的,那么每次做snapshot备份的时候,也会自动在snapshot备份中增量增加数据或者删除部分数据。因此这就意味着每次增量备份的速度都是非常快的。

如果要使用这个功能,我们需要有一个预先准备好的独立于es之外的共享目录,用来保存我们的snapshot备份数据。es支持多种不同的目录类型:shared filesystem,比如NAS;Amazon S3;hdfs;Azure Cloud。不过对于国内的情况而言,其实NAS应该很少用,一般来说,就用hdfs会比较多一些,跟hadoop这种离线大数据技术栈整合起来使用。

1 - 备份

1.1 - 安装hdfs插件

首先先要在es插件目录安装repository-hdfs的插件,必须在每个节点上都安装,然后重启整个集群。

./bin/elasticsearch-plugin install file:/opt/soft/repository-hdfs-6.8.0.zip

1.2 - 创建仓库

在hdfs node上,都加入hdfs-site.xml,禁止权限检查,如果要修改这个配置文件,停止整个hdfs集群,然后在node上,都修改hdfs-site.xml,加入下面的配置,禁止权限的检查:

<property>
  <name>dfs.permissions</name>
  <value>false</value>
</property>

hdfs snapshot/restore plugin是跟最新的hadoop 2.x整合起来使用的,目前是hadoop 2.7.1。所以如果我们使用的hadoop版本跟这个es hdfs plugin的版本不兼容,那么考虑在hdfs plugin的文件夹里,将hadoop相关jar包都替换成我们自己的hadoop版本对应的jar包。即使hadoop已经在es所在机器上也安装了,但是为了安全考虑,还是应该将hadoop jar包放在hdfs plugin的目录中。

安装好了hdfs plugin之后,就可以创建hdfs仓库了,用如下的命令即可:

PUT _snapshot/my_hdfs_repository
{
  "type": "hdfs",
  "settings": {
    "uri": "hdfs://hdfs01:9000",
    "path": "my_hdfs_repository",
    "max_snapshot_bytes_per_sec" : "50mb",
    "max_restore_bytes_per_sec" : "50mb"
  }
}

1.3 - 验证仓库

如果一个仓库被创建好之后,我们可以立即去验证一下这个仓库是否可以在所有节点上正常使用。verify参数都可以用来做这个事情,比如下面的命令。这个命令会返回一个node列表,证明那些node都验证过了这个仓库是ok的,可以使用的:

POST _snapshot/my_hdfs_repository/_verify

1.4 - 对索引进行snapshotting备份

对所有open的索引进行snapshotting备份

一个仓库可以包含多分snapshot,每个snapshot是一部分索引的备份数据,创建一份snapshot备份时,我们要指定要备份的索引。比如下面这行命令:PUT _snapshot/my_hdfs_repository/snapshot_1,这行命令就会将所有open的索引都放入一个叫做snapshot_1的备份,并且放入my_hdfs_repository仓库中。这个命令会立即返回,然后备份操作会被后台继续进行。如果我们不希望备份操作以后台方式运行,而是希望在前台发送请求时等待备份操作执行完成,那么可以加一个参数即可,比如下面这样:PUT _snapshot/my_hdfs_repository/snapshot_1?wait_for_completion=true

对指定的索引进行snapshotting备份

默认的备份是会备份所有的索引,但是有的时候,可能我们不希望备份所有的索引,有些可能是不重要的数据,而且量很大,没有必要占用我们的hdfs磁盘资源,那么可以指定备份少数重要的数据即可。此时可以使用下面的命令去备份指定的索引:

PUT _snapshot/my_hdfs_repository/snapshot_1
{
    "indices": "index_1,index_2",
    "ignore_unavailable": true,
    "include_global_state": false,
    "partial": true
}

ignore_unavailable如果设置为true的话,那么那些不存在的index就会被忽略掉,不会进行备份过程中。默认情况下,这个参数是不设置的,那么此时如果某个index丢失了,会导致备份过程失败。设置include_global_state为false,可以阻止cluster的全局state也作为snapshot的一部分被备份。默认情况下,如果某个索引的部分primary shard不可用,那么会导致备份过程失败,那么此时可以将partial设置为true

而且snapshotting的过程是增量进行的,每次执行snapshotting的时候,es会分析已经存在于仓库中的snapshot对应的index file,然后仅仅备份那些自从上次snapshot之后新创建的或者有过修改的index files。这就允许多个snapshot在仓库中可以用一种紧凑的模式来存储。而且snapshotting过程是不会阻塞所有的es读写操作的,然而,在snapshotting开始之后,写入index中的数据,是不会反应到这次snapshot中的。每次snapshot除了创建一份index的副本之外,还可以保存全局的cluster元数据,里面包含了全局的cluster settingstemplate

每次只能执行一次snapshot操作,如果某个shard正在被snapshot备份,那么这个shard此时就不能被移动到其他node上去,这会影响shard rebalance的操作。只有在snapshot结束之后,这个shard才能够被移动到其他的node上去。

1.5 - 查看snapshot备份列表

一旦我们在仓库中备份了一些snapshot之后,就可以查看这些snapshot相关的详细信息了,使用这行命令就可以查看指定的snapshot的详细信息:GET _snapshot/my_hdfs_repository/snapshot_2,结果大致如下所示。当然也可以查看所有的snapshot列表,GET _snapshot/my_hdfs_repository/_all

GET _snapshot/my_hdfs_repository/snapshot_2?pretty
{
  "snapshots" : [
    {
      "snapshot" : "snapshot_0",
      "uuid" : "ulzZ-zosRAWHsBVmVJ5SJA",
      "version_id" : 6080099,
      "version" : "6.8.0",
      "indices" : [
        "mysia"
      ],
      "include_global_state" : false,
      "state" : "SUCCESS",
      "start_time" : "2020-06-09T01:59:26.923Z",
      "start_time_in_millis" : 1591667966923,
      "end_time" : "2020-06-09T01:59:28.289Z",
      "end_time_in_millis" : 1591667968289,
      "duration_in_millis" : 1366,
      "failures" : [ ],
      "shards" : {
        "total" : 5,
        "failed" : 0,
        "successful" : 5
      }
    }
  ]
}

1.6 - 删除snapshot备份

如果要删除过于陈旧的snapshot备份快照,那么使用下面这行命令即可:DELETE _snapshot/my_hdfs_repository/snapshot_2记住,一定要用api去删除snapshot,不要自己手动跑到hdfs里删除这个数据。因为snapshot是增量的,有可能很多snapshot依赖于底层的某一个公共的旧的snapshot segment。但是delete api是理解数据如何增量存储和互相依赖的,所以可以正确的删除那些不用的数据。如果我们自己手工进行hdfs文件删除,可能导致我们的backup数据破损掉,就无法使用了。

DELETE _snapshot/my_hdfs_repository/snapshot_2

1.7 - 监控snapshotting的进度

使用wait_for_completion可以在前台等待备份完成,但是实际上也没什么必要,因为可能要备份的数据量特别大,难道还等待1个小时??看着是不太现实的,所以一般还是在后台运行备份过程,然后使用另外一个监控api来查看备份的进度,首先可以获取一个snapshot IDGET _snapshot/my_hdfs_repository/snapshot_3。如果这个snapshot还在备份过程中,此时我们就可以看到一些信息,比如什么时候开始备份的,已经运行了多长时间,等等。然而,这个api用了跟snapshot一样的线程池去执行,如果我们在备份非常大的shard,进度的更新可能会非常之慢。一个更好的选择是用_status APIGET _snapshot/my_hdfs_repository/snapshot_3/_status,这个api立即返回最详细的数据。这里我们可以看到总共有几个shard在备份,已经完成了几个,还剩下几个,包括每个索引的shard的备份进度:

GET _snapshot/my_hdfs_repository/snapshot_2/_status

1.8 - 取消snapshotting备份过程

如果我们想要取消一个正在执行的snapshotting备份过程,比如我们发现备份时间过于长,希望先取消然后在晚上再运行,或者是因为不小心误操作发起了一次备份操作,这个时候就可以运行下面这条命令:DELETE _snapshot/my_hdfs_repository/snapshot_2。也就是立即删除这个snapshot,这个命令会去取消snapshot的过程,同时将备份了一半的仓库中的数据给删除掉。

DELETE _snapshot/my_hdfs_repository/snapshot_2

3 - 还原

一般来说,备份工作是在一个shell脚本里,用crontab做一个定时去做增量备份。那么在es集群故障,导致数据丢失的时候,就可以用_restore api进行数据恢复了。比如下面这行命令:

POST _snapshot/my_hdfs_repository/snapshot_2/_restore

文件中所有索引都全恢复。在某些场景下,我们想恢复一些数据但是不要覆盖现有数据,用下面的命令即可恢复数据,并且进行重命名操作:

POST /_snapshot/my_hdfs_repository/snapshot_2/_restore
{
    "indices": "index_1", 
    "ignore_unavailable": true,
    "include_global_state": true,
    "rename_pattern": "index_(.+)", 
    "rename_replacement": "restored_index_$1" 
}

这个restore过程也是在后台运行的,如果要在前台等待它运行完,那么可以加上:

POST _snapshot/my_hdfs_repository/snapshot_2/_restore?wait_for_completion=true

等待它备份完成了以后,才会去执行下一条命令。

restore过程只能针对已经close掉的index来执行,而且这个index的shard还必须跟snapshot中的indexshard数量是一致的。restore操作会自动在恢复好一个index之后open这个index,或者如果这些index不存在,那么就会自动创建这些index。如果通过include_global_state存储了集群的state,还会同时恢复一些template

此外,还可以在恢复的过程中,修改index的一些设置,比如下面的命令:

POST /_snapshot/my_hdfs_repository/snapshot_2/_restore
{
  "indices": "index_1",
  "index_settings": {
    "index.number_of_replicas": 0
  },
  "ignore_index_settings": [
    "index.refresh_interval"
  ]
}

监控restore的进度
从一个仓库中恢复数据,其实内部机制跟从其他的node上恢复一个shard是一样的。如果要监控这个恢复的过程,可以用recovery api,比如:

GET restored_index_3/_recovery

如果要看所有索引的恢复进度:GET /_recovery/。可以看到恢复进度的大致的百分比。

取消恢复过程
如果要取消一个恢复过程,那么需要删除已经被恢复到es中的数据。因为一个恢复过程就只是一个shard恢复,发送一个delete操作删除那个索引即可,如果那个索引正在被恢复,那么这个delete命令就会停止恢复过程,然后删除已经恢复的所有数据。

DELETE restored_index_3

增量还原
基于snapshot的备份,再做完第一次全量后,其实后续的备份都是基于上一次备份的增量备份。而Elasticsearch在做还原时,不像MySQLSQL Server那样,需要先还原全量,在恢复增量。

假设,有3个Elasticsearch的备份:

  • snapshop_202008041000
  • snapshop_202008041010
  • snapshop_202008041020

如果要还原到最新的备份,也就是snapshop_202008041020这个备份,只需要:

POST _snapshot/ES/snapshop_202008041020/_restore

还原最新备份的同时,Elasticsearch会根据hdfs仓库里面备份的关联关系,将之前的备份也一起恢复。

如果不巧的是,不确定还原到哪个备份,那么就需要依次还原:

还原全量备份:
POST _snapshot/ES/snapshop_202008041000/_restore

此时假设数据还不对,需要还原下一个增量,需要先关闭索引,再还原增量
POST test_shapshot/_close
POST _snapshot/ES/snapshop_202008041010/_restore

如果数据仍然不对,后续的增量还原,重复上面的步骤

奇怪的是,官网上的snapshot部分,没有写增量还原部分。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,898评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,401评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,058评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,539评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,382评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,319评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,706评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,370评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,664评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,715评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,476评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,326评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,730评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,003评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,275评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,683评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,877评论 2 335

推荐阅读更多精彩内容