一種既便捷又超便宜的數據庫(MySQL、MongoDB)備份與恢復方案

一種既便捷又超便宜的數據庫(MySQL、MongoDB)備份與恢復方案:數據庫的備份和恢復是很古老的話題了,可是現有的方案沒找到順手的,沒辦法只能從新發明輪子了。代碼參考db-backup-and-restorehtml

1.個人需求場景

  • 1.基本需求: 備份和容災恢復,按指定時間週期備份,當生產系統故障時,可以進行恢復
  • 2.業務需求: 可以回滾恢復到某個指定時間點的數據
    • 2.1.好比用戶誤刪除數據或者把數據搞亂掉了,要求恢復到2個月前的數據再從新開始
    • 2.2.開發測試時,有時會使用某個歷史節點的數據進行功能測試
  • 3.備份和恢復使用方便,簡單易懂
  • 4.故障後的恢復過程速度快
  • 5.廉價的備份成本
  • 6.備份數據除了保存在本地外,也可以保存在雲存儲
  • 7.支持mongodb、mysql等經常使用的業務數據庫

2.個人探尋過程

2.1.阿里雲的數據庫備份RBS

詳細參見官網介紹:阿里雲的數據庫備份服務RBSpython

RBS知足需求場景中的一、二、3,功能仍是挺強大的,可是有兩個致命缺點,一個是貴,另外一個是死慢死慢的mysql

第一點:貴,RBS是按備份數據量收費的,而備份數據量以下所示,「經過備份鏈路的實際數據大小」,跟你每月執行備份的次數有關。若是我有50G數據,天天備份一次,每月就要1000多塊錢,另外備份存儲也要單獨收費 git

阿里雲RBM中的數據量定義

第二點:最不能忍受,恢復數據執行起來死慢死慢的,我作了個測試,總共50M數據文件,RBS恢復了2個小時尚未執行完,這麼點數據量用mongorestore,幾秒鐘就能夠執行完。github

2.2.github上的開源方案

  • mgob : 一個golang大神寫的,是基於docker容器的Mongodb備份程序。能夠備份到亞馬遜的S三、gcloud,也能夠本地備份。
    • 可是不支持備份到阿里雲,
    • 並且恢復數據的操做不太理想,須要手工下載到本地,而後再執行mongorestore命令,不夠傻瓜化
  • PyBackup: 能夠存儲到oss、騰訊雲、七牛等,還比較適合咱們的需求場景,可是沒有對應的數據恢復功能。另外備份任務定時執行是經過操做系統的cron控制的
  • mongodb-backup-manager: 界面,可是說明文檔不全,部署起來比較麻煩,本身自己還須要一個mongodb數據庫。最關鍵的是也沒有數據恢復功能
  • AliyunRDS: 實現阿里雲RDS數據庫備份數據庫自動定時下載,並轉儲阿里雲OSS文件服務器, 使用C#實現的,還把工程文件上傳,看着就不利索!

總結: 不論是阿里雲的數據庫備份RBS仍是github已有的開源方案,都不是太適合咱們的業務場景需求,只好從新造輪子了。golang

3.個人方案

3.1.方案整體框架

【方案整體框架】包含兩個主要程序:sql

  • 備份程序:常駐進程,週期性執行備份任務,備份文件保存在本地或者上傳到雲存儲(如阿里雲、七牛、騰訊雲等)。
  • 恢復程序:單次執行,經過引導步驟傻瓜式操做,簡單易上手

數據庫備份和恢復流程

3.2.基於時間衰減的備份存儲策略

【基於時間衰減的備份存儲策略】 備份存儲的時間衰減策略: 越近的數據越重要,保存的時間間隔越小,份數越多;越老的數據重要性越小,保存的時間間隔越大,份數越少 能夠經過策略參數控制,例如:mongodb

  • "days": 6, 最近6天,天天保存一份
  • "weeks": 3, 最近3周,每週保存一份
  • "months": 6, 最近6個月,每個月保存一份
  • "years": 5, 最近5年,每一年保存一份,超過5年以上就不保留備份了

基於時間衰減的備份存儲策略

好比5年的歷史數據,備份數= 6 + 3 + 6 + 5 = 20docker

以每一個備份20G的存儲大小爲例,20G*20份==400G,購買一個500G的歸檔型存儲包,每一年的存儲費用爲135元,算是很是便宜的方案了(參加 阿里雲產品訂價-對象存儲OSS數據庫

阿里雲產品訂價-對象存儲OSS-存檔存儲包

3.3.恢復程序

【恢復程序】的執行邏輯以下面有限狀態機所示,用戶只須要根據引導輸入3個指令便可完成一個恢復:

  • input_uri: 輸入目標數據庫的uri
  • choice_task: 選擇一個備份任務(在config.tasks中配置)
  • choice_file: 選擇一個備份文件 (能夠是本地的備份文件,也能夠是遠端的備份文件)
    數據庫恢復執行邏輯有限狀態機

4.quickstart

4.1.運行條件

  • python3.6版本以上
  • 若是是mongodb,須要預安裝mongodump和mongorestore命令
  • 若是是mysql,須要預安裝mysql客戶端,能夠支持mysql和mysqldump命令

4.2.下載工程代碼

git clone https://github.com/perfectstorm88/db-backup-and-restore
cd db-backup-and-restore
pip install -r requirements.txt
cp config.sample.yml config.yml
複製代碼

4.3.配置config.yml,定義第一個備份任務

最簡單的樣例以下:

tmpPath: './temp'
archivePath: './archive'
local:
 retention: 10   # number of backups to keep locally

tasks:
 - name: 'mongo_my_test1'
 type: 'mongodb'  
 schedule: "day 13:15" # 天天 13:15執行
 params:  # 經過mongodump執行的參數
 uri: "mongodb://test:test@127.0.0.1:13722/lcz_test1" #
複製代碼

4.4.數據庫備份

有兩種啓動方式,啓動常駐進程,週期任務調度:

python backup.py -l
複製代碼

另外一種方式,是直接啓動任務,忽略schedule參數,當即執行數據庫備份,通常應用在測試場景,如

python backup.py -t mongo_my_test1
複製代碼

4.5.數據庫恢復

執行restore.py ,按着引導步驟執行便可

python restore.py 
複製代碼

4.5.1. 數據恢復執行樣例

恢復程序】的執行邏輯以下面有限狀態機所示,用戶只須要根據引導輸入3個指令便可完成一個恢復:

  • input_uri: 輸入目標數據庫的uri
  • choice_task: 選擇一個備份任務(在config.tasks中配置)
  • choice_file: 選擇一個備份文件 (能夠是本地的備份文件,也能夠是遠端的備份文件)
    數據庫恢復執行邏輯有限狀態機

執行 python restore.py命令,過程以下:

*******************welcome to use database restore program****************
# 【輸入】選擇一個備份任務(任務名稱是在config.yml )
please choice the task to restore  
0) mongo_lcz_test1
1) mysql_db1
-1) return last step
(choice task)->1
# 【輸入】選擇一個數據源文件
please choice the following file to restore  
 0) 20190829150621.zip 232.100 KB  (local)
-1) return last step
(choice task)->0
# 【輸入】輸入目標數據庫的uri
please input the destination db uri,format is [scheme://][user[:[password]]@]host[:port][/schema][?attribute1=value1&attribute2=value2]
(such as mysql://root:123456@127.0.0.1/db1)  
(uri)->mysql://root:123456@127.0.0.1/db2
# 檢查uri格式
now is check uri ....                            
# 解壓縮zip文件
unzip file:/root/db-backup-and-restore/./archive/mysql_db1/20190829150621.zip 
# 執行數據庫恢復命令
2019-08-29 16:13:57,833 INFO start exec restore cmd: mysql  -uroot -p123456 -h47.99.73.225 db2 < /root/db-backup-and-restore/temp/uIZ3XfhB/back.sql
2019-08-29 16:13:57,857 DEBUG mysql: [Warningder] Using a password on the command line interface can be insecure.
2019-08-29 16:14:01,041 DEBUG b
process exit
複製代碼

6.配置參數詳解

tmpPath: './temp'
archivePath: './archive'
# oss: # 存儲到OSS
# url: "http://oss-cn-hangzhou.aliyuncs.com"
# bucket: "jfjun4test"
# accessKey: "accessKey"
# secretKey: "secretKey"
# prefix: 'backup/' # oss中的存儲根路徑
# # 存儲策略,只有一個起做用,優先級timeDecay>retention>expireDays,
# expireDays: 730 # 最大保存天數
# retention: 14 # 最大保留分數
# timeDecay:
# - months: 6 # 若是超過2個月後,每月只保留一份
# - years: 10 # 若是超過2年後,每一年只保留一份
# - days: 6
# - weeks: 3

# 存放到本地,存放目錄 {archivePath}/{task.name}/
local:
  # 稀疏策略,若是配置了稀疏策略,則retention失效,expireDays失效
 expireDays: 730  # 最大保存天數
 retention: 10    # 最大保留份數
 timeDecay:   # 時間衰減保存策略
 days: 6,   # 最近6天,天天保存一份
 weeks: 3,  # 最近3周,每週保存一份
 months: 6, # 最近6個月,每個月保存一份
 years: 5,  # 最近5年,每一年保存一份,超過5年以上就不保留備份了

tasks:
 - name: 'mongo_lcz_test1'
 type: 'mongodb'
    # schedule表示執行時間策略
    # "day 03:21" # 天天 03:21執行
    # "hour :31" # 每小時 31分執行
    # "monday 03:21" # 每週一 03:21執行
 schedule: "day 13:15" # 天天 13:15執行
 params:  # 經過mongodump執行的參數
      # uri: "mongodb://test:test@127.0.0.1:13722/lcz_test1"
 d: lcz_test1
 u: test
 p: test
 h: 127.0.0.1:13722

 - name: 'mysql_db1'
 type: 'mysql'
 schedule: "day :00"  # 每週
 params:  # 經過mysqldumap執行的參數
      # uri: "mysql://root:123456@127.0.0.1/db1"
 u: "root"
 p: "123456"
 databases: "db1"
 host: "127.0.0.1"
複製代碼

7.擴展閱讀

上述方案爲全量備份,比較適合於中小型業務場景,好比200G如下的的數據量,若是是過T的數據量,能夠考慮按期全量+增量備份方案,下面爲擴展閱讀

相關文章
相關標籤/搜索