備份Cassandra的挑戰
備份Apache Cassandra資料庫很困難,并不複雜。您可以使用nodetool snapshot手動做快照,并将其從節點移到另一個節點。現有的開放源代碼工具(例如
tablenap)就是這樣做的。但是,它們都往往缺少線上生産中所需的某些功能,尤其是在還原資料時,這是對備份解決方案的終極測試。
為Cassandra提供災難恢複有一些有趣的挑戰和機遇:
- 每個SSTable中的資料都是不可變的,進而允許進行高效的差異備份,該差異備份僅複制自上次備份以來的更改。
- 每個SSTable都包含該節點負責的資料,還原過程必須確定将其放置在也負責該資料的節點上。否則,用戶端可能無法通路。
- 要恢複到不同的群集配置,節點數或令牌數的變化,需要按照Cassandra的規則将資料重新配置設定到新的拓撲中。
medusa(美杜莎)介紹
Medusa是一個指令行備份和還原工具,可了解Cassandra的工作方式。
該項目最初由Spotify建立,以替換其舊式備份系統。TLP在不久之後被聘來接管開發工作,使其可以投入生産并進行開源。
它已在小型和大型叢集上使用,并提供了營運團隊所需的大多數功能。
美杜莎支援:
- 備份單個節點。
- 恢複單個節點。
- 還原整個群集。
- 選擇性還原keyspace和表。
- 支援單個令牌和vnode群集。
- 清除舊資料的備份集。
- 完整或增量備份模式。
- 自動驗證還原的資料。
使用Python 3.6版的指令行工具,需要安裝在要備份的所有節點上。它支援2.1.0之後的所有版本的Cassandra,并且由于
Apache libcloud項目可以在許多平台上存儲備份,包括:
- Amazon Web服務S3。
- Google Cloud Platform GCS。
- 本地檔案存儲。
- 任何支援 libcloud的provider都 隻需最少的努力。
使用Medusa備份單個節點
一旦安裝并配置了medusa,就可以使用一個簡單的指令來備份節點:
medusa backup --backup-name=<backup name>
當這樣執行時,美杜莎将:
- 使用Cassandra nodetool指令建立快照。
- 将快照上載到配置的存儲提供程式。
- 從本地節點清除快照。
與SSTables一起,Medusa将為每個備份存儲三個元檔案:
完整備份和差異備份
所有Medusa備份僅從節點複制新的SSTable,進而減少了所需的網絡流量。然後,它有兩種方法來管理備份目錄中的檔案,我們稱之為完全備份或差異備份。對于差異備份,每個新備份僅保留對SSTables的引用,是以每個SStable無論其有多少個備份,僅有一份資料,。差異備份是預設的,在Spotify中的操作減少了某些群集的備份大小高達80%
完全備份每次運作時都會在節點上建立所有SSTable的完整副本。自上次備份以來未更改的檔案将在備份目錄中複制到新備份中(而不是從節點上複制)。與僅建立對檔案的引用的差分方法相反。當您需要制作完整副本并将所有檔案放在一個位置時,完全備份非常有用。

差異備份利用了由Cassanda使用的LSM存儲引擎建立的不可變SSTable的特點。在這種模式下,Medusa會檢查SSTable之前是否已經備份過,并且僅複制新檔案(就像往常一樣)。但是,該節點的所有SSTable然後都存儲在一個公用檔案夾中,并且備份清單僅包含中繼資料檔案和對SSTable的引用。
使用Medusa備份群集
Medusa目前缺少業務流程層來為您在所有節點上運作備份。實際上,我們一直在使用crontab進行群集範圍的備份。雖然我們一直在考慮了自動化執行此操作的最佳方法,但我們建議使用以下技術:
列出備份
具有相同“備份名稱”的所有備份均被視為群集的同一備份的一部分。Medusa可以提供群集的所有備份的清單,包括備份的開始和結束時間以及所有節點是否都已完成備份。
要列出叢集的所有現有備份,請在一個節點上運作以下指令:
$ medusa list-backups
2019080507 (started: 2019-08-05 07:07:03, finished: 2019-08-05 08:01:04)
2019080607 (started: 2019-08-06 07:07:04, finished: 2019-08-06 07:59:08)
2019080707 (started: 2019-08-07 07:07:04, finished: 2019-08-07 07:59:55)
2019080807 (started: 2019-08-08 07:07:03, finished: 2019-08-08 07:59:22)
2019080907 (started: 2019-08-09 07:07:04, finished: 2019-08-09 08:00:14)
2019081007 (started: 2019-08-10 07:07:04, finished: 2019-08-10 08:02:41)
2019081107 (started: 2019-08-11 07:07:04, finished: 2019-08-11 08:03:48)
2019081207 (started: 2019-08-12 07:07:04, finished: 2019-08-12 07:59:59)
2019081307 (started: 2019-08-13 07:07:03, finished: Incomplete [179 of 180 nodes])
2019081407 (started: 2019-08-14 07:07:04, finished: 2019-08-14 07:56:44)
2019081507 (started: 2019-08-15 07:07:03, finished: 2019-08-15 07:50:24)
在上面的示例中,名為“ 2019081307”的備份被标記為未完成,因為180個節點中有1個節點未能完成備份。
還可以驗證是備份中所有期望的檔案,并且它們的内容與備份時生成的哈希值比對。更多操作在Medusa
README檔案中進行了詳細說明。
恢複備份
當缺少備份的編排時,Medusa協調還原整個群集,是以您隻需要運作一個指令即可。該過程通過SSH連接配接到節點,并根據需要啟動和停止Cassandra,直到可以使用叢集為止。還原過程處理三種不同的用例。
案例1-還原到同一群集
這是最簡單的情況:将備份還原到同一群集。群集的拓撲結構未更改,建立備份時存在的所有節點仍在群集中運作。
使用以下指令運作就地還原:
$ medusa restore-cluster --backup-name=<name of the backup> \
--seed-target node1.domain.net
種子目标節點将用作發現群集中其他節點的聯系點。Medusa将發現叢集中節點和令牌配置設定的數量,并檢查其是否與源叢集的拓撲比對。
要完成此還原,每個節點将:
- 将備份資料下載下傳到
目錄中。/tmp
- 停止cassandra。
- 删除送出日志,儲存的緩存和資料目錄(包括系統keyspace)。
- 将下載下傳的SSTables移到資料目錄中。
- 啟動Cassandra。
不需要重新建立schema,因為它包含在系統keyspace中,并且可以從備份中複制。
情況2-還原到具有相同節點數的其他群集
還原到具有相同數量節點的其他群集會有些困難,因為:
- 目标群集可能具有不同的名稱,該名稱存儲在system.local表中。
- 節點可以具有不同的名稱。
- 節點可以具有不同的令牌配置設定。
使用以下指令運作遠端還原:
$ medusa restore-cluster --backup-name=<name of the backup> \
--host-list <mapping file>
該
host-list
參數告訴Medusa如何從原始備份節點映射到新叢集中的目标節點,該新叢集假定為正在工作的Cassandra叢集。映射檔案必須是具有以下各列的指令分隔檔案(無标題行):
- is_seed:
或True
訓示目标節點是否是種子節點。是以,我們可以首先還原并啟動種子節點。False
- target_node:目标叢集中節點的主機名。
- source_node:要從中複制備份資料的源節點的主機名。
例如:
True,new_node1.foo.net,old_node1.foo.net
True,new_node2.foo.net,old_node2.foo.net
False,new_node3.foo.net,old_node3.foo.net
除了上面為案例1列出的步驟之外,在執行到遠端叢集的備份時,還執行以下步驟:
- 不會修改system.local和system.peers表以保留叢集名稱并防止目标叢集連接配接到源叢集。
- 除非将
标志傳遞給restore指令,否則從備份中還原system_auth keyspace。--keep-auth
- 通過在
重新啟動節點時傳遞JVM參數,在目标節點上更新令牌所有權以比對源節點。這将中更新本地system keyspace,會引起重新更改資料所有權。-Dcassandra.initial_token
情況#3-還原到具有不同數量節點的其他群集
恢複到具有不同數量節點的其他叢集是最難處理的情況,因為:
- 令牌範圍永遠不能相同,因為節點數不同。
最後一點是問題的症結所在。我們無法獲得相同的令牌配置設定,因為我們有不同數量的節點,并且令牌被配置設定為在節點之間平均配置設定資料。但是,我們備份的SSTables包含與源群集中定義的令牌範圍對齊的資料。還原過程必須確定根據新令牌配置設定将資料放置在作為副本的節點上,否則資料似乎已丢失。
為了支援将資料還原到其他拓撲中,Medusa使用了Cassandra代碼庫中的
sstableloader
工具。盡管比從備份中複制檔案要慢,但是sstableloader能夠将資料“修複”到目标群集中。它通過讀取令牌配置設定并将SSTable中與新令牌範圍比對的部分流式傳輸到叢集中的所有副本來實作。
使用以下指令來運作到具有不同拓撲的叢集的還原:
$ medusa restore-cluster --backup-name=<name of the backup> \
--seed-target target_node1.domain.net
使用此技術還原資料有一些短闆:
- 還原将花費更長的時間。
- 加載到群集中的資料量将是備份集的大小乘以複制因子。例如,具有複制因子3的群集的備份将具有9個資料副本的副本。多餘的副本将通過壓縮删除,但是在還原過程中磁盤上的總負載将比還原結束時的總負載高。參見下面的進一步讨論。
- 将删除叢集中的目前schema,并使用備份中的schema建立一個新的。預設情況下,當删除schema時,Cassandra将做一個快照,該快照由
配置設定控制,Medusa或Cassandra不會清除該快照,這個快照将占用額外的磁盤空間。這是明智的安全預防措施,一種簡單的解決方法是手動確定目标群集中沒有任何資料。auto_snapshot
使用sstableloader還原時,有一些關于資料放大的額外說明。備份具有多副本的資料,假如我們的複制因子為3,大緻來說每個分區有3個副本。這些副本散布在我們從每個節點收集的SSTable上。當我們處理每個SSTable時,sstableloader将資料修複回群集,并将其發送到3個新副本。是以,備份包含3個副本,我們将處理每個副本,然後将每個副本發送到3個新副本,這意味着:
- 還原将九份資料副本發送到群集。
- 每個節點獲得三個資料副本,而不是一個。
運作這種類型的還原時,将發生以下操作序列:
現在可以在GitHub上使用
Medusa現在
可以在GitHub上使用,并且很快将通過
PyPi提供。使用此部落格文章和存儲庫中的
自述檔案,您應該能夠在開始的幾分鐘内進行備份。與往常一樣,如果您有任何問題,請在GitHub項目中建立一個問題以擷取幫助。它已經在Spotify中使用了幾個月,并在Google Cloud Storage(GCS)中存儲了PB的備份,并且我們感謝Spotify向社群捐贈了該軟體,以使其他人也可以放心地對其資料進行安全備份。
最後一件事,我們很樂于地接受社群貢獻patch,尤其是增加支援新對象存儲源,如阿裡OSS
入群邀約
為了營造一個開放的 Cassandra 技術交流環境,社群建立了微信群公衆号和釘釘群,為廣大使用者提供專業的技術分享及問答,定期開展專家技術直播,歡迎大家加入。另外阿裡雲提供免費Cassandra試用:
https://www.aliyun.com/product/cds