Từ Single-tenant đến Multi-tenant: Hành trình Atlassian xây lại kiến trúc Cloud cho hàng triệu khách hàng
Khám phá cách Atlassian (cha đẻ Jira, Confluence) giải quyết bài toán scale, chuyển đổi từ kiến trúc Single-tenant truyền thống sang Multi-tenant Cloud hiện đại với Tenant Context Service (TCS) và GeoDNS.
Nội dung bài viết
Khi một công ty SaaS phát triển từ vài nghìn lên hàng triệu khách hàng, bài toán không còn đơn giản là "làm sao để phần mềm chạy được". Thách thức thực sự là: Làm sao để hệ thống mở rộng cực nhanh, tối ưu chi phí, chịu lỗi tốt nhưng vẫn đảm bảo dữ liệu của khách hàng A không bao giờ lọt sang khách hàng B?
Đây chính xác là bài toán mà Atlassian đã phải đối mặt khi đưa các "con gà đẻ trứng vàng" như Jira và Confluence từ mô hình Server truyền thống lên Cloud. Họ không đơn giản là "bê" ứng dụng lên AWS, mà đã tái thiết kế lại toàn bộ cách hệ thống vận hành.

1. Giới hạn chết người của Single-tenant Architecture#
Trong giai đoạn đầu, Atlassian sử dụng mô hình Single-tenant (Đơn khách hàng). Nghĩa là mỗi công ty (ví dụ: Decathlon, Nike) sẽ có một cỗ máy chủ (Compute Node) và Database riêng biệt. Node đó được "cấu hình cứng" để biết chính xác nó đang phục vụ ai.

Cách tiếp cận này rất an toàn và dễ hiểu, nhưng khi số lượng khách hàng đạt mốc hàng chục nghìn, nó bộc lộ 3 tử huyệt:
- Khả năng chịu lỗi kém (Blast Radius): Nếu một Compute Node bị hỏng (chết phần cứng, lỗi win), toàn bộ công ty đó sẽ mất truy cập vào Jira.
- Nỗi ác mộng Deploy: Cập nhật phiên bản mới đồng nghĩa với việc nâng cấp từng node một. Một lần rollout toàn cầu có thể kéo dài hơn 24 giờ và luôn rình rập rủi ro downtime.
- Lãng phí chi phí khổng lồ: Khách hàng lớn hay nhỏ đều "chiếm rịt" một server riêng. Server chạy 24/7 kể cả lúc nửa đêm không ai dùng, gây lãng phí tài nguyên khủng khiếp.
2. Bước nhảy vọt lên Multi-tenant: Tách rời "Bộ não" và "Dữ liệu"#
Để sống sót, Atlassian buộc phải chuyển sang Multi-tenant Architecture. Nguyên tắc cốt lõi được thay đổi: Compute node không còn gắn cố định với bất kỳ khách hàng nào.
Lúc này, các Compute Node trở thành những cỗ máy Stateless (Vô trạng thái). Bất kỳ khách hàng nào cũng có thể được xử lý bởi bất kỳ Node nào đang rảnh rỗi.
Sự thay đổi này mang lại sức mạnh to lớn:
- Scale ngang hoàn hảo: Lưu lượng tăng? Chỉ cần bật thêm Node mới.
- Tự phục hồi: Một Node chết? Request lập tức chuyển sang Node khác, khách hàng không hề hay biết.
- Zero-Downtime Deployment: Cập nhật phiên bản bằng cách tạo Node mới chứa code mới, từ từ chuyển traffic sang rồi tắt dần Node cũ.
Nhưng một bài toán hóc búa xuất hiện: Khi một request từ nike.atlassian.net bay tới một Compute Node dùng chung, làm sao Node đó biết phải lấy dữ liệu ở Database nào?
3. Tenant Context Service (TCS): "Danh bạ" linh hồn của hệ thống#
Thay vì đập đi xây lại (rewrite) hàng triệu dòng code legacy của Jira để ứng dụng tự nhận biết database, Atlassian chọn một cách tiếp cận thông minh hơn: Tạo ra một lớp Abstraction (trừu tượng) ở giữa mang tên Tenant Context Service (TCS).

Quy trình diễn ra như sau:
- Trình duyệt gửi request tới Compute Node.
- Compute Node tạm dừng, gửi một câu hỏi nội bộ cho TCS: "Khách này là ai? Cấu hình ra sao? Kết nối Database số mấy?"
- TCS trả về thông tin kết nối.
- Compute Node dùng chuỗi kết nối đó để chọc thẳng vào Database của riêng khách hàng đó.
Tuy nhiên, TCS lúc này trở thành "yết hầu" của hệ thống. Để gánh 30.000+ request mỗi giây, TCS không thể chỉ là một database thông thường.
4. Giải quyết bài toán CAP bằng CQRS và AWS SNS#
TCS cần 2 thứ mâu thuẫn nhau: Dữ liệu phải luôn chính xác (Consistency) nhưng tốc độ đọc phải chớp nhoáng (Availability). Atlassian giải quyết bằng mô hình CQRS (Tách biệt Đọc - Ghi):
- Luồng Ghi (Single Source of Truth): Mọi thay đổi cấu hình được ghi vào DynamoDB ở một Region trung tâm. Đảm bảo tính chính xác tuyệt đối.
- Luồng Đọc (Phân tán toàn cầu): Atlassian đặt các "Bản sao TCS" (TCS Clusters) ở tất cả các trung tâm dữ liệu (Mỹ, Châu Âu, Châu Á...). Tại đây, TCS trả lời Compute Node bằng cách đọc trực tiếp từ Cache nội bộ (Redis/Memcached) ở tốc độ chưa tới 1 mili-giây.
Bài toán Cache Invalidation (Xóa cache khi có dữ liệu mới): Khi DynamoDB có dữ liệu mới, làm sao để hàng ngàn TCS Node trên thế giới tự cập nhật Cache? Atlassian dùng AWS SNS (Simple Notification Service). Ngay khi có thay đổi, một Event được "bắn" lên không trung. Toàn bộ các TCS Node đang lắng nghe sẽ bắt được Event này và tự động gạch bỏ dữ liệu cũ trong Cache của mình.
5. Bức tranh toàn cảnh: Hành trình 1 giây của gói tin toàn cầu#
Để mọi thứ hoạt động trơn tru, hạ tầng mạng phía trước cũng phải cực kỳ tinh vi. Hãy xem hành trình thực tế của một nhân viên ở Pháp truy cập vào Jira:

- Phân giải GeoDNS: Máy tính tại Pháp hỏi DNS Resolver (của nhà mạng). Resolver mang thông tin dải IP (ECS) đi hỏi GeoDNS của Atlassian. GeoDNS trả về IP Anycast của điểm biên gần nhất ở Châu Âu.
- Cổng kiểm duyệt biên (Edge & WAF): Gói tin đi vào Global Load Balancer của AWS tại Paris. Tại đây nó bị quét bởi tường lửa (WAF) để chống DDoS.
- Chạy trên đường cao tốc: Gói tin an toàn được đưa vào mạng cáp quang nội bộ của AWS, lướt thẳng đến Regional Load Balancer tại trung tâm dữ liệu Frankfurt (Đức).
- Xử lý Stateless: Regional Load Balancer chia gói tin cho một Compute Node đang rảnh rỗi.
- Truy vấn TCS: Compute Node gọi TCS Cluster tại Frankfurt (mất 1ms) để lấy thông tin Database.
- Lấy dữ liệu & Trả về: Compute Node lấy dữ liệu từ Database, gói lại và gửi trả về Pháp theo con đường cũ.
Tất cả diễn ra trong nháy mắt!
Lời kết#
Hành trình của Atlassian để lại một bài học System Design sâu sắc: Scale (mở rộng) không chỉ là vứt thêm tiền mua server.
Scale là câu chuyện về việc quản lý trạng thái (State), cách chia tách dữ liệu và định tuyến thông minh. Thay vì đập bỏ hệ thống Legacy, họ đã thêm những lớp Abstraction đúng chỗ (như TCS) để mang lại sức sống Cloud-native cho những cỗ máy cũ kỹ.
Một kiến trúc tốt cho 1.000 user chưa chắc đã trụ được với 100.000 user. Quyết định tái kiến trúc đúng thời điểm chính là chìa khóa định đoạt sự thành bại của một nền tảng SaaS quy mô toàn cầu.
Bạn nghĩ sao về mô hình này của Atlassian? Hãy để lại bình luận và thảo luận bên dưới nhé!
