Online index migration and shard-scaling in OpenSearch with AOSC
Bài tóm tắt Atlassian 2026 3. Quy mô lớn Độ khó: Nâng cao
Atlassian · 2026 · 3. Quy mô lớn · Độ khó: Nâng cao — bài gốc
Bối cảnh
- Team Core Index Serving (Search Platform) vận hành OpenSearch phía sau search của Confluence, Jira và Rovo: hơn 300 cụm, hơn 2.500 data node, 1,7 PB, cụm dùng chung và cụm theo tenant ở 13 region (2026).
- Khác OpenSearch dùng cho log (index theo thời gian, dựng lại rẻ), ở đây index chính là sản phẩm: ghi nhiều, luôn online, không có giờ vắng để dựng lại.
- Yêu cầu "đổi hình index" đến liên tục: tách tenant lớn khỏi index dùng chung (noisy neighbor), tăng số shard khi tenant lớn lên, bỏ field (bỏ vector embedding không cần thì nhanh hơn rõ), đổi
textsangkeyword, làm phẳng field lồng. - Các lựa chọn có sẵn đều không đủ:
/_reindexchụp một thời điểm, không thấy ghi đến sau, nên index đích cũ ngay khi xong;/_split,/_shrinkcần chặn ghi suốt thao tác;- ghi kép ở ứng dụng giữ được online nhưng đẩy cả migration vào code indexer (retry, đối soát, "ghi thành công một bên còn bên kia xung đột version"), khó chắc hai bên bằng nhau (thường chấp nhận lệch khoảng 0,1% số document), bootstrap tốn tài nguyên. Một lệnh API thành dự án vài tuần.
Thay đổi chính: AOSC (plugin mã nguồn mở)
- Lấy mẫu của database: copy ban đầu + CDC phát lại mọi thay đổi + cutover ngắn. OpenSearch không có API CDC công khai nhưng có hai khối:
- Lucene changes snapshot: mỗi lệnh ghi trên shard có sequence number, đọc lại được theo khoảng (cần soft delete);
- retention lease: đánh dấu "đừng cắt lịch sử từ số này trở đi", để luồng phát lại còn đó khi cần.
- Backfill bằng
Engine.Searcher(giữ các segment cần đọc, không chặn merge); cutover bằng đổi alias nguyên tử. Search Platform vốn luôn gọi qua alias. - Quy trình mỗi shard: lấy retention lease → backfill → phát lại cho tới khi khoảng cách dưới 500 thao tác → khi mọi shard đã hội tụ thì chặn ghi index nguồn → phát lại lần cuối → so số document → đổi alias.
- Chọn chặn ghi ngắn (ứng dụng nhận lỗi retry được) thay vì giữ ghi ở alias; indexer vốn đã retry kỹ. Thực tế chặn ghi 2–5 giây, tối đa 30 giây với index 50 TB, 1,2 tỷ document.
- Chạy bên trong cụm, cạnh shard, vì mọi khối trên đều chỉ có cục bộ ở node giữ shard: worker trên mỗi data node làm phần của shard, coordinator trên cluster-manager điều phối toàn index; trao đổi qua cluster state (xuống) và transport action (lên). Có API trạng thái cho từng shard.
- Routing key tuỳ chỉnh (dùng cho multi-tenancy): delete trong changes snapshot không mang routing key, phát lại ngây thơ sẽ trượt shard. Cùng số shard thì tổng hợp routing key; split theo luỹ thừa 2 thì fan-out delete ra cả khối shard đích; trường hợp khác (shrink) chưa an toàn và bị từ chối.
- Không làm quá tải cụm đang phục vụ: chạy nhanh trên cụm rảnh thì đốt CPU, nên mục tiêu đổi từ nhanh sang chậm, đều, chỉnh được:
- cấu hình tạm cho đích lúc backfill (0 replica, tắt refresh), trả lại khi hội tụ;
- tối đa 1 shard nguồn đồng thời mỗi node ở production;
- ngưỡng hội tụ và số vòng tối đa: không đạt thì shard tự báo lỗi, để migration hỏng rõ ràng thay vì kẹt;
- gặp backpressure, admission control thì backoff có jitter;
- bộ điều tốc thay được:
adaptive_batch(AIMD trên kích thước batch, mặc định khi online),adaptive(Gradient2 cho cả batch và concurrency, dùng khi offline).
- Hỏng thì sao: trước khi đổi alias, nguồn vẫn là sự thật duy nhất, chạy lại là xong. Đổi alias là bước duy nhất không đảo được, chỉ làm sau khi chặn ghi, phát lại cuối và so số document đều qua; quay lui là một migration khác.
Vì sao (theo Atlassian)
Với một team nhỏ, mỗi lần đổi hình index bằng tay (dạy indexer ghi kép, trông backfill, dàn cutover) là một khoản "thuế". Shard và hình index là việc của hạ tầng search, không phải của ứng dụng. Đổi hình index online cũng là nền cho tự động scale shard sau này.
Bài học cho SWE
- Migration online của mọi kho dữ liệu đều có cùng khung: backfill, phát lại thay đổi, hội tụ, chặn ngắn, bắt kịp, kiểm, chuyển (Migration không downtime).
- Đưa migration vào trong hệ lưu trữ (cạnh shard và log thay đổi) thay vì để ứng dụng ghi kép; ứng dụng chỉ cần retry được lỗi tạm.
- Resharding một tenant lớn ra index riêng là thao tác thường xuyên, nên phải rẻ (Sharding và tách database).
- Việc nền trên cụm đang phục vụ phải tự điều tốc theo backpressure (AIMD) và có giới hạn concurrency cứng (Load shedding, rate limit và backpressure).
- Thiết kế để mọi bước trước bước cuối đều huỷ được mà không cần dọn.
Liên quan
Migration không downtimeSharding và tách databaseLoad shedding, rate limit và backpressureHạ tầng tìm kiếmMulti-tenancy và cô lập tenant
Được nhắc tới trong
Chủ đề (6)
Công ty (1)
Bài tóm tắt (2)