Chương 55. Backup và restore

Ở chương trước, ta nói về các kiểu hỏng thường gặp trong production.

Retry storm.

Queue overload.

Database overload.

Provider outage.

Partial outage.

Graceful degradation.

Tất cả những thứ đó giúp hệ thống chống chịu tốt hơn.

Nhưng vẫn còn một câu hỏi rất thẳng:

Nếu dữ liệu quan trọng bị mất hoặc bị hỏng, ta cứu lại bằng cách nào?

Đó là bài toán backup và restore.

Backup là tạo bản sao dữ liệu.

Restore là khôi phục từ bản sao đó.

Nghe có vẻ đơn giản.

Nhưng trong hệ thống thật, có một sự thật hơi đau:

Backup chưa được test restore thì chưa nên được xem là backup đáng tin.

Vì rất nhiều team tưởng mình có backup.

Đến lúc cần khôi phục mới phát hiện:

File backup bị lỗi.
Thiếu bảng quan trọng.
Backup quá cũ.
Không ai biết cách restore.
Restore mất 12 tiếng trong khi business chỉ chịu được 1 tiếng.
Khôi phục database nhưng object storage không khớp.
Khôi phục xong nhưng dữ liệu bị lệch giữa các service.

Thông điệp chính của chương:

> Backup là bản sao. Restore mới là năng lực cứu hệ thống. Một hệ thống chỉ thật sự có backup khi nó đã từng khôi phục thành công trong điều kiện gần giống thực tế.

---

55.1. Một tình huống: mất dữ liệu bài nộp

Hãy quay lại hệ thống AI Judge.

Một ngày nào đó, có sự cố.

Một script migration chạy sai.

Thay vì chỉ cập nhật dữ liệu test, nó xóa nhầm một phần submission thật.

Ban đầu team không biết.

Sau vài phút, giáo viên báo:

Một số bài nộp của học sinh biến mất.

Team mở database.

Đúng là có vấn đề.

Câu hỏi lúc này không còn là:

Ai viết script sai?

Câu hỏi vận hành trước mắt là:

Ta có thể khôi phục không?
Khôi phục đến thời điểm nào?
Mất bao nhiêu dữ liệu?
Mất bao lâu?
Có làm hỏng dữ liệu mới phát sinh sau sự cố không?

Nếu backup tốt, team có đường đi.

Nếu backup mơ hồ, mọi người bắt đầu hoảng.

Đây là lý do backup không phải chuyện phụ.

Nó là một phần của kiến trúc hệ thống.

---

55.2. Backup không phải chỉ dành cho database

Khi nghe backup, nhiều người nghĩ ngay:

Backup database.

Đúng, nhưng chưa đủ.

Một hệ thống hiện đại thường có nhiều loại dữ liệu:

Database chính.
File upload.
Object storage.
Search index.
Cache.
Message queue.
Configuration.
Secret.
Log/audit.
Analytics data.
Model/prompt/rubric version.

Không phải tất cả đều cần backup giống nhau.

Nhưng ta phải biết dữ liệu nào quan trọng.

Trong AI Judge, dữ liệu có thể gồm:

User.
Lớp học.
Assignment.
Submission.
File bài làm.
Rubric.
Prompt version.
Kết quả chấm.
Feedback.
Audit log.
Job trạng thái chấm.

Nếu chỉ backup database mà file bài làm nằm trong object storage không được backup, restore sẽ bị khuyết.

Database nói:

Submission 123 có file essay-123.pdf.

Nhưng object storage không còn file đó.

Kết quả là dữ liệu nhìn có vẻ tồn tại, nhưng không dùng được.

Backup phải nhìn theo luồng nghiệp vụ, không chỉ theo từng công nghệ.

---

55.3. Câu hỏi đầu tiên: dữ liệu nào không được mất?

Không phải dữ liệu nào cũng quan trọng như nhau.

Ví dụ:

Bài nộp gốc của học sinh: cực kỳ quan trọng.
Điểm và feedback: rất quan trọng.
Cache dashboard: có thể tạo lại.
Search index: có thể rebuild.
Metric cũ: hữu ích nhưng không phải lúc nào cũng sống còn.
Temporary file: có thể bỏ.

Nếu xếp mọi dữ liệu ngang nhau, hệ thống backup sẽ vừa đắt vừa khó vận hành.

Cách tốt hơn là phân loại.

Ví dụ với AI Judge:

Tier 1: không được mất hoặc mất rất ít
- Submission gốc.
- File bài làm.
- User/assignment/rubric.
- Kết quả chấm chính thức.
- Audit log quan trọng.

Tier 2: có thể mất một phần nhỏ
- Job state.
- Notification history.
- Analytics gần đây.

Tier 3: có thể tạo lại
- Cache.
- Search index.
- Materialized view.
- Report tạm.

Khi đã phân loại, ta mới biết backup cái gì trước.

Senior không hỏi chung chung:

Có backup chưa?

Họ hỏi:

Dữ liệu nào được backup?
Bao lâu backup một lần?
Restore mất bao lâu?
Mất tối đa bao nhiêu dữ liệu?
Đã test restore chưa?

---

55.4. RPO là gì?

RPO là Recovery Point Objective.

Hiểu đơn giản:

Khi sự cố xảy ra, ta chấp nhận mất tối đa bao nhiêu dữ liệu?

Ví dụ:

RPO = 24 giờ

nghĩa là trong tình huống xấu, ta có thể mất dữ liệu phát sinh trong 24 giờ gần nhất.

Nếu backup chạy mỗi ngày lúc 00:00, và database hỏng lúc 23:59, bản backup gần nhất đã gần 24 giờ tuổi.

Với blog cá nhân, RPO 24 giờ có thể chấp nhận được.

Với hệ thống nộp bài trước deadline, RPO 24 giờ có thể là thảm họa.

Vì học sinh nộp bài trong ngày đó có thể mất hết dữ liệu.

Với AI Judge, có thể ta muốn:

Submission gốc: RPO vài phút hoặc gần 0.
Kết quả chấm: RPO vài phút đến vài chục phút, tùy có thể chấm lại không.
Cache/report: RPO không quan trọng vì rebuild được.

RPO càng thấp, hệ thống càng tốn công và tốn tiền.

Không nên nói:

Tất cả phải RPO = 0.

Trừ khi business thật sự cần và sẵn sàng trả giá.

---

55.5. RTO là gì?

RTO là Recovery Time Objective.

Hiểu đơn giản:

Khi sự cố xảy ra, ta cần khôi phục trong bao lâu?

Ví dụ:

RTO = 4 giờ

nghĩa là hệ thống có thể chịu downtime hoặc suy giảm trong tối đa 4 giờ trước khi vượt ngưỡng chấp nhận.

Với một tính năng phụ, RTO 24 giờ có thể ổn.

Với chức năng nộp bài ngay trước deadline, RTO 4 giờ có thể quá lâu.

RTO khác RPO.

RPO hỏi:

Mất bao nhiêu dữ liệu?

RTO hỏi:

Mất bao lâu để quay lại?

Ví dụ:

Backup mỗi 5 phút.
RPO tốt.
Nhưng restore database 2TB mất 10 giờ.
RTO xấu.

Ngược lại:

Restore rất nhanh.
Nhưng backup gần nhất cách đây 24 giờ.
RTO tốt, RPO xấu.

Thiết kế backup phải nhìn cả hai.

---

55.6. RPO/RTO giúp nói chuyện với business

RPO và RTO không chỉ là thuật ngữ kỹ thuật.

Chúng giúp team kỹ thuật và business nói chuyện rõ ràng.

Thay vì nói:

Hệ thống phải an toàn.

Ta nói:

Với bài nộp gốc, ta chấp nhận mất tối đa 5 phút dữ liệu.
Khi sự cố lớn, ta cần khôi phục chức năng nộp bài trong 30 phút.
Chức năng báo cáo có thể khôi phục trong 24 giờ.

Như vậy mới thiết kế được.

Nếu business muốn:

Không mất dữ liệu.
Không downtime.
Chi phí thấp.
Vận hành đơn giản.

thì đó là bốn mục tiêu rất khó cùng đạt.

Kiến trúc luôn có trade-off.

RPO/RTO làm trade-off hiện ra rõ.

---

55.7. Full backup, incremental backup, point-in-time recovery

Có nhiều kiểu backup.

Full backup là sao lưu toàn bộ dữ liệu tại một thời điểm.

Ví dụ:

Mỗi đêm 02:00, dump toàn bộ database.

Ưu điểm:

Dễ hiểu.
Dễ lưu.
Dễ biết một bản backup chứa gì.

Nhược điểm:

Tốn dung lượng.
Tốn thời gian.
Không đủ tốt nếu dữ liệu thay đổi liên tục.

Incremental backup là chỉ sao lưu phần thay đổi từ lần backup trước.

Ưu điểm:

Tiết kiệm dung lượng.
Nhanh hơn.

Nhược điểm:

Restore phức tạp hơn.
Cần đủ chuỗi backup.
Một mắt xích hỏng có thể làm restore khó.

Point-in-time recovery, thường gọi là PITR, là khả năng khôi phục đến một thời điểm cụ thể.

Ví dụ:

Script xóa nhầm dữ liệu lúc 14:03.
Ta restore database về trạng thái 14:02:50.

PITR rất hữu ích với database production.

Vì nhiều lỗi không phải database chết hẳn.

Mà là:

Xóa nhầm.
Update nhầm.
Migration sai.
Bug ghi dữ liệu bẩn.

Trong các tình huống đó, backup đêm qua có thể quá cũ.

PITR giúp giảm mất mát.

---

55.8. Snapshot không giống backup hoàn chỉnh

Snapshot là ảnh chụp trạng thái của một volume, database, hoặc storage tại một thời điểm.

Snapshot rất hữu ích.

Nhưng không nên tự động xem snapshot là backup hoàn chỉnh.

Vì còn phải hỏi:

Snapshot có nhất quán không?
Snapshot có nằm cùng region không?
Nếu account cloud bị xóa thì snapshot còn không?
Snapshot có được mã hóa không?
Snapshot giữ được bao lâu?
Đã restore thử từ snapshot chưa?

Một lỗi phổ biến:

Database và file storage được snapshot ở hai thời điểm khác nhau.

Khi restore:

Database trỏ đến file mới.
Nhưng snapshot file storage chưa có file đó.

Dữ liệu bị lệch.

Với hệ thống có nhiều nguồn dữ liệu, backup cần tính đến tính nhất quán giữa chúng.

Không phải lúc nào cũng cần nhất quán tuyệt đối đến từng giây.

Nhưng phải hiểu lệch ở đâu và xử lý thế nào.

---

55.9. Backup cùng nơi với production là rủi ro

Nếu production ở một nơi, backup cũng ở đúng nơi đó, cùng account, cùng quyền, cùng region, rủi ro vẫn lớn.

Ví dụ:

Ai đó xóa nhầm resource.
Script lỗi xóa cả backup.
Account bị compromise.
Region cloud gặp sự cố lớn.
Ransomware mã hóa dữ liệu và backup online.

Backup tốt thường cần tách biệt.

Ví dụ:

Backup ở region khác.
Backup ở account khác.
Backup có quyền ghi một chiều.
Backup có retention policy.
Backup có immutable storage nếu cần.

Immutable nghĩa là trong một khoảng thời gian, backup không thể bị sửa hoặc xóa dễ dàng.

Điều này đặc biệt quan trọng với sự cố bảo mật.

Nếu attacker có quyền production và có thể xóa luôn backup, backup gần như vô nghĩa.

---

55.10. Quy tắc 3-2-1

Một nguyên tắc dễ nhớ là 3-2-1.

Nó nói:

3 bản sao dữ liệu.
2 loại storage khác nhau.
1 bản nằm ngoài site hoặc ngoài môi trường chính.

Không phải hệ thống nào cũng áp dụng y nguyên.

Nhưng tư duy của nó rất tốt:

Đừng để mọi bản sao chết cùng một nguyên nhân.

Ví dụ:

Production database.
Backup trong cùng cloud account.
Backup copy sang account/region khác.

Hoặc:

Object storage chính.
Versioning bật.
Replication sang bucket khác có policy bảo vệ.

Điểm quan trọng không phải con số đẹp.

Điểm quan trọng là tránh single point of failure cho chính backup.

Backup cũng cần được thiết kế như một hệ thống.

---

55.11. Retention là gì?

Retention là thời gian giữ backup.

Ví dụ:

Giữ backup hằng ngày trong 30 ngày.
Giữ backup hằng tuần trong 12 tuần.
Giữ backup hằng tháng trong 12 tháng.

Retention quá ngắn có thể không đủ.

Vì có lỗi không được phát hiện ngay.

Ví dụ:

Bug tính điểm sai âm thầm chạy 10 ngày.
Nếu chỉ giữ backup 7 ngày, ta không còn bản trước khi bug xuất hiện.

Retention quá dài cũng có vấn đề:

Tốn tiền.
Tăng rủi ro giữ dữ liệu nhạy cảm lâu hơn cần thiết.
Liên quan đến yêu cầu pháp lý/xóa dữ liệu.

Vì vậy retention phải gắn với:

Mức quan trọng của dữ liệu.
Khả năng phát hiện lỗi muộn.
Chi phí lưu trữ.
Yêu cầu pháp lý.
Yêu cầu quyền riêng tư.

Không nên chọn retention bằng cảm giác.

---

55.12. Backup phải được mã hóa và kiểm soát quyền

Backup chứa dữ liệu thật.

Nhiều khi còn nguy hiểm hơn production, vì backup gom rất nhiều dữ liệu vào một nơi.

Do đó backup cần:

Mã hóa khi lưu.
Mã hóa khi truyền.
Kiểm soát ai được đọc.
Ghi audit log khi ai đó truy cập backup.
Tách quyền tạo backup và quyền restore nếu cần.
Không để backup public.
Không nhúng secret trong file backup không bảo vệ.

Với AI Judge, backup có thể chứa:

Thông tin học sinh.
Bài làm.
Điểm.
Feedback.
File upload.
Audit log.

Đây là dữ liệu nhạy cảm.

Một backup bị lộ cũng nghiêm trọng như database bị lộ.

Đôi khi còn nghiêm trọng hơn, vì backup có thể chứa dữ liệu lịch sử đã bị xóa khỏi production.

---

55.13. Restore mới là phần khó

Tạo backup thường dễ hơn restore.

Vì backup có thể chạy tự động.

Restore thì hay xảy ra trong lúc căng thẳng.

Khi restore, team phải quyết định:

Restore toàn bộ hay một phần?
Restore vào môi trường mới hay đè lên production?
Restore đến thời điểm nào?
Dữ liệu mới sau thời điểm đó xử lý ra sao?
Service nào dừng trước?
Service nào mở lại trước?
Ai xác nhận dữ liệu đúng?
User được thông báo thế nào?

Nếu chưa từng diễn tập, lúc sự cố thật sẽ rất dễ rối.

Một câu nói đáng nhớ:

Backup là hy vọng. Restore test là bằng chứng.

Team tốt không chỉ có lịch backup.

Team tốt có lịch test restore.

---

55.14. Restore toàn bộ và restore một phần

Không phải sự cố nào cũng cần restore toàn bộ.

Restore toàn bộ nghĩa là đưa cả hệ thống hoặc cả database về một trạng thái trước đó.

Điều này mạnh, nhưng nguy hiểm.

Vì có thể làm mất dữ liệu hợp lệ phát sinh sau thời điểm restore.

Ví dụ:

14:00 script xóa nhầm 100 submission.
14:30 phát hiện.
Trong 30 phút đó có 500 submission mới hợp lệ.

Nếu restore cả database về 13:59, ta cứu 100 submission bị xóa.

Nhưng có thể mất 500 submission mới.

Restore một phần nghĩa là khôi phục đúng phần bị mất/hỏng.

Ví dụ:

Restore backup vào môi trường tạm.
Trích 100 submission bị xóa.
Import lại vào production.
Kiểm tra liên kết file, result, audit.

Restore một phần thường khó hơn.

Nhưng trong nhiều sự cố dữ liệu, nó là cách ít gây thiệt hại hơn.

Muốn restore một phần tốt, schema và audit log phải hỗ trợ truy vết.

---

55.15. Restore vào môi trường tạm

Một nguyên tắc thực tế:

Đừng vội restore thẳng vào production nếu chưa chắc.

Nhiều trường hợp nên restore vào một môi trường tạm trước.

Mục đích:

Kiểm tra backup có dùng được không.
Xác định dữ liệu cần lấy.
So sánh trước/sau.
Viết script phục hồi có kiểm soát.
Cho người có trách nhiệm xác nhận.

Ví dụ AI Judge:

Restore database backup 14:00 vào staging-restore.
Tìm các submission đã bị xóa.
Kiểm tra file object storage còn không.
Export danh sách cần phục hồi.
Import lại vào production bằng script idempotent.

Cách này chậm hơn một chút.

Nhưng an toàn hơn nhiều so với thao tác trực tiếp lên production trong hoảng loạn.

---

55.16. Dữ liệu mới sau thời điểm backup là bài toán khó

Một trong những phần khó nhất của restore là dữ liệu phát sinh sau thời điểm backup.

Ví dụ:

Backup gần nhất lúc 13:00.
Sự cố xảy ra lúc 14:00.
Phát hiện lúc 14:30.

Trong khoảng 13:00 đến 14:30 có thể có:

Submission mới.
User mới.
Điểm mới.
Feedback mới.
Payment mới.
Message mới.

Nếu restore về 13:00, tất cả dữ liệu sau đó có nguy cơ mất.

Vì vậy cần hỏi:

Có transaction log không?
Có PITR không?
Có event log không?
Có audit log không?
Có thể replay một số thao tác không?
Có thể merge dữ liệu từ backup và production hiện tại không?

Trong các hệ thống quan trọng, restore không chỉ là copy file cũ đè lên file mới.

Nó là bài toán phục hồi trạng thái đúng nhất có thể.

---

55.17. Consistency giữa database và file storage

Rất nhiều hệ thống lưu metadata trong database và file trong object storage.

Ví dụ:

Database:
submission_id = 123
file_key = uploads/123.pdf

Object storage:
uploads/123.pdf

Nếu restore database mà không restore object storage, có thể database trỏ đến file không tồn tại.

Nếu restore object storage mà không restore database, có thể có file không còn record nào trỏ tới.

Không phải lúc nào cũng tránh được hoàn toàn.

Nhưng phải có cách kiểm tra và sửa.

Ví dụ:

Job kiểm tra file missing.
Job tìm orphan files.
Audit log khi upload.
Object versioning.
Quy trình restore database + object storage cùng thời điểm gần nhau.

Với AI Judge, bài nộp gốc thường quan trọng hơn kết quả chấm.

Nếu mất kết quả chấm, có thể chấm lại.

Nếu mất file bài làm gốc, rất khó cứu.

Vì vậy object storage chứa bài làm cần được đối xử như dữ liệu Tier 1.

---

55.18. Message queue có cần backup không?

Câu trả lời là:

Tùy queue chứa gì.

Nếu queue chỉ chứa job có thể tạo lại từ database, backup queue không quá quan trọng.

Ví dụ:

Database có submission trạng thái queued.
Nếu queue mất, ta có thể quét database và tạo lại job.

Nhưng nếu queue là nơi duy nhất chứa thông tin quan trọng, mất queue là mất dữ liệu.

Đó là thiết kế nguy hiểm.

Một nguyên tắc tốt:

Queue không nên là source of truth cho dữ liệu nghiệp vụ quan trọng.

Queue nên là đường vận chuyển công việc.

Source of truth nên nằm ở database hoặc event log bền vững.

Với AI Judge:

Submission nằm trong database.
Job chấm có thể được tạo lại từ trạng thái submission.
Queue mất thì khó chịu, nhưng không mất bài.

Đó là thiết kế tốt hơn.

---

55.19. Cache và search index thường nên rebuild

Cache thường không cần backup.

Vì cache là dữ liệu có thể tạo lại.

Search index cũng thường có thể rebuild từ database chính.

Ví dụ:

Elasticsearch index mất.
Ta rebuild từ bảng assignments, submissions, users.

Nhưng vẫn cần biết:

Rebuild mất bao lâu?
Trong lúc rebuild, tính năng search bị ảnh hưởng thế nào?
Có cần degrade UI không?
Rebuild có làm database production quá tải không?

Dữ liệu có thể rebuild không có nghĩa là miễn phí.

Nếu rebuild search index mất 20 giờ và làm database chậm, đó vẫn là rủi ro vận hành.

Vì vậy với dữ liệu rebuild được, ta vẫn cần kế hoạch phục hồi.

Chỉ là kế hoạch đó khác backup truyền thống.

---

55.20. Migration sai là lý do rất thực tế để cần restore

Nhiều sự cố dữ liệu không đến từ disk hỏng.

Mà đến từ chính code của ta.

Ví dụ:

Migration update nhầm tất cả rubric.
Script cleanup xóa nhầm submission.
Bug tính điểm ghi đè feedback cũ.
Admin thao tác nhầm.
Job batch chạy hai lần.

Những lỗi này nguy hiểm vì hệ thống vẫn "hoạt động".

Không có server nào chết.

Không có CPU nào đỏ.

Nhưng dữ liệu bị sai.

Để giảm rủi ro:

Backup trước migration lớn.
Dry run nếu có thể.
Giới hạn batch nhỏ.
Ghi audit log.
Có script rollback.
Có cách kiểm tra số row bị ảnh hưởng.
Không chạy script nguy hiểm bằng quyền quá rộng.

Một câu đơn giản nhưng cứu nhiều hệ thống:

Trước khi chạy lệnh sửa dữ liệu hàng loạt, phải biết cách quay lại.

---

55.21. Backup trước deploy có cần không?

Không phải deploy nào cũng cần backup thủ công.

Nếu hệ thống đã có PITR tốt, backup định kỳ tốt, migration an toàn, thì không cần mỗi deploy đều dump database bằng tay.

Nhưng với thay đổi dữ liệu lớn, nên cẩn thận hơn.

Ví dụ:

Đổi schema điểm số.
Gộp nhiều bảng kết quả chấm.
Chuyển file từ storage cũ sang storage mới.
Chuẩn hóa rubric.
Xóa dữ liệu cũ.

Những thay đổi này nên có:

Backup hoặc restore point rõ ràng.
Migration plan.
Rollback plan.
Verification query.
Giới hạn batch.
Theo dõi sau deploy.

Điểm quan trọng:

Backup không thay thế migration an toàn.

Backup là lưới cứu.

Nhưng không nên nhảy khỏi tầng cao chỉ vì có lưới.

---

55.22. Restore drill là gì?

Restore drill là diễn tập khôi phục.

Nghĩa là team chủ động thử restore trong điều kiện kiểm soát.

Ví dụ:

Mỗi tháng chọn một bản backup ngẫu nhiên.
Restore vào môi trường tạm.
Chạy kiểm tra dữ liệu.
Đo thời gian restore.
Ghi lại lỗi gặp phải.
Cập nhật runbook.

Restore drill trả lời các câu hỏi rất thật:

Backup có tải xuống được không?
Key giải mã còn dùng được không?
Người trực có đủ quyền không?
Restore mất bao lâu?
Script restore có còn chạy không?
Database version có tương thích không?
Object storage có restore khớp không?
Ứng dụng có chạy được trên dữ liệu restore không?

Nếu không drill, mọi câu trả lời chỉ là niềm tin.

Nếu có drill, team có bằng chứng.

---

55.23. Runbook restore nên có gì?

Runbook restore là tài liệu chỉ cách khôi phục khi sự cố xảy ra.

Nó không nên viết như bài văn dài.

Nó nên đủ rõ để người trực làm theo khi đang căng thẳng.

Một runbook tốt thường có:

Khi nào dùng runbook này.
Ai có quyền quyết định restore.
Các loại restore: toàn bộ, một phần, PITR.
Cách chọn thời điểm restore.
Cách tạo môi trường tạm.
Cách kiểm tra backup.
Cách dừng service ghi dữ liệu nếu cần.
Cách restore database.
Cách restore object storage.
Cách kiểm tra dữ liệu sau restore.
Cách mở lại traffic.
Cách thông báo cho user/stakeholder.
Cách ghi lại incident.

Runbook không cần hoàn hảo từ đầu.

Nhưng sau mỗi restore drill hoặc incident, nó phải được cập nhật.

Runbook cũ hơn hệ thống 2 năm có thể nguy hiểm.

Vì nó làm team tưởng mình có quy trình, nhưng quy trình đó không còn chạy.

---

55.24. Ai được quyền restore?

Restore là thao tác quyền lực.

Làm đúng thì cứu hệ thống.

Làm sai thì có thể phá dữ liệu mới.

Vì vậy cần rõ:

Ai được quyết định restore production?
Ai được thực hiện?
Ai xác nhận dữ liệu đúng?
Ai thông báo cho khách hàng/user?
Ai ghi incident report?

Không nên để mọi engineer đều có thể tự restore production bất cứ lúc nào.

Nhưng cũng không nên khóa quá chặt đến mức khi sự cố xảy ra không ai có quyền.

Thiết kế quyền tốt thường là:

Quyền đọc backup hạn chế.
Quyền restore production cần phê duyệt.
Quyền restore vào môi trường tạm dễ hơn nhưng vẫn audit.
Mọi thao tác restore được log.

Trong sự cố, rõ vai trò giúp giảm hỗn loạn.

---

55.25. Backup và bảo mật liên quan chặt chẽ

Backup là mục tiêu hấp dẫn với attacker.

Nếu attacker lấy được backup, họ có thể đọc dữ liệu mà không cần chạm vào database production nữa.

Nếu attacker xóa được backup, họ làm team mất khả năng phục hồi.

Nếu attacker mã hóa được backup, ransomware nguy hiểm hơn nhiều.

Vì vậy backup cần nằm trong thiết kế bảo mật.

Cần nghĩ đến:

Encryption.
Access control.
Immutable backup.
Separate account.
Audit log.
Key management.
Restore permission.
Regular restore test.

Một rủi ro hay bị quên là key.

Backup được mã hóa nhưng key mất thì không restore được.

Backup được mã hóa nhưng key bị lộ thì attacker có thể đọc.

Key management là một phần của backup strategy.

---

55.26. Backup và compliance

Nếu hệ thống xử lý dữ liệu người dùng, backup còn liên quan đến compliance.

Ví dụ:

Người dùng yêu cầu xóa dữ liệu.
Dữ liệu trong production đã xóa.
Nhưng backup vẫn còn.

Ta cần chính sách rõ:

Dữ liệu trong backup được giữ bao lâu?
Khi restore từ backup cũ, làm sao đảm bảo dữ liệu đã xóa không sống lại sai cách?
Backup có chứa dữ liệu nhạy cảm không?
Ai được truy cập?

Tùy lĩnh vực và luật áp dụng, yêu cầu sẽ khác nhau.

Điểm quan trọng trong sách này không phải học thuộc luật.

Điểm quan trọng là:

Backup không nằm ngoài trách nhiệm dữ liệu.

Dữ liệu đã đi vào backup vẫn cần được quản lý.

---

55.27. Monitoring cho backup

Backup cũng cần monitoring.

Không nên để backup fail âm thầm trong 3 tháng.

Cần theo dõi:

Backup job có chạy không?
Backup gần nhất lúc nào?
Backup size có bất thường không?
Backup duration có tăng không?
Upload/copy sang storage khác có thành công không?
Encryption có thành công không?
Retention có xóa đúng không?
Restore drill gần nhất khi nào?

Một dấu hiệu rất đáng nghi:

Backup size hôm nay nhỏ hơn bình thường rất nhiều.

Có thể backup thiếu dữ liệu.

Hoặc:

Backup bỗng tăng gấp 10 lần.

Có thể có dữ liệu rác, log phình, hoặc lỗi cấu hình.

Alert cho backup nên rõ ràng:

Backup Tier 1 failed.
No successful backup in 6 hours.
Restore drill overdue.
PITR lag too high.

Backup fail là sự cố nghiêm túc, dù user chưa thấy gì.

---

55.28. Kiểm tra backup không chỉ là kiểm tra file tồn tại

Một check kém:

File backup tồn tại.

File tồn tại không có nghĩa là dùng được.

Check tốt hơn:

File backup có size hợp lý.
Checksum đúng.
Có thể giải mã.
Có thể restore vào môi trường tạm.
Ứng dụng đọc được dữ liệu restore.
Một số record mẫu tồn tại.
Quan hệ dữ liệu chính không bị đứt.

Với AI Judge, sau restore test có thể kiểm tra:

Một assignment mẫu còn tồn tại.
Submission mẫu còn file.
Rubric còn đúng version.
Result chấm còn liên kết với submission.
User permission còn đúng.
Audit log quan trọng còn đọc được.

Đó là kiểm tra restore theo nghiệp vụ.

Không chỉ kiểm tra theo hạ tầng.

---

55.29. Thiết kế AI Judge backup thực dụng

Với AI Judge, một chiến lược thực dụng có thể là:

Database chính:

PITR bật.
Backup định kỳ.
Retention theo nhu cầu business.
Restore drill hằng tháng.

Object storage chứa bài làm:

Versioning bật.
Replication sang bucket/region/account khác nếu cần.
Lifecycle policy rõ.
Quyền xóa hạn chế.

Kết quả chấm và feedback:

Lưu trong database chính.
Gắn với submission_id và rubric_version.
Ghi idempotent.
Có thể chấm lại nếu cần, nhưng không xem nhẹ dữ liệu này.

Queue:

Không là source of truth.
Job có thể tạo lại từ database.
Theo dõi job state.

Search/report/cache:

Có kế hoạch rebuild.
Không nhất thiết backup như dữ liệu gốc.

Runbook:

Restore toàn bộ.
Restore một phần submission.
Restore object file.
Rebuild queue.
Rebuild search index.

Monitoring:

Alert khi backup fail.
Alert khi PITR lag.
Alert khi replication fail.
Alert khi restore drill quá hạn.

Điểm cốt lõi:

Không mất bài nộp gốc.
Không mất liên kết giữa bài, rubric, điểm và feedback.
Nếu chấm chậm có thể chịu được.
Nếu mất bài gốc thì rất khó chấp nhận.

---

55.30. Một kịch bản restore cụ thể

Giả sử lúc 14:03 có script xóa nhầm 200 submission.

14:20 phát hiện.

Một hướng xử lý có thể là:

1. Dừng script lỗi.
2. Đóng quyền chạy script tương tự.
3. Xác định phạm vi: submission nào bị xóa.
4. Chọn thời điểm trước lỗi: 14:02.
5. Restore backup/PITR vào môi trường tạm.
6. Trích 200 submission bị xóa.
7. Kiểm tra file object storage tương ứng.
8. Import lại production bằng script idempotent.
9. Kiểm tra assignment, user, result, file.
10. Ghi audit log phục hồi.
11. Thông báo cho stakeholder.
12. Viết incident report và bổ sung guardrail.

Điểm đáng chú ý:

Không vội restore toàn bộ production.
Không đè mất dữ liệu mới từ 14:03 đến 14:20.
Không chỉ phục hồi record database mà quên file.
Không kết thúc khi script import chạy xong; phải verify nghiệp vụ.

Đây là khác biệt giữa "có backup" và "biết cứu dữ liệu".

---

55.31. Những sai lầm phổ biến

Sai lầm thứ nhất:

Tin rằng cloud tự lo hết.

Cloud cung cấp công cụ.

Nhưng chiến lược backup, restore, quyền, retention, test restore vẫn là trách nhiệm của team.

Sai lầm thứ hai:

Chỉ backup database.

Trong khi file, object storage, config, secret, hoặc event log cũng quan trọng.

Sai lầm thứ ba:

Không test restore.

Đây là sai lầm lớn nhất.

Sai lầm thứ tư:

Không có RPO/RTO.

Kết quả là không ai biết backup hiện tại có đủ tốt không.

Sai lầm thứ năm:

Backup nằm cùng chỗ, cùng quyền với production.

Một lỗi hoặc một cuộc tấn công có thể xóa cả hai.

Sai lầm thứ sáu:

Không nghĩ đến dữ liệu mới sau thời điểm restore.

Restore sai có thể cứu dữ liệu cũ nhưng làm mất dữ liệu mới.

Sai lầm thứ bảy:

Runbook không được cập nhật.

Đến lúc cần thì lệnh không còn đúng, quyền không còn đủ, tên service đã đổi.

---

55.32. Checklist backup và restore

Trước khi tin rằng hệ thống đã an toàn, hãy hỏi:

  • Dữ liệu nào là Tier 1?
  • RPO của từng loại dữ liệu là bao nhiêu?
  • RTO của từng chức năng là bao nhiêu?
  • Database có PITR không?
  • File/object storage có versioning hoặc backup không?
  • Backup có nằm tách khỏi production không?
  • Backup có được mã hóa không?
  • Ai được đọc backup?
  • Ai được restore?
  • Retention là bao lâu?
  • Backup fail có alert không?
  • Backup size bất thường có bị phát hiện không?
  • Đã restore thử trong 30 ngày gần nhất chưa?
  • Restore drill mất bao lâu?
  • Có runbook restore không?
  • Runbook có được cập nhật sau drill không?
  • Có cách restore một phần không?
  • Có xử lý dữ liệu mới phát sinh sau thời điểm backup không?
  • Queue có phải source of truth không?
  • Cache/search index có kế hoạch rebuild không?

Nếu nhiều câu trả lời là "không biết", hệ thống chưa thật sự sẵn sàng.

---

55.33. Kết luận của chương

Backup và restore là phần dễ bị xem nhẹ cho đến khi sự cố xảy ra.

Nhưng khi dữ liệu bị mất hoặc bị hỏng, không có gì thay thế được một quy trình phục hồi đã được kiểm chứng.

Backup là bản sao.

Restore là năng lực quay lại.

RPO nói ta chấp nhận mất bao nhiêu dữ liệu.

RTO nói ta cần quay lại nhanh đến mức nào.

PITR giúp khôi phục đến một thời điểm cụ thể.

Retention quyết định giữ backup bao lâu.

Encryption và access control bảo vệ backup khỏi rò rỉ.

Restore drill biến niềm tin thành bằng chứng.

Thông điệp cần nhớ:

> Đừng hỏi "có backup chưa" rồi yên tâm. Hãy hỏi "đã restore thử chưa, mất bao lâu, mất bao nhiêu dữ liệu, và dữ liệu sau khi restore có đúng với nghiệp vụ không".

Ở chương tiếp theo, ta sẽ chuyển sang phần testing: vì muốn hệ thống đáng tin, ta không chỉ cần backup khi mọi thứ hỏng, mà còn cần cách phát hiện lỗi trước khi nó đi vào production.