注: 部分概念介绍来源于网络

1、数据灾备。在整个集群无法正常工作时,可以及时从备份中恢复数据。
2、归档数据。随着数据的积累,比如日志类的数据,集群的存储压力会越来越大,不管是内存还是磁盘都要承担数据增多带来的压力,此时我们往往会选择只保留最近一段时间的数据,比如1个月,而将1个月之前的数据删除。如果你不想删除这些数据,以备后续有查看的需求,那么你就可以将这些数据以备份的形式归档。
3、迁移数据。当你需要将数据从一个集群迁移到另一个集群时,也可以用备份的方式来实现。
Elasticsearch 做备份有两种方式,一是将数据导出成文本文件,比如通过 elasticdump、esm 等工具将存储在 Elasticsearch 中的数据导出到文件中。二是以备份 elasticsearch data 目录中文件的形式来做快照,也就是 Elasticsearch 中 snapshot 接口实现的功能。第一种方式相对简单,在数据量小的时候比较实用,当应对大数据量场景效率就大打折扣。我们今天就着重讲解下第二种备份的方式,即 snapshot api 的使用。

(1)备份到哪里
在创建快照(snapshot)之前,首先需要创建快照仓库(repository),一个仓库里面可以有多个快照。
在 Elasticsearch 中通过 repository 定义备份存储类型和位置,存储类型有共享文件系统、AWS 的 S3存储、HDFS、微软 Azure的存储、Google Cloud 的存储等。
首先,你要在 elasticsearch.yml 的配置文件中注明可以用作备份路径 path.repo ,如下所示:
path.repo: ["D:\\lkh", "D:\\lkh\\ES\\elasticsearch-6.7.2\\first\\elasticsearch-6.7.2-1\\data\\my_backup"]
配置好后,重启elasticsearch,就可以使用 snapshot api 来创建一个 repository 了,如下我们创建一个名为 my_backup 的 repository。
PUT /_snapshot/my_backup
{
  "type": "fs",
  "settings": {
    "location": "D:\\lkh\\ES\\elasticsearch-6.7.2\\first\\elasticsearch-6.7.2-1\\data\\my_backup",
    "compress":"true" # 指定是否对快照文件进行压缩. 默认是 true.
  }
}
之后我们就可以在这个 repository 中来备份数据了。
PUT _snapshot/my_backup
{
    "type": "fs",
    "settings": {
        "location": "/mount/backups/my_backup",
        "max_snapshot_bytes_per_sec" : "50mb",    
        "max_restore_bytes_per_sec" : "50mb"    
    }
}
my_backup:仓库名称
type:指定仓库的类型是一个共享文件系统
localhost:指定已挂载的设备作为仓库地址
max_snapshot_bytes_per_sec:当快照数据进入仓库时,这个参数控制这个过程的限流情况。默认每秒 20mb
max_restore_bytes_per_sec:当从仓库恢复数据时,这个参数控制什么时候恢复过程会被限流以保障你的网络不会被占满。默认每秒 20mb。

(2)如何备份
有了 repostiroy 后,我们就可以做备份了,也叫快照,也就是记录当下数据的状态。如下所示我们创建一个名为 snapshot_1 的快照。
PUT /_snapshot/my_backup/snapshot_1?wait_for_completion=true
或者备份某一个索引
PUT _snapshot/my_backup/snapshot_1
{
    "indices": "elasticsearch-1",
    "ignore_unavailable": true,
    "include_global_state": true
}
wait_for_completion 为 true 是指该 api 在备份执行完毕后再返回结果,否则默认是异步执行的,我们这里为了立刻看到效果,所以设置了该参数,线上执行时不用设置该参数,让其在后台异步执行即可。
执行成功后会返回如下结果,用于说明备份的情况:
{
  "snapshot" : {
    "snapshot" : "snapshot_1",
    "uuid" : "Jf-7suADTUCudajaWaiqCg",
    "version_id" : 6070299,
    "version" : "6.7.2",
    "indices" : [
      "elasticsearch-1",
      ".kibana_task_manager",
      "elasticsearch-1-index",
      ".kibana_1"
    ],
    "include_global_state" : true,
    "state" : "SUCCESS",
    "start_time" : "2021-12-13T08:14:36.761Z",
    "start_time_in_millis" : 1639383276761,
    "end_time" : "2021-12-13T08:14:37.131Z",
    "end_time_in_millis" : 1639383277131,
    "duration_in_millis" : 370,
    "failures" : [ ],
    "shards" : {
      "total" : 8,
      "failed" : 0,
      "successful" : 8
    }
  }
}
返回结果的参数意义都是比较直观的,比如 indices 指明此次备份涉及到的索引名称,由于我们没有指定需要备份的索引,这里备份了所有索引;state 指明状态;duration_in_millis 指明备份任务执行时长等。
此时如果去 /mount/backups/my_backup 查看,会发现里面多了很多文件,这些文件其实都是基于 elasticsearch data 目录中的文件生成的压缩存储的备份文件。大家可以通过 du -sh . 命令看一下该目录的大小,方便后续做对比。

(3)何时备份
通过上面的步骤我们成功创建了一个备份,但随着数据的新增,我们需要对新增的数据也做备份,那么我们如何做呢?方法很简单,只要再创建一个快照 snapshot_2 就可以了。
PUT /_snapshot/my_backup/snapshot_2?wait_for_completion=true
当执行完毕后,你会发现 /mount/backups/my_backup 体积变大了。这说明新数据备份进来了。要说明的一点是,当你在同一个 repository 中做多次 snapshot 时,elasticsearch 会检查要备份的数据 segment 文件是否有变化,如果没有变化则不处理,否则只会把发生变化的 segment file 备份下来。这其实就实现了增量备份。

(4)如何恢复
同一个集群做恢复
通过调用如下 api 即可快速实现恢复功能。
POST /_snapshot/my_backup/snapshot_1/_restore?wait_for_completion=true
{
  "indices": "elasticsearch-1",
  "rename_replacement": "restored_elasticsearch-1"
}
POST _snapshot/my_backup/snapshot_1/_restore
{
  "indices": "elasticsearch-1",
  "ignore_unavailable": true,
  "include_global_state": false,              
  "rename_pattern": "elasticsearch-1",
  "rename_replacement": "restored_elasticsearch-1",
  "include_aliases": false
}
通过上面的 api,我们可以将 index_1 索引恢复到 restored_index_1 中。这个恢复过程完全是基于文件的,因此效率会比较高。
如果集群中已有快照的索引那就会报索引已存在的错误。
partial:false可选,默认:false,如果快照包含一个或多个索引没有所有主碎片可用,则整个还原操作将失败。 如果为true,则允许恢复具有不可用碎片的索引的部分快照。将只恢复快照中成功包含的碎片。所有丢失的碎片将重新创建为空 。
include_global_state:false 将还原快照中的所有数据流和索引,但不还原群集状态,如果ignore_unavailable:false时,一个索引缺失,快照请求会失败,true 时,在创建快照时会忽略不存在的索引
include_aliases 是否需要别名,true恢复,false不恢复别名
这个rename_pattern 与rename_replacement 支持正则表达式
使用正则表达式:
"rename_pattern": "test-0(.+)",
"rename_replacement": "restored_test_$1"
还原数据的时候,修改索引配置
POST /_snapshot/my_backup/snapshot_1/_restore
{
  "indices": "elasticsearch-1",
  "ignore_unavailable": true,
  "index_settings": {
    "index.number_of_replicas": 0
  },
  "ignore_index_settings": [
    "index.refresh_interval"
  ]
}
恢复数据时,把恢复索引的副本数改为0(不需要副本)。
恢复到另外一个集群
重复之前的步骤(当前集群开启备份,并重启服务,创建仓库,将快照目录拷贝到另外一台服务器,恢复快照)

(5)注意事项
注意版本问题,同一个大版本之间的备份与恢复是没有问题的,但你不能把一个高版本的备份在低版本恢复,而低版本备份在高版本恢复有一定要求
5.x 可以在 6.x 恢复
2.x 可以在 5.x 恢复
1.x 可以在 2.x 恢复
其他跨大版本的升级都是不可用的,比如1.x 的无法在 5.x 恢复。这里主要原因还是 Lucene 版本问题导致的
elasticsearch 的资深用户应该了解 force merge 功能,即可以强行将一个索引的 segment file 合并成指定数目,这里要注意的是如果你主动调用 force merge api,那么 snapshot 功能的增量备份功能就失效了,因为 api 调用完毕后,数据目录中的所有 segment file 都发生变化了。
另一个就是备份时机的问题,虽然 snapshot 不会占用太多的 cpu、磁盘和网络资源,但还是建议大家尽量在闲时做备份。

快照恢复前需要关掉索引
POST /my_index/_close
开启索引
POST /my_index/_open

(6)基本操作命令
恢复的指定索引:
GET restored_index_3/_recovery
查看集群里所有索引,可能包括跟你的恢复进程无关的其他分片移动:
GET /_recovery/
取消一个恢复,你需要删除正在恢复的索引。因为恢复进程其实就是分片恢复,发送一个 删除索引 API 修改集群状态,就可以停止恢复进程:
DELETE /restored_index_3
获取所有快照信息
GET _snapshot/my_backup/_all
获取指定快照信息
GET /_snapshot/my_backup/snapshot_2
删除快照
DELETE /_snapshot/my_backup/snapshot_2
删除多个
DELETE /_snapshot/my_backup/snapshot_2,snapshot_3,snapshot_4
通配符删除
DELETE /_snapshot/my_backup/snaps*
过期快照清理
POST /_snapshot/my_backup/_cleanup

(7)验证集群各个节点是否可以使用这个仓库:
POST /_snapshot/my_backup/_verify
//返回,说明我3个节点的集群都验证通过
{
  "nodes" : {
    "Ex5l_bvGRT2DazMFYO-M3Q" : {
      "name" : "master"
    },
    "CPiErxiBQOqvG0jINB42YQ" : {
      "name" : "node-002"
    },
    "-YG6nieCS7y1bvHN4HHHiA" : {
      "name" : "node-003"
    }
  }
}

(8)创建仓库参数设置:
location
仓库地址
compress
是否压缩,默认true,
chunk_size
是否将大文件分解成块,分解成块的单位,例子: 1GB, 10MB, 5KB, 500B,默认:null(不限制)
max_restore_bytes_per_sec
快照恢复的速度,默认:无限制
max_snapshot_bytes_per_sec
节点出入站的速率,默认:40mb/s
readonly
仓库快照是否时只读,默认:false

(9)获取指定快照状态
GET /_snapshot/my_backup/snapshot_2/_status
分片的状态有:
INITIALIZING
分片在检查集群状态看看自己是否可以被快照。这个一般是非常快的。
STARTED
数据正在被传输到仓库。
FINALIZING
数据传输完成;分片现在在发送快照元数据
DONE
快照完成!
FAILED
快照处理的时候碰到了错误,这个分片/索引/快照不可能完成了。检查你的日志获取更多信息。

(10)创建日期表达式的快照
也是需要用日期表达式而且也需要放在尖括号中且最终转为URI编码。
# 创建格式为:snapshot-2020-09-28 转为表达式:<snapshot-{now/d}>   转为URI: %3Csnapshot-%7Bnow%2Fd%7D%3E
# 创建以当前日期保存所有索引的快照
PUT /_snapshot/my_backup/%3Csnapshot-%7Bnow%2Fd%7D%3E

(11)获取通配符快照信息
获取模糊快照信息,多个用逗号隔开
GET /_snapshot/my_backup/snap*
GET /_snapshot/my_backup/snap*,test*
GET /_snapshot/my_backup/snapshot_2,snapshot_1

(12)查看repository信息
GET /_snapshot/my_backup?pretty
可以使用POST 请求,用来修改已经存在的repository
POST /_snapshot/my_backup
{
"type": "fs",
"settings": {
"location": "D:\\lkh",
"max_snapshot_bytes_per_sec" : "50mb",
"max_restore_bytes_per_sec" : "50mb"
}
}

(13)列出所有当前正在运行的快照以及显示他们的详细状态信息
GET /_snapshot/_status?pretty
(14)查看指定仓库正在运行的快照以及显示他们的详细状态信息
GET /_snapshot/my_backup/_status?pretty
(15)查看快照仓库列表
GET /_cat/repositories?v
id                   type
elasticsearch_backup   fs
test                   fs
(16)验证仓库是否所有节点都可用:
POST /_snapshot/my_backup/_verify

通过设置 include_global_state 为 false,可以阻止集群全局状态信息被保存为快照的一部分。默认情况下,如果如果一个快照中的一个或者多个索引没有所有主分片可用,整个快照创建会失败,该情况可以通过设置 partial 为 true 来改变。
快照名可以通过使用 date_math_expressions 来自动获得,和创建新索引时类似。注意特殊字符需要 URI 转码处理。
例如,在名字中使用当前日期,比如 snapshot-2018.05.11,来创建快照,可以使用如下命令完成:
# PUT /_snapshot/my_backup/<snapshot-{now/d}>
curl -X PUT "localhost:9200/_snapshot/my_backup/%3Csnapshot-%7Bnow%2Fd%7D%3E"

如果一些快照不可用,会导致获取命令执行失败。可以通过设置布尔参数 ignore_unavailable 来指定返回当前可用的所有快照。
从基于云存储的仓库中获取所有的快照,在消耗和性能方面看代价都比较高。如果只是获取快照的 names/uuids 和每个快照的索引列表,可以设置可选的布尔参数 verbose 为 true,这样再执行快照的获取,性能表现更好,消耗更划算。注意,设置 verbose 为 false,会忽略关于快照的所有其他信息,例如状态信息、快照分片的数量等,verbose 参数的默认值为 true。
当前正在运行的快照可以使用如下命令获取:
curl -X GET "localhost:9200/_snapshot/my_backup/_current"

默认情况下,快照中的所有索引将被恢复,集群状态不被恢复。可以通过在恢复请求中使用 indices 和 include_global_state 选项来指定要恢复的索引和允许恢复集群全局状态。索引列表支持多索引语法。rename_pattern 和 rename_replacement 选项在恢复时通过正则表达式来重命名索引。设置 include_aliases 为 false 可以防止与索引关联的别名被一起恢复。

恢复操作可以在正常运行的集群上执行。已存在的索引只能在关闭状态下才能恢复,并且要跟快照中索引拥有相同数目的分片。还原操作自动打开关闭状态的索引,如果被还原索引在集群不存在,将创建新索引。如果集群状态通过 include_global_state (默认是 false)选项被还原,在集群中不存在的模板会被新增,已存在的同名模板会被快照中的模板替换。持久化设置会被添加到现有的持久化设置中。

默认情况下,如果参与恢复操作的一个或者多个索引没有全部可用分片的快照,整个恢复操作将会失败。比如部分分片快照备份操作失败,上面的情况就会发生。这种情况依然可以通过设置 partial 为 true 来实现快照的恢复。注意在这种情况下,只有成功完成快照备份的分片才会被还原,而所有丢失的 其它分片将被创建成空分片。

如果原来集群中的索引使用了分片分配过滤器(shard allocation filtering)来分配索引到特定的节点,那么相同的规则将在新集群中被执行。所以,如果新集群不包含具有可以使被还原索引分配到自身的的属性的节点,索引将不会被成功恢复,除非在恢复时更改索引的分配配置。

恢复操作还会检查恢复持久化设置是否与当前集群兼容,以避免意外恢复不兼容的设置,例如 discovery.zen.minimum_master_nodes,因此在添加所必需数目的备选主节点之前,禁用较小的集群。如果需要恢复具有不兼容持久化设置的快照,则请尝试在没有全局集群状态的情况下执行。

还原过程是基于 Elasticsearch 标准恢复机制。因此标准的恢复监控服务可以用来监控还原的状态。当集群执行还原操作时通常会进入 red 状态。这是因为还原操作是从恢复被还原索引的主分片开始的,在此期间主分片状态变为不可用,表现为集群状态为 red。一旦主分片恢复完成,ElasticSearch 开始创建所需数目的副本的标准复制过程,这时集群切换到 yellow 状态。一旦完成所有必需副本的创建,集群变切换到 green 状态。

集群健康状态只提供了还原过程的一个比较粗略的一个状态。还可以通过使用 indices recovery 和 cat recovery 接口获取更详细的恢复过程的状态信息。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐