Sự cố lưu trữ lúc 2 giờ sáng
Đó là lúc 2 giờ sáng, và thiết bị báo tin (pager) của tôi đang kêu inh ỏi. Instance PostgreSQL chính vừa chạm ngưỡng 98% dung lượng đĩa. Một lần nữa. Chúng tôi đã tăng kích thước volume EBS hai lần trong tháng này. Giờ đây, đội ngũ tài chính đang thắc mắc tại sao hóa đơn RDS hàng tháng lại vọt lên tới 12.000 USD. Thủ phạm là bảng telemetry_logs đã phình to lên tới 4TB, mặc dù ứng dụng của chúng tôi chỉ cần dữ liệu của 30 ngày gần nhất cho các hoạt động hàng ngày.
Lưu trữ năm năm nhật ký (logs) lịch sử trên ổ cứng NVMe hiệu suất cao là một sự lãng phí tài nguyên. Nó giống như việc cất giữ những cuốn kỷ yếu cấp ba cũ kỹ trong một hầm bạc bảo mật cao vậy. Nó đắt đỏ, không cần thiết và làm chậm tốc độ sao lưu cũng như kéo dài thời gian phục hồi dữ liệu. Đây chính là lúc Data Tiering phát huy tác dụng. Bạn giữ dữ liệu “Hot” trên các đĩa cứng nhanh và chuyển dữ liệu “Cold” sang các kho lưu trữ rẻ tiền như Amazon S3.
Đánh giá các lựa chọn lưu trữ (Archiving)
Khi cơ sở dữ liệu của bạn bắt đầu chạm giới hạn lưu trữ, thường sẽ có ba hướng giải quyết. Tôi đã triển khai cả ba và dưới đây là sự so sánh giữa chúng trong môi trường production:
1. Chiến lược “Xóa và Quên”
Bạn chạy một cron job để xóa sạch dữ liệu cũ hơn 90 ngày. Đây là cách đơn giản nhất nhưng cũng rủi ro nhất. Ngay khi khách hàng yêu cầu báo cáo tăng trưởng so với cùng kỳ năm ngoái, bạn sẽ gặp rắc rối. Trong kỷ nguyên SaaS hiện đại, dữ liệu là tài sản mà bạn hiếm khi muốn tiêu hủy hoàn toàn.
2. Cơ sở dữ liệu lưu trữ phụ
Bạn di chuyển các bản ghi cũ sang một instance PostgreSQL riêng biệt với cấu hình thấp hơn. Cách này giải phóng không gian trên DB chính nhưng lại tạo ra gánh nặng lớn cho các nhà phát triển. Ứng dụng của bạn giờ đây cần logic phức tạp để quyết định truy vấn cơ sở dữ liệu nào, làm tăng gấp đôi chi phí quản lý kết nối, tương tự như khi triển khai Read Replicas trong PostgreSQL.
3. Data Tiering với Foreign Data Wrappers (FDW)
Đây là cách tiếp cận cân bằng nhất. Bạn chuyển dữ liệu sang S3 nhưng vẫn giữ cho nó có thể truy cập được thông qua SQL tiêu chuẩn. Đối với ứng dụng, dữ liệu trông giống như một partition thông thường. Đối với ngân sách của bạn, nó chỉ tốn vài đồng lẻ. Đây là chiến lược mà chúng ta sẽ triển khai dưới đây.
Sự đánh đổi khi sử dụng S3 Tiering
Trước khi chuyển các workload production, bạn phải hiểu rõ đặc tính hiệu suất và thực hiện phân tích hiệu năng PostgreSQL. S3 không phải là sự thay thế trực tiếp cho ổ SSD cục bộ.
- Lợi ích:
- Tiết kiệm chi phí khổng lồ: S3 Standard có giá khoảng 0,023 USD/GB. So sánh với 0,125 USD/GB cho volume AWS gp3 hoặc hơn 0,20 USD/GB cho Provisioned IOPS.
- Khả năng mở rộng vô hạn: S3 không có trạng thái “đầy đĩa”. Bạn có thể mở rộng từ 1TB lên 1PB mà không cần chạm vào bất kỳ thanh trượt cấu hình nào.
- DB chính nhẹ hơn: Giữ cho các index đang hoạt động nhỏ gọn giúp chúng nằm trọn trong RAM. Điều này giúp các truy vấn “Hot” luôn chạy dưới ngưỡng 10ms.
- Nhược điểm:
- Tăng độ trễ: Một truy vấn cục bộ có thể mất 20ms, trong khi truy vấn tương tự thực hiện trên S3 có thể mất từ 2 đến 5 giây. Hãy dành phương án này cho các báo cáo nội bộ, không phải cho các tính năng trực tiếp cho người dùng.
- Chi phí quản lý: Bạn phải xử lý các IAM role và đảm bảo schema của các foreign table luôn đồng bộ với các tệp dữ liệu của mình.
Kiến trúc: Partitioning + S3
Đối với thiết lập cấp độ production, hãy sử dụng PostgreSQL Declarative Partitioning kết hợp với s3_fdw để mở rộng PostgreSQL vượt giới hạn một node đơn lẻ. Thiết lập này cho phép bạn có một bảng cha (ví dụ: orders) với các partition con như orders_2024_q3 (trên đĩa) và orders_2022_archive (trên S3).
Trong quá trình di chuyển này, bạn thường cần chuyển đổi dữ liệu cũ. Nếu bạn cần chuyển đổi các file CSV xuất ra thành JSON để kiểm tra hoặc xác thực, toolcraft.app/vi/tools/data/csv-to-json là một công cụ tuyệt vời. Nó xử lý mọi thứ ngay trong trình duyệt của bạn, giữ cho dữ liệu nhạy cảm không bị đẩy lên các máy chủ bên ngoài—một điều bắt buộc để tuân thủ SOC2.
Hướng dẫn triển khai từng bước
Hãy cùng cấu hình s3_fdw. Hướng dẫn này giả định bạn đang dùng một instance PostgreSQL dựa trên Linux hoặc một dịch vụ cho phép cài đặt extension tùy chỉnh.
Bước 1: Cài đặt Extension
Kích hoạt extension trong cơ sở dữ liệu của bạn. Trên AWS RDS hoặc Aurora, thông thường bạn sẽ sử dụng extension aws_s3 thay thế, nhưng s3_fdw là tiêu chuẩn cho Postgres tự quản lý.
CREATE EXTENSION s3_fdw;
Bước 2: Định nghĩa Foreign Server
PostgreSQL cần biết cách kết nối tới S3 bucket của bạn. Thay thế các phần giữ chỗ bằng region và thông tin xác thực AWS cụ thể của bạn.
CREATE SERVER s3_server
FOREIGN DATA WRAPPER s3_fdw
OPTIONS (host 's3.us-east-1.amazonaws.com');
CREATE USER MAPPING FOR current_user
SERVER s3_server
OPTIONS (access_key 'YOUR_ACCESS_KEY', secret_key 'YOUR_SECRET_KEY');
Bước 3: Ánh xạ Foreign Table
Bây giờ, hãy định nghĩa một bảng trỏ tới một tệp CSV cụ thể trong bucket của bạn. Đây đóng vai trò là cầu nối giữa các truy vấn SQL và đối tượng trên S3.
CREATE FOREIGN TABLE logs_2023_archive (
id bigint,
event_name text,
created_at timestamp
)
SERVER s3_server
OPTIONS (bucket 'my-company-archives', filename 'logs/2023_backup.csv', format 'csv');
Bước 4: Tự động hóa việc di chuyển dữ liệu
Việc di chuyển thủ công rất dễ xảy ra sai sót. Bạn nên viết một hàm PL/pgSQL để xử lý việc xoay vòng (rotation). Logic tuân theo một mô hình đơn giản: xuất dữ liệu, xóa lưu trữ cục bộ và liên kết bảng S3.
Dưới đây là cách thực hiện hoán đổi partition trong thực tế:
-- 1. Di chuyển dữ liệu cục bộ sang S3 (Ví dụ sử dụng các công cụ của AWS RDS)
SELECT * from aws_s3.query_export_to_s3(
'SELECT * FROM logs_old_partition',
aws_commons.create_s3_uri('my-company-archives', 'logs_old.csv', 'us-east-1')
);
-- 2. Loại bỏ partition cục bộ nặng nề
ALTER TABLE logs DETACH PARTITION logs_old_partition;
DROP TABLE logs_old_partition;
-- 3. Gắn partition S3 vào
ALTER TABLE logs ATTACH PARTITION logs_2023_archive
FOR VALUES FROM ('2023-01-01') TO ('2024-01-01');
Bài học thực tế rút ra
Phân lớp dữ liệu (tiering) không chỉ là để tiết kiệm tiền; nó giúp cơ sở dữ liệu của bạn có thể quản lý được trở lại. Khi một lệnh pg_dump đầy đủ chỉ mất 15 phút thay vì 12 giờ, mục tiêu thời gian phục hồi (RTO) của bạn sẽ được cải thiện đáng kể, hỗ trợ đắc lực cho quy trình nâng cấp database zero-downtime. Chỉ cần lưu ý một điều: S3 không hỗ trợ các index cơ sở dữ liệu truyền thống. Nếu bạn truy vấn dữ liệu đã lưu trữ, hãy luôn kèm theo một khoảng thời gian (date range) để ngăn chặn database engine quét qua mọi tệp tin trong bucket của bạn.

