Borgbackup Extraction

Borgbackup is slow. How to speed up the extraction process, around 97TB of data.

현 상황

좋은데 나쁜 상황이다. 97TB의 데이터가 온전히 보관되어 있다.

백업을 했을 당시에, 대체 무엇에 쫓겼는지는 모르겠지만 정리 방법이 엉망이었다.

// no highlight
borg info [repo]
Enter passphrase for key [repo]: 
- Repository ID: 9f569a0db926127236b9..........d5bb304dc722dcb8c2252c3
+ Location: [repo_location]{:js}
Encrypted: Yes (repokey)
Cache: /Users/[username]/.cache/borg/9f569a0db926127236b9..........d5bb304dc722dcb8c2252c3
Security dir: /Users/[username]/.config/borg/security/9f569a0db926127236b9..........d5bb304dc722dcb8c2252c3
------------------------------------------------------------------------------
// no highlight
                       Original size      Compressed size    Deduplicated size
All archives:               97.77 TB             81.88 TB             60.94 TB

									Unique chunks					Total chunks
Chunk index:						27985001					45119793

파일 개수는 기억나지도 않고, 내부 구조도 기억나지 않는다. 망했다

미션

현재 borgrepo는 12x14TB(raw 168TB, raid6 120TB)의 DAS에 있고, 더 나은 스토리지 (dRAID2, 36x4TB SAS)에 데이터를 손실 없이 옮기고, 검증해야 한다.

방안

DAS와 컴퓨터는 thunderbolt4로 연결되어 있고, NAS는 10G로 연결되어 있다.

borgbackup은 extract 구문을 사용 시 cache를 어느정도 사용하기 때문에, 싱글스레드가 빠르고, 디스크 액세스 타임이 낮은 컴퓨터를 선택하는 것이 좋다.

Borgbackup에서 제공하는 extract, mount, extract-tar를 사용하여 데이터를 옮길 수 있다.

  1. borgbackup의 extract를 사용하여 그대로 NAS에 복사한다.
  2. borgbackup의 mount를 사용하여 필요한 것만 복사한다.
  3. borgbackup의 extract-tar를 사용하고 원격지로 tar를 스트리밍하고, 원격지에서 바로 tar를 풀어준다.
  4. 한 번 쓰고 버릴 자동화 코드 만들기.

1. borg extract

borg extract는 가장 간단한 방법이다. extract 할 경로로 pwd를 이동한 뒤, repo와 archive를 지정하고, extract실행하면 된다.

다만, 어디선가 중단이 일어날 때 까지는 잘 동작한다. extract를 다시 실행하면, 해당 archive의 '어디선가 부터' 다시 시작하여, 실패시 중단점 부터 다시 시작하는 방식이 필요했다.

one-shot

failed

retry

Extract Location

Extract from start

Great!

Don't know exact brackpoint

2. borg mount

borg mount는 mount를 사용하여, 해당 archive를 마운트하고, 필요한 것만 복사하는 방법이다. 이 방법은 mount를 사용하기 때문에, 중단이 발생하더라도, mount를 해제하고, 다시 mount하면 된다. 다만, mount가 매우 느리고, 파일 개수가 많은 폴더를 조회하는 경우에는 아무것도 못한다.

3. borg extract-tar

borg extract보다 빠른 느낌이 있다. extract 실행시에 여러 archive를 동시 실행하는 경우 lock.roster 파일에 상당히 많은 lock이 걸렸는데, 그 보다는 완화된 느낌이다. 다만 extract-tar를 사용하면, tar를 스트리밍하기 때문에, 원격지에서의 tar 압축을 해제하는 overhead가 발생한다. 파일이 지나치게 큰 경우에는 원격지의 메모리에 따라 중단이 되는 경우도 있었다.

4. Scripting

몇 번의 시도 끝에, borg extract를 사용하며 filter 옵션을 하는 것은 문제가 있고, borg mount는 너무 느렸고, borg extract-tar는 원격지에서 tar를 해제하는 overhead를 신경 쓸 겨를이 없었다. 자동화가 필요했다.

파일 리스트를 DB에 저장하고, 각 archive를 병렬로 실행하는 방법을 사용했다.

import로 archive 내부의 각 파일에 대해 path와 size를 DB에 저장하고, extract를 실행할 때 size를 우선 검증하여 중단점을 확인하고, 중단된 부분부터 다시 시작하는 방법이다.
archive를 병렬로 실행하기 위해, ThreadPoolExecutor를 사용하여, 각 archive를 병렬로 실행하고, 각 archive의 extract가 끝나면 size 검증을 하고 DB에 업데이트를 한다.

Checksum 값을 사용하고 싶었으나, 기본적으로 borg는 각 파일의 checksum을 저장하지 않는다. Checksum을 borg list에 사용하는 순간, list를 하면서 extract가 이루어지고, extract를 하면서 checksum을 계산하여 output한다.. 현실적으로 90TB를 기다릴 시간은 없어서 타협한 부분이다.

아무튼 아래 흐름으로 약 14일 정도 걸렸다.

Extracting

check duplicated

write

import

extract

write mismatches

read

read

read

Start Python Script
with exclude rules
(regular expression)

Select mode
(import, extract)

SQLite DB

borglist TSV output
to Table
or check

BorgExtractor 초기화
(repo, archive, extract_path, db, threads)

get_paths_from_db()
DB에서 경로 목록 불러오기

find_common_prefix()
archive와 공통 경로 계산으로 strip-components 확정

기존 파일 체크
check_existing_files

남은 경로 대상 병렬 추출
borg extract
ThreadPoolExecutor

추출 파일 사이즈 검증
verify_extracted_files()

DB 업데이트 큐 처리
update_db_batch

Extraction Completed
_print_summary()

Lessons Learned

archive의 백업시기는 5년 정도 전 이다. borgbackup을 백업 할 당시 버전은 1.4였다. 현재 2.0 beta에서는 multi-thread extraction이 가능하다고 알려져 있으나, beta버전을 사용하기 위해 repo를 업그레이드 하는 것은 위험부담이 매우 컸다.

restic을 사용하자. borg 역시 대단한 백업 툴이지만, 이것저것 신경 쓸 것이 너무나도 많고, 자잘하다.

리뷰를 이정도 밖에 못하는건.. 그러니깐 조금 더 간편해 보이는 것으로 끌리는 이유는, 뭣 모르고 달려들던 5년 전 보다 나이가 들어 그럴 수도 있겠다 넘어가주면 좋겠다.