Elasticsearch的Snapshot and Restore(快照备份与恢复)

简介: Elasticsearch提供的Snapshot api就是从正在运行的集群中获取备份用的,可以根据情况选择整个集群,也可以指定index和data stream。Elasticsearch是以增量的方式获取Snapshot,节约了时间和空间,小开销意味着可以适当增加备份的频率。每一个Snapshot在逻辑上相互独立,所以删除某一个Snapshot不会影响到其他的Snapshot。

Snapshot and Restore(快照备份与恢复)

简介

  无论使用哪种存储数据的软件,定期备份数据都是很重要的。Elasticsearch 副本提供了高可靠性;它们让你可以容忍少量的节点丢失而不会中断服务。但是,副本并不提供对灾难性故障的保护。对这种情况,你需要的是对集群真正的备份——在某些东西确实出问题的时候有一个完整的拷贝。需要注意的是Elasticsearch并不支持直接拷贝集群data目录、备份服务器的方式来备份、升级群集,这样做会导致数据损坏、无法恢复数据。

  Elasticsearch提供的Snapshot api就是从正在运行的集群中获取备份用的,可以根据情况选择整个集群,也可以指定index和data stream。Elasticsearch是以增量的方式获取Snapshot,节约了时间和空间,小开销意味着可以适当增加备份的频率。每一个Snapshot在逻辑上相互独立,所以删除某一个Snapshot不会影响到其他的Snapshot。

  从Snapshot恢复集群数据可以指定index和data stream,当然也可以通过SLM来管理Snapshot的生命周期。

  备份恢复时的版本兼容性:当前版本支持当前版本及升高一个的版本进行恢复不支持跨版本直接恢复。当然如果你想跨版本恢复,可以尝试版本递增滚动升级来达到目的。反之则不可行,不能递减版本来恢复备份的数据。

Snapshot version 2.x 5.x 6.x 7.x 8.x
1.x → - - - -
2.x → - - -
5.x → - - -
6.x → - - -
7.x → - - -

配置Snapshot仓库

  在使用Snapshot备份前,必须要注册快照仓库。可以存储在本地或者远程仓库中,远程仓库支持Amazon S3, HDFS, Microsoft Azure, Google GCS等,参考仓库插件的类型。

1.创建仓库

  在创建仓库之前需要在所有Master和Data节点中增加仓库配置项(elasticsearch.yml),以下以共享存储的方式举例。单节点的情况下可以用本地物理存储路径,如果是多节点分布式,需要保证共享存储都进行了正确的mount挂载。

path:
  repo:
    - /apps/data/esbackup
    - /apps/data/stream-backup
    # Windows系统下
    - D:\\apps\\data\\esbackup

  等到滚动重启完所有的节点,就可以创建仓库了。

PUT /_snapshot/my_fs_backup
{
  "type": "fs",
  "settings": {
    # location为配置文件中paath.repo所配置的子路径,所以也可以写相对路径 "location": "My_fs_backup_location"
    "location": "/apps/data/esbackup/My_fs_backup_location",
    # 是否启用压缩,默认为true
    "compress": "true"
  }
}
# 成功后会返回
{
    "acknowledged": true
}

  创建完成后可以GET查询仓库。

GET /_snapshot
# 返回结果
{
    "my_fs_backup": {
        "type": "fs",
        "settings": {
            "compress": "true",
            "location": "My_fs_backup_location"
        }
    }
}

  通过verify验证节点仓库是否在所有节点已生效。

POST /_snapshot/my_fs_backup/_verify
# 返回结果
{
    "nodes": {
        "8Z7MmAUeToq6WGCxhVFk8A": {
            "name": "jt-hpzbook"
        },
        "yRahNXjuR2-w6w1ObVXQjg": {
            "name": "jt-hpzbook2"
        },
    }
}

  其他接口:

# 查看所有仓库
GET /_snapshot/_all
# 删除仓库
DELETE /_snapshot/my_fs_backup

2.可配置参数

  更多参数可以参考:Repository API

  • location: 仓库地址
  • compress: 是否启用压缩,默认为true
  • chunk_size: 是否将文件切块,并指定文件块大小,默认:null(不切分)
  • max_restore_bytes_per_sec: Snapshot从仓库恢复时的限速,默认:无限制
  • max_snapshot_bytes_per_sec: 节点创建Snapshot进入仓库时的限速,默认:40mb/s
  • readonly: Snapshot是否只读,默认:false

3.插件

  插件的扩展使得Snapshot可以选择更多的方式,无论是HDFS集群还是常见的云厂商的云端。

  • 官方插件:

    • S3 Repository: 亚马逊的S3仓库
    • Azure Repository: 微软Azure仓库
    • HDFS Repository: HDFS仓库
    • Google Cloud Storage Repository: 谷歌的GCS仓库
  • 社区插件:

    • Openstack Swift

Snapshot快照备份

1.创建Snapshot

  一个仓库可以包含多个Snapshot,一个Snapshot在集群中的名字是唯一的。Snapshot快照备份的内容仅包含截止快照开始时间之前的数据,快照之后的数据需要通过不断的增量Snapshot来捕获。通过PUT请求创建一个Snapshot,默认备份集群所有可读索引、流,如果需要部分备份则可以通过传参来指定。

# wait_for_completion参数表示是否要同步等Snapshot创建完成再返回,PUT请求如果传参为空则默认备份所有可读索引、流
PUT /_snapshot/my_fs_backup/snapshot_1?wait_for_completion=true
{
  "indices": "hundredsman,index_1,index_2",
  "ignore_unavailable": true,
  "include_global_state": false,
  "metadata": {
    "taken_by": "james",
    "taken_because": "Hundreds man fighting for book backup."
  }
}
# 返回结果
{
    "snapshot": {
        "snapshot": "snapshot_1",
        "uuid": "HQHFSpPoQ1aY4ykm2o-a0Q",
        "version_id": 7100099,
        "version": "7.10.0",
        "indices": [
            "index_1",
            "index_2",
            "hundredsman"
        ],
        "data_streams": [],
        "include_global_state": true,
        "state": "SUCCESS",
        "start_time": "2021-09-03T12:46:56.237Z",
        "start_time_in_millis": 1630673216237,
        "end_time": "2021-09-03T12:46:56.237Z",
        "end_time_in_millis": 1630673216237,
        "duration_in_millis": 0,
        "failures": [],
        "shards": {
            "total": 3,
            "failed": 0,
            "successful": 3
        }
    }
}

2.删除Snapshot

  删除Snapshot需要发送DELETE请求:

DELETE /_snapshot/my_fs_backup/snapshot_1
# 删除多个可以用逗号分隔或者通配符
DELETE /_snapshot/my_fs_backup/snapshot_2,snapshot_3
DELETE /_snapshot/my_fs_backup/snap*

  如果Snapshot正在创建过程中,Elasticsearch也会终止任务并删除所有Snapshot相关的数据。但要注意不能手动删除仓库里的备份数据,这样会有数据损坏的风险。

Restore恢复

  发送POST请求从Snapshot恢复数据:

# 不带参数的请求默认恢复所有Snapshot中的索引、流
POST /_snapshot/my_fs_backup/snapshot_1/_restore
# 如果需要恢复特定的索引、流,可以在POST参数中指定
POST /_snapshot/my_fs_backup/snapshot_1/_restore
{
  "indices": "index*",
  "ignore_unavailable": true,
  # include_global_state默认为true,是设置集群全局状态
  "include_global_state": false, 
  # 重命名索引匹配规则,如: index_1
  "rename_pattern": "index_(.+)",
  # 重命名索引为新的规则,如: re_index_1
  "rename_replacement": "re_index_$1",
  "include_aliases": false
}
# 正常返回结果
{
    "accepted": true
}
# 如果索引已经存在,会提示已经有同名索引存在,需要重命名。
{
    "error": {
        "root_cause": [
            {
                "type": "snapshot_restore_exception",
                "reason": "[my_fs_backup:snapshot_1/90A9o4hORUCv732HTQBfRQ] cannot restore index [index_1] because an open index with same name already exists in the cluster. Either close or delete the existing index or restore the index under a different name by providing a rename pattern and replacement name"
            }
        ]
    },
    "status": 500
}

  需要注意的是如果没有匹配到Stream的模板,Stream是不能滚动创建的。所以如果有快照中包含有Stream流数据,要记得提前创建模板。

监控进度

1.监控Snapshot状态

  通过GET请求监控当前Snapshot状态,需要注意的是,如果你的Snapshot和索引shard分片很多、仓库存储的延迟很大,那么_current请求可能会耗时很久。

# 查看当前Snapshot状态
GET /_snapshot/my_fs_backup/_current

# 指定Snapshot查看
GET /_snapshot/my_fs_backup/snapshot_1
GET /_snapshot/my_fs_backup/snapshot_*

# 查看所有仓库(如果建了多个仓库的话)
GET /_snapshot/_all
GET /_snapshot/my_fs_backup,my_hdfs_backup
GET /_snapshot/my*

# 指定查看某一个Snapshot的进度详情
GET /_snapshot/my_fs_backup/snapshot_1/_status
# 返回结果较大,以下仅展示部分结果。更多结果说明参考:https://www.elastic.co/guide/en/elasticsearch/reference/current/get-snapshot-status-api.html
{
    "snapshots": [
        {
            "snapshot": "snapshot_1",
            "repository": "my_fs_backup",
            "uuid": "HQHFSpPoQ1aY4ykm2o-a0Q",
            "state": "SUCCESS",
            "include_global_state": true,
            "shards_stats": {
                "initializing": 0,
                "started": 0,
                "finalizing": 0,
                "done": 3,
                "failed": 0,
                "total": 3
            },
            "stats": {
                "incremental": {
                    "file_count": 3,
                    "size_in_bytes": 624
                },
                "total": {
                    "file_count": 3,
                    "size_in_bytes": 624
                },
                "start_time_in_millis": 1630673216237,
                "time_in_millis": 0
            },
            "indices": {
                "index_1": {
                    "shards_stats": {
                        "initializing": 0,
                        "started": 0,
                        "finalizing": 0,
                        "done": 1,
                        "failed": 0,
                        "total": 1
                    },
                    "stats": {
                        "incremental": {
                            "file_count": 1,
                            "size_in_bytes": 208
                        },
                        "total": {
                            "file_count": 1,
                            "size_in_bytes": 208
                        },
                        "start_time_in_millis": 1630673216237,
                        "time_in_millis": 0
                    },
                    "shards": {
                        "0": {
                            # initializing:初始化检查集群状态是否可以创建快照
                            # started:数据正在被传输到仓库
                            # finalizing:数据传输完成,shard分片正在发送Snapshot元数据
                            # done:Snapshot创建完成
                            # failed:遇到错误失败的shard分片
                            "stage": "DONE",
                            "stats": {
                                "incremental": {
                                    "file_count": 1,
                                    "size_in_bytes": 208
                                },
                                "total": {
                                    "file_count": 1,
                                    "size_in_bytes": 208
                                },
                                "start_time_in_millis": 1630673216237,
                                "time_in_millis": 0
                            }
                        }
                    }
                    # 省略部分结果...
                }
            }
        }
    ]
}

2.监控Restore恢复状态

  当Restore恢复启动后,因为Restore在恢复索引的主分片,所以集群状态会变成yellow,主分片恢复完成后Elasticsearch开始根据副本设置的策略恢复副本数,所有操作完成后集群才会恢复到green状态。也可以先把索引的副本数修改为0,待主分片完成后再修改到目标副本数。Restor恢复状态可以通过监控集群或者指定索引的Recovery状态。

# 查看集群恢复状态,更多请参考集群恢复监控接口:https://www.elastic.co/guide/en/elasticsearch/reference/current/cat-recovery.html
GET /_cat/recovery/
# 查看索引的恢复状态,更多请参考索引恢复监控接口:https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-recovery.html
GET /index_1/_recovery
# 返回结果
{
    "restore_lakehouse": {
        "shards": [
            {
                "id": 1,
                "type": "SNAPSHOT",
                "stage": "INDEX",
                "primary": true,
                "start_time_in_millis": 1630673216237,
                "total_time_in_millis": 1513,
                "source": {
                    "repository": "my_fs_backup",
                    "snapshot": "snapshot_3",
                    "version": "7.10.0",
                    "index": "index_1",
                    "restoreUUID": "fLtPIdOORr-3E7AtEQ3nFw"
                },
                "target": {
                    "id": "8Z7MmAUeToq6WGCxhVFk8A",
                    "host": "127.0.0.1",
                    "transport_address": "127.0.0.1:9300",
                    "ip": "127.0.0.1",
                    "name": "jt-hpzbook"
                },
                "index": {
                    "size": {
                        "total_in_bytes": 25729623,
                        "reused_in_bytes": 0,
                        "recovered_in_bytes": 23397681,
                        "percent": "90.9%"
                    },
                    "files": {
                        "total": 50,
                        "reused": 0,
                        "recovered": 43,
                        "percent": "86.0%"
                    },
                    "total_time_in_millis": 1488,
                    "source_throttle_time_in_millis": 0,
                    "target_throttle_time_in_millis": 0
                },
                "translog": {
                    "recovered": 0,
                    "total": 0,
                    "percent": "100.0%",
                    "total_on_start": 0,
                    "total_time_in_millis": 0
                },
                "verify_index": {
                    "check_index_time_in_millis": 0,
                    "total_time_in_millis": 0
                }
            }
            # 其它shard详情省略...
        ]
    }
}

其他备份手段

elasticdump

  类似mysql dump的功能,对Elasticsearch集群的数据进行导入导出。适合非增量索引数据的备份。更多安装使用elasticdump请移步:elasticsearch-dump Github。

其他数据同步工具

  • Kettle: 免费开源的基于java的企业级ETL工具,功能强大简单易用,仅支持写入Elasticsearch。更多参考:Kettle Gighub
  • DataX: 是阿里云 DataWorks数据集成。更多参考:Datax Github 的开源版本,多种异构数据源之间高效的数据同步功能,目前仅支持写入Elasticsearch。
  • Flinkx: 是一个基于Flink的批流统一的数据同步工具,支持Elasticsearch的读取和写入。更多参考:Flinkx Github

你可能感兴趣的:(elasticsearch)