简介
Elasticsearch 做备份有两种方式,一是将数据导出成文本文件,比如通过elasticdump、esm等工具将存储在 Elasticsearch 中的数据导出到文件中。二是以备份 elasticsearch data 目录中文件的形式来做快照,也就是 Elasticsearch 中snapshot接口实现的功能。第一种方式相对简单,在数据量小的时候比较实用,当应对大数据量场景效率就大打折扣。我们今天就着重讲解下第二种备份的方式,即snapshotapi 的使用。
Snapshot
Elasticsearch文档里对于snapshot有如下描述:
代码语言:javascript复制The index snapshot process is incremental. In the process of making the index snapshot Elasticsearch analyses the list of the index files that are already stored in the repository and copies only files that were created or changed since the last snapshot.
这里说snapshot
是增量备份的,每次snapshot
,Es会分析index文件,并且只备份增量部分。
- snapshot是增量备份,对未发生变化的index重复备份几乎没有资源消耗;
- 删除snapshot不会对其它snapshot产生影响;
- snapshot是增量备份,对未发生变化的index重复备份几乎没有资源消耗
- 删除某个snapshot不会对其它snapshot产生影响。
建仓
在创建快照(snapshot
)之前,首先需要创建快照仓库(repository
),一个仓库里面可以有多个快照。而创建快照仓库需要在elasticsearch.yml
配置仓库地址,配置之后,需要重启ES
服务。
在elasticsearch.yml 中添加:
path.repo: ["/Users/booker/Documents/opt/elasticsearch-cluster/es_repository"]
# 可以填多个仓库地址,后面添加快照时保存地址必须在下面配置地址之中
path.repo: ["/opt/elasticsearch-cluster/snapshot_repo", "/opt/elasticsearch-cluster/data_backups"]
创建一个名为es_bak_20210722
的快照仓库
POST _snapshot/es_bak_20210722
{
"type": "fs",
"settings": {
"location": "/Users/booker/Documents/opt/elasticsearch-cluster/es_repository",
"max_restore_bytes_per_sec": "50mb",
"max_snapshot_bytes_per_sec": "50mb",
"compress": true
}
}
响应:
{
"acknowledged" : true
}
这样就创建了一个仓库地址,之后就可以在这个仓库之后添加快照。
代码语言:javascript复制1.查看仓库:GET /_snapshot/_all
{
"es_bak_20210722" : {
"type" : "fs",
"settings" : {
"location" : "/Users/lihuan/Documents/opt/elasticsearch-cluster/es_repository",
"max_restore_bytes_per_sec" : "50mb",
"compress" : "true",
"max_snapshot_bytes_per_sec" : "50mb"
}
}
}
2.删除仓库:DELETE /_snapshot/es_bak_20210722
3.验证集群各个节点是否可以使用这个仓库:POST /_snapshot/es_bak_20210722/_verify
{
"nodes" : {
"0bCCNIOgT96vNrRVaTnXXQ" : {
"name" : "node-1"
}
}
}
4.查看某一个repository的具体setting:GET /_snapshot/repo-name
创建仓库还有其他的参数可以设置:
代码语言:javascript复制location:仓库地址
compress:是否压缩,默认true,
chunk_size:是否将大文件分解成块,分解成块的单位,例子: 1GB, 10MB, 5KB, 500B,默认:null(不限制)
max_restore_bytes_per_sec:快照恢复的速度,默认:无限制
max_snapshot_bytes_per_sec:节点出入站的速率,默认:40mb/s
readonly:仓库快照是否时只读,默认:false
以上介绍的是基于本地存储,可以配置仓库插件就可以存储在其他地方,如:
代码语言:javascript复制repository-s3 支持S3 仓库
repository-hdfs 支持HDFS 仓库
repository-azure 支持Azure 仓库
repository-gcs 支持 Google Cloud 仓库
备份
仓库配置好了,就可以开始备份了。snapshot是增量的,在创建snapshot的时候,Elasticsearch会分析已经存在snapshot,只备份自上一次快照以来创建或更改的文件, 那些没有更改的文件会直接引用到上一次的snapshot中。因此如果频繁备份,那么snapshot的文件会越来越小。
代码语言:javascript复制1.snapshot是某一个时间点的集群状态,因此开始创建快照之后所有对ES的修改都不会出现在这次snapshot中
2.创建snapshot的过程中,集群所有的工作都不会被block。但是同一时间,只能有一份snapshot在创建
- 删除快照
DELETE /_snapshot/es_bak_20210722/snapshot_kibana_sample_data_flights
使用以上指令删除snapshot的时候:
*会将repository中所有和这个快照相关的文件都删除
*会保留下来那些被其他还存在的快照使用的文件(因为快照是增量的)
1.删除多个快照:DELETE /_snapshot/my_backup/snapshot_2,snapshot_3,snapshot_4
2.通配符删除:DELETE /_snapshot/my_backup/snaps*
3.过期快照清理:POST /_snapshot/my_backup/_cleanup
- 保存集群下的所有索引快照
# 格式:/_snapshot/仓库名称/快照名称
PUT /_snapshot/my_backup/snapshot_1
这个指令返回关于snapshot的基本信息,包括开始和结束时间、创建快照的elasticsearch版本、包含的索引列表、快照的当前状态和快照期间发生的故障列表。
- 保存集群下的指定索引快照
指定索引,添加wait_for_completion
参数,等于true
时,将等待快照保存结束时才会返回结果。反之异步返回结果。
PUT /_snapshot/es_bak_20210722/snapshot_kibana_sample_data_flights?wait_for_completion=true
{
"indices": "kibana_sample_data_flights"
}
响应:
{
"snapshot" : {
"snapshot" : "snapshot_kibana_sample_data_flights",
"uuid" : "GmOEM-JeQ0KSC25yMXhjhw",
"version_id" : 7020199,
"version" : "7.2.1",
"indices" : [
"kibana_sample_data_flights"
],
"include_global_state" : true,
"state" : "SUCCESS",
"start_time" : "2021-07-22T07:15:07.028Z",
"start_time_in_millis" : 1626938107028,
"end_time" : "2021-07-22T07:15:07.758Z",
"end_time_in_millis" : 1626938107758,
"duration_in_millis" : 730,
"failures" : [ ],
"shards" : {
"total" : 1,
"failed" : 0,
"successful" : 1
}
}
}
# 格式:/_snapshot/仓库名称/快照名称
PUT /_snapshot/my_backup/snapshot_2?wait_for_completion=true
{
"indices": ".security-7,topic,indexName"
}
快照是增量的,有可能很多快照依赖于过去的段,在仓库下的文件要注意了不要手动删除。
- 获取所有快照信息
GET /_snapshot/es_bak_20210722/_all
响应:
{
"snapshots" : [
{
"snapshot" : "snapshot_kibana_sample_data_flights",
"uuid" : "GmOEM-JeQ0KSC25yMXhjhw",
"version_id" : 7020199,
"version" : "7.2.1",
"indices" : [
"kibana_sample_data_flights"
],
"include_global_state" : true,
"state" : "SUCCESS",
"start_time" : "2021-07-22T07:15:07.028Z",
"start_time_in_millis" : 1626938107028,
"end_time" : "2021-07-22T07:15:07.758Z",
"end_time_in_millis" : 1626938107758,
"duration_in_millis" : 730,
"failures" : [ ],
"shards" : {
"total" : 1,
"failed" : 0,
"successful" : 1
}
}
]
}
- 获取指定快照信息
获取snapshot_kibana_sample_data_flights
快照信息
GET /_snapshot/es_bak_20210722/snapshot_kibana_sample_data_flights
- 获取指定快照状态
除了上边加的wait_for_completion
参数,可以知道快照是否完成之外,可以使用如下:
GET /_snapshot/es_bak_20210722/snapshot_kibana_sample_data_flights/_status
响应:
{
"snapshots" : [
{
"snapshot" : "snapshot_kibana_sample_data_flights",
"repository" : "es_bak_20210722",
"uuid" : "GmOEM-JeQ0KSC25yMXhjhw",
"state" : "SUCCESS",
"include_global_state" : true,
"shards_stats" : {
"initializing" : 0,
"started" : 0,
"finalizing" : 0,
"done" : 1,
"failed" : 0,
"total" : 1
},
"stats" : {
"incremental" : {
"file_count" : 13,
"size_in_bytes" : 6739545
},
"total" : {
"file_count" : 13,
"size_in_bytes" : 6739545
},
"start_time_in_millis" : 1626938107185,
"time_in_millis" : 454
},
"indices" : {
"kibana_sample_data_flights" : {
"shards_stats" : {
"initializing" : 0,
"started" : 0,
"finalizing" : 0,
"done" : 1,
"failed" : 0,
"total" : 1
},
"stats" : {
"incremental" : {
"file_count" : 13,
"size_in_bytes" : 6739545
},
"total" : {
"file_count" : 13,
"size_in_bytes" : 6739545
},
"start_time_in_millis" : 1626938107185,
"time_in_millis" : 454
},
"shards" : {
"0" : {
"stage" : "DONE",
"stats" : {
"incremental" : {
"file_count" : 13,
"size_in_bytes" : 6739545
},
"total" : {
"file_count" : 13,
"size_in_bytes" : 6739545
},
"start_time_in_millis" : 1626938107185,
"time_in_millis" : 454
}
}
}
}
}
}
]
}
分片的状态有:
代码语言:javascript复制INITIALIZING:分片在检查集群状态看看自己是否可以被快照。这个一般是非常快的
STARTED:数据正在被传输到仓库
FINALIZING:数据传输完成;分片现在在发送快照元数据
DONE:快照完成
FAILED:快照处理的时候碰到了错误,这个分片/索引/快照不可能完成了。检查你的日志获取更多信息
- 创建日期表达式的快照
# 创建格式为:snapshot-2020-09-28 转为表达式:<snapshot-{now/d}> 转为URI:
# 创建以当前日期保存所有索引的快照
PUT /_snapshot/my_backup/
- 获取通配符快照信息
获取模糊快照信息,多个用逗号隔开
代码语言:javascript复制GET /_snapshot/my_backup/snap*
GET /_snapshot/my_backup/snap*,test*
GET /_snapshot/my_backup/snapshot_2,snapshot_1
恢复
一旦你备份过了数据,恢复它就简单了:只要在你希望恢复回集群的快照ID后面加上_restore
即可:
POST /_snapshot/es_bak_20210722/snapshot_kibana_sample_data_flights/_restore
如上,就会恢复快照中的snapshot_kibana_sample_data_flights
索引与数据,如果集群中已有快照的索引那就会报索引已存在的错误。如果索引再快照之前有别名,那么恢复快照时,会一同恢复别名。
如果你想在不替换现有数据的前提下,恢复老数据来验证内容,或者做其他处理。可以从快照里恢复单个索引并提供一个替换的名称:
代码语言:javascript复制POST /_snapshot/es_bak_20210722/snapshot_kibana_sample_data_flights/_restore
{
"indices": "kibana_sample_data_flights",
"ignore_unavailable": true,
"include_global_state": false,
"rename_pattern": "kibana_sample_data_flights",
"rename_replacement": "restored_kibana_sample_data_flights",
"include_aliases": false
}
备注:kibana_sample_data_flights在恢复之前是有一个别名flights的,那么在恢复快照时,会排除别名恢复。
恢复后索引名:restored_kibana_sample_data_flights
恢复完成后,当前集群与快照同名的索引、模板会被覆盖。在集群中存在,但快照中不存在的索引、索引别名、模板不会被删除。因此恢复并非同步成与快照一致。
代码语言:javascript复制partial:false可选,默认:false,如果快照包含一个或多个索引没有所有主碎片可用,则整个还原操作将失败。 如果为true,则允许恢复具有不可用碎片的索引的部分快照。将只恢复快照中成功包含的碎片。所有丢失的碎片将重新创建为空。
include_global_state:false 将还原快照中的所有数据流和索引,但不还原群集状态。
ignore_unavailable:false,false表示当缺少kibana_sample_data_flights索引时报错
include_aliases 是否需要恢复别名,true恢复,false不恢复别名
rename_pattern 与rename_replacement 支持正则表达式也可以像上面直接写死。
使用正则表达式:
代码语言:javascript复制POST /_snapshot/my_backup/snapshot_1/_restore
{
"indices": "test-01",
"ignore_unavailable": true,
"include_global_state": false,
"rename_pattern": "test-0(. )",
"rename_replacement": "restored_test_$1",
"include_aliases": false
}
还原数据的时候,修改索引配置:
代码语言:javascript复制POST /_snapshot/my_backup/snapshot_1/_restore
{
"indices": "index_1",
"ignore_unavailable": true,
"index_settings": {
"index.number_of_replicas": 0
},
"ignore_index_settings": [
"index.refresh_interval":1s
]
}
https://blog.csdn.net/lingzhao8988/article/details/85424671