天天看點

Elasticsearch的Snapshot and Restore(快照備份與恢複)

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叢集還是常見的雲廠商的雲端。

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