Nâng cấp Database Zero-Downtime: Cẩm nang sinh tồn với Blue-Green Deployment

Database tutorial - IT technology blog
Database tutorial - IT technology blog

Cơn ác mộng bảo trì lúc 2 giờ sáng

Tôi vẫn còn nhớ lần nâng cấp database lớn đầu tiên của mình. Chúng tôi có một instance PostgreSQL 9.6 trên môi trường production, nặng khoảng 1.2TB, cần chuyển lên phiên bản 11. Chiến lược của tôi ư? Một phương pháp “Cửa sổ bảo trì” (Maintenance Window) cổ điển. Chúng tôi treo một banner thông báo trên website, ngắt toàn bộ kết nối của ứng dụng vào lúc nửa đêm và bắt đầu chạy pg_dump. Đến 4:15 sáng, quá trình restore vẫn lẹt đẹt. Doanh nghiệp đang bị sụt giảm doanh thu nghiêm trọng, và tim tôi thì đập thình thịch trong lồng ngực.

Khái niệm “cửa sổ bảo trì” đang dần lùi vào dĩ vãng. Trong một thế giới mà độ khả dụng 99.999% là chuẩn mực, việc thông báo với người dùng toàn cầu rằng dịch vụ sẽ ngừng hoạt động trong bốn giờ là một điều rất khó chấp nhận. Người dùng không quan tâm đến việc bạn thay đổi định dạng lưu trữ; họ chỉ muốn dữ liệu của mình. Nâng cấp zero-downtime đã chuyển từ một thứ xa xỉ thành yêu cầu bắt buộc đối với các đội ngũ kỹ thuật hiện đại.

Tại sao nâng cấp Database thường yêu cầu Downtime?

Nút thắt cổ chai nằm ở vấn đề kỹ thuật. Hầu hết các database engine, bao gồm PostgreSQL và MySQL, đều thay đổi định dạng đĩa nội bộ giữa các phiên bản lớn (major version). Một file dữ liệu được ghi bởi PostgreSQL 12 có thể trở thành “vô nghĩa” đối với PostgreSQL 15.

Các phương pháp tiêu chuẩn thường đẩy bạn vào thế khó:

  • Nâng cấp Binary: Các công cụ như pg_upgrade rất nhanh, nhưng chúng vẫn yêu cầu dừng toàn bộ dịch vụ để đảm bảo tính nhất quán của dữ liệu.
  • Dump và Restore: Xuất mọi thứ ra file SQL và import lại. Với một database 500GB, quá trình này có thể dễ dàng ngốn mất 6 tiếng đồng hồ.

Downtime xảy ra vì từ trước đến nay chúng ta luôn gắn liền việc di chuyển dữ liệu với tính khả dụng của dịch vụ. Nếu database chính đang bận cấu trúc lại dữ liệu, nó không thể xử lý các tác vụ ghi mới một cách an toàn mà không đối mặt với nguy cơ hỏng dữ liệu.

So sánh các chiến lược nâng cấp

Tôi thường cân nhắc ba phương pháp dựa trên mức độ rủi ro mà doanh nghiệp có thể chấp nhận:

1. “Big Bang” (Nâng cấp tại chỗ)

Bạn tắt ứng dụng, chạy công cụ nâng cấp và cầu nguyện. Phương pháp này đơn giản nhưng rủi ro cực cao. Nếu việc nâng cấp gặp trục trặc giữa chừng, bạn buộc phải restore từ bản backup—việc này vô tình làm tăng gấp đôi thời gian downtime của bạn.

2. Di chuyển ở chế độ Read-Only

Bạn khóa ứng dụng ở chế độ chỉ đọc (read-only), sao chép dữ liệu sang phiên bản mới, sau đó chuyển đổi. Mặc dù cách này ngăn chặn mất mát dữ liệu, nhưng nó lại phá hỏng trải nghiệm của bất kỳ người dùng nào đang cố gắng lưu công việc hoặc thực hiện mua hàng.

3. Blue-Green Deployment

Đây là mô hình được ưu tiên trong ngành. Bạn chạy hai môi trường giống hệt nhau song song: “Blue” (phiên bản production hiện tại) và “Green” (phiên bản mới). Bạn đồng bộ dữ liệu giữa chúng trong thời gian thực. Khi Green đã sẵn sàng, bạn chỉ cần gạt công tắc. Tổng thời gian downtime? Thường là dưới 30 giây—vừa đủ để cập nhật một proxy hoặc bản ghi DNS.

Kế hoạch chi tiết: Zero-Downtime thông qua Logical Replication

Bí mật để nâng cấp mà không bị căng thẳng chính là Logical Replication. Physical replication sao chép các khối dữ liệu thô (raw blocks) và yêu cầu các phiên bản phải giống hệt nhau. Ngược lại, logical replication truyền phát các thay đổi dữ liệu cụ thể—như INSERT và UPDATE—dựa trên nội dung. Điều này cho phép một database phiên bản 13 giao tiếp with phiên bản 16 mà không gặp trở ngại nào.

Bước 1: Thiết lập môi trường Green

Đầu tiên, hãy khởi tạo một instance mới với phiên bản mục tiêu của bạn. Instance này cần có schema giống hệt production nhưng bắt đầu ở trạng thái trống. Mẹo nhỏ: Hãy vô hiệu hóa các ràng buộc (constraints) nặng, khóa ngoại (foreign keys) hoặc trigger trong quá trình đồng bộ ban đầu. Bạn có thể bật lại chúng sau đó để quá trình di chuyển diễn ra nhanh hơn.

Bước 2: Đổ dữ liệu ban đầu (Initial Data Seed)

Bạn cần một bản snapshot tại một thời điểm nhất định để bắt đầu. Tôi thường sử dụng một công cụ backup cung cấp snapshot nhất quán trong khi môi trường Blue vẫn đang xử lý lưu lượng truy cập thực tế. Trong quá trình di chuyển này, tôi thường cần ánh xạ các tập dữ liệu nhỏ hoặc file cấu hình. Khi cần chuyển đổi nhanh CSV sang JSON để import dữ liệu, tôi sử dụng toolcraft.app/vi/tools/data/csv-to-json. Nó chạy hoàn toàn trên trình duyệt, rất tốt cho bảo mật vì không có dữ liệu nhạy cảm nào rời khỏi máy của bạn.

Bước 3: Thiết lập đồng bộ Delta

Khi Green đã có dữ liệu nền tảng, bạn bắt đầu đồng bộ “delta” để cập nhật những gì đã xảy ra trong quá trình seed. Trong PostgreSQL, điều này có nghĩa là tạo một PUBLICATION trên Blue và một SUBSCRIPTION trên Green.

-- Trên Blue (PostgreSQL 12)
CREATE PUBLICATION upgrade_pub FOR ALL TABLES;

-- Trên Green (PostgreSQL 15)
CREATE SUBSCRIPTION upgrade_sub 
CONNECTION 'host=blue-db user=repl_user password=secret dbname=mydb' 
PUBLICATION upgrade_pub;

Đối với MySQL, hãy sử dụng Row-Based Replication (RBR). Thiết lập Green làm bản sao (replica) của Blue bằng lệnh CHANGE MASTER TO, đảm bảo server-id của bạn là duy nhất để tránh xung đột.

Bước 4: Chuyển đổi (Cutover)

Khi độ trễ replication (replication lag) giảm xuống dưới 100ms, bạn đã sẵn sàng. Hãy tuân thủ nghiêm ngặt trình tự sau:

  1. Tạm dừng ứng dụng hoặc trỏ nó về một trang bảo trì ngắn.
  2. Chờ vài giao dịch cuối cùng cập bến Green (theo dõi sát các chỉ số lag!).
  3. Cập nhật các sequence (Postgres) hoặc giá trị tự động tăng (MySQL).
  4. Trỏ chuỗi kết nối (connection string) của ứng dụng sang database Green.
  5. Đưa ứng dụng hoạt động trở lại.

Những bài học xương máu từ thực tế

Việc đồng bộ kỹ thuật thường là phần dễ dàng. Những trường hợp biên (edge cases) mới là thứ gây ra rắc rối. Đây là cách để bạn luôn đi trước một bước:

Hãy cẩn thận với các Sequence

Logical replication trong PostgreSQL không đồng bộ các sequence. Nếu bạn chuyển sang Green mà không cập nhật chúng, bản ghi mới đầu tiên của bạn sẽ bị lỗi vi phạm khóa chính (primary key violation). Luôn luôn chạy một script để setval() cho các sequence của bạn. Tôi thường thêm một khoảng đệm +1.000 vào giá trị lớn nhất để đảm bảo an toàn.

Lợi thế của Proxy

Đừng dựa vào việc cập nhật DNS; chúng có thể bị trình duyệt lưu cache trong nhiều phút. Hãy sử dụng một database proxy như PgBouncer hoặc HAProxy. Bạn có thể reload cấu hình proxy để trỏ sang IP mới ngay lập tức. Các kết nối hiện tại có thể tạm dừng trong tích tắc, nhưng chúng sẽ không bị ngắt.

Tính nhất quán của Schema

Cả hai môi trường phải có schema hoàn toàn giống nhau. Tôi đã từng thấy các đợt di chuyển thất bại vì một lập trình viên đã thêm một cột vào Blue sau khi bản snapshot cho Green được tạo. Hãy khóa các thay đổi schema trong suốt quá trình nâng cấp để ngăn chặn sự sai lệch.

Lời kết

Từ bỏ kiểu nâng cấp “được ăn cả ngã về không” đã thay đổi cuộc đời kỹ sư của tôi. Blue-Green deployment không chỉ là về thời gian uptime; nó còn là về sự an toàn. Nếu Green có hiện tượng tăng vọt CPU hoặc truy vấn chậm sau khi chuyển đổi, môi trường Blue vẫn ở đó, đã được đồng bộ đầy đủ và sẵn sàng để quay ngược lại (fallback). Mức độ kiểm soát đó xứng đáng với từng phút bỏ ra để thiết lập thêm.

Share: