Multi-tenancy và cô lập tenant

Chủ đề Dành cho thành viên
Bài đọc thử: 1/3 · còn 2 bài miễn phí · Xem gói thành viên

Bài toán

Một hệ phục vụ nhiều khách (tenant: workspace, shop, organization, account, service nội bộ) trên cùng hạ tầng thì rẻ và dễ vận hành, vì tài nguyên được dùng chung. Cái giá là bốn câu hỏi đi theo hệ suốt đời:

  1. Chia dữ liệu theo tenant đến mức nào: cột tenant_id trong bảng chung, schema/DB riêng trên máy chung, hay cả bộ hạ tầng riêng.
  2. Noisy neighbor: tải theo luật luỹ thừa, một tenant lớn hay một lần import làm chậm hoặc làm sập phần của mọi tenant khác.
  3. Định tuyến: mọi request phải biết "tenant này ở đâu", và nơi trả lời câu hỏi đó thành phụ thuộc cứng.
  4. Đổi tenancy khi khách lớn lên: tách tenant lớn ra, gộp tenant nhỏ lại, dời tenant giữa shard/region mà không downtime.

Trang này gom các lời giải xuyên tầng (DB, queue, search, compute, metrics). Phần chọn khoá shard nói chung ở Sharding và tách database; phần tải lệch và hot key ở Hot partition và thundering herd; rate limit và cắt tải ở Load shedding, rate limit và backpressure.

Diễn tiến theo thời gian

  • 2012 · Zillow: hàng chục tới hàng trăm nghìn website môi giới chạy chung một lõi WordPress tự host; tenant được ánh xạ tới server cache và DB server cố định theo hash. Zillow 2012
  • 2015 · Yahoo: BookKeeper/Pulsar làm messaging đa tenant cho hơn 60 ứng dụng (thông báo mobile, Weather, quảng cáo Gemini...). Việc còn treo trong bài: cô lập tenant khi đọc nặng. Hệ messaging dùng chung sớm muộn gặp bài toán này. Yahoo 2015
  • 2015 · Two Sigma: một cụm compute cho cả job interactive và batch của nhiều researcher; Cook dùng công bằng theo Cumulative Resource Share (ưu tiên trong một user thì dễ, dựng thứ tự toàn cục từ đó) + preemption; replay trace 7 ngày: interactive nhanh lên, utilization giảm dưới 2% (bài 2016). Two Sigma 2016
  • 2016→2019 · LinkedIn (Brooklin): thay hàng trăm cụm Kafka MirrorMaker (mỗi cặp cụm một cụm) bằng cụm Brooklin multitenant: mỗi pipeline cấu hình, pause, cấp tài nguyên riêng; lỗi cô lập tới mức partition và tự resume. LinkedIn 2019
  • 2017 · Slack: dữ liệu shard theo team; sản phẩm Enterprise Grid thêm cấp organization phía trên nên phải có shard theo organization và một khung migrate dữ liệu từng khách (handler validate/transform/insert idempotent, queue và worker riêng, dùng lại rate limiter cho chính migration). Khoá tenant gắn với khái niệm sản phẩm; sản phẩm thêm cấp thì đổi ID lan khắp nơi. Slack 2017
  • 2018 · Shopify: pod = một tập shop trên một bộ datastore cô lập hoàn toàn; app server dùng chung nhưng mỗi request chỉ chạm một pod, cấm thao tác xuyên pod. Sorting Hat ở load balancer định tuyến theo shop; Pod Mover dời pod sang data center khác trong khoảng một phút. Theo Shopify, shard mà vẫn lặp qua mọi shard thì không cô lập được lỗi. Shopify 2018
  • 2018 · Segment: một queue mỗi đích thì khách lớn (50.000 message dồn liền) chặn khách nhỏ hoặc kéo retry; Centrifuge dùng MySQL làm queue với queue ảo theo (khách, đích), để một cặp hỏng không giữ hàng của cặp khác. Segment 2018
  • 2019 · Atlassian: Jira giữ một DB mỗi tenant (nhiều DB trên một RDS), tenant gom thành shard rải nhiều region để thu nhỏ blast radius và tránh noisy neighbor. Ánh xạ tenant → vị trí gom vào Tenant Context Service, về sau thành dịch vụ metadata tenant cho toàn Atlassian Cloud, nên phải thiết kế khắt khe nhất. Atlassian 2019
  • 2019 · LinkedIn (Nuage): quota giữa service cấu hình qua Nuage, thư viện thực thi trong router/app server cache quota và nhận cập nhật tức thì qua ZooKeeper; throttle theo số request hoặc chi phí request. LinkedIn 2019
  • 2019 · LinkedIn (YARN): gộp compute cụm phụ (MapReduce churn nhanh) vào cụm chính (Spark dài) làm Capacity Scheduler kẹt ở queue "ít dùng", job chờ hàng giờ; vá bằng chọn queue ngẫu nhiên đều (YARN-9770), sửa gốc bằng chỉ xét ứng dụng cùng partition với node (YARN-9730). LinkedIn 2021
  • 2020 · Slack: chiều ngược với Shopify. Shard theo workspace dễ làm nhưng tạo hot spot với khách lớn và chặn tính năng xuyên khách; lên Vitess thì đổi khoá shard theo dữ liệu (tin nhắn theo channel). Slack 2020
  • 2020 · LinkedIn (Rain): noisy neighbor không do tài nguyên cạn: trên kernel mới, app deploy cùng máy làm p99 của app khác tăng vì hồi quy ext4 với I/O tuần tự đồng thời trên HDD. LinkedIn 2020
  • 2020→2023 · Zillow: Spark tốn hơn 15% ngân sách cloud cho hơn 13.000 job; ZACS dùng YuniKorn đặt giới hạn theo team trên cụm chung để team nào cũng có capacity dự đoán được. Zillow 2023
  • 2021 · Wix: Velo chạy code của hàng triệu site; phân bố đuôi dài làm "một container cho mỗi tenant" quá đắt. Pool pod ấm dùng chung, gắn tạm theo tenant khi có request là điểm giữa giữa cold start và giữ máy cho tenant nhàn rỗi. Wix 2021
  • 2022 · DoorDash: dùng tenancy cho việc khác: tenant DoorTest trong production để chạy E2E test. Giá trị tenant hai cấp <L0:L1> truyền qua mọi hop bằng OpenTelemetry baggage; L0 cô lập vật lý (DB riêng), L1 cô lập logic (cột tenant-id); CDN xoá header test nếu IP không thuộc VPN. DoorDash 2022
  • 2022 · Meta: ACS (xác thực ẩn danh) là dịch vụ multi-tenant: mỗi request ghi tên use case, mỗi use case có khoá riêng để token cấp cho use case này không đổi được ở use case khác; mỗi use case tự đặt giới hạn dùng lại credential (bộ đếm trên ZippyDB). Meta 2022
  • 2023 · Notion: reshard 32 → 96 DB theo workspace; CPU và IOPS giảm nhưng shard nhỏ hơn làm workspace ngoại lai lộ rõ hơn. Chia đều không giải được tenant khổng lồ. Notion 2023
  • 2023 · Deno: Deno KV trên FoundationDB phải tự thêm cấu hình theo tenant (replication, backup, quota) mà FoundationDB không có sẵn. Cùng năm, một DDoS vào một deployment trên Deno Deploy: cô lập giữa deployment giữ các tenant khác sống, còn phần tự co giãn cho deployment bị dội tải thì không theo kịp. Deno 2023 Deno 2023
  • 2023 · Stack Overflow: Teams dùng DB Sites làm nền multi-tenancy, mỗi DB khoảng 1.000 Team. Khi lên Azure, Elasticsearch dùng một filtered alias mỗi Team để không khách nào đọc được dữ liệu khách khác; số alias quá lớn làm chậm một API và node master chết. Cách cô lập theo tenant có thể chạm giới hạn ẩn của hệ bên dưới. Stack Overflow 2023
  • 2024 · Deno: Deploy/Subhosting chạy code không tin cậy của user của khách trên V8 isolate. Threat model 5 nguyên tắc (tenant chỉ chạm runtime và dữ liệu của mình, không chiếm tài nguyên isolate khác...), nhiều lớp namespaces/cgroups/seccomp cộng "watch dog" giết tenant đáng ngờ khi các lớp kia bị vượt. Deno 2024
  • 2024 · Neon: cực còn lại của trục: database-per-user, mỗi khách một môi trường gần như single-tenant. Không phải định tuyến query tới đúng DB, độ phức tạp dồn sang provisioning và deploy. Theo Neon, đây không còn là multi-tenancy và chỉ đáng khi quy định hoặc nhịp nâng cấp bắt buộc. Neon 2024
  • 2024 · Stripe: Data Movement Platform biến tách shard, bin-pack shard dùng ít, nâng phiên bản và chuyển khách lớn từ multi-tenant sang tenant riêng thành cùng một thao tác trực tuyến (cutover dưới 2 giây bằng versioned gating). Stripe 2024
  • 2024 · Inngest: queue đa tenant; tháng 10/2024 shard queue chính quá tải CPU, họ xây công cụ dời account giữa shard, thử với account của chính mình rồi chuyển khách theo lô. Inngest 2024
  • 2024 · WarpStream: đo usage để tính tiền ngay ở đường nóng: mỗi kết nối tự đếm, gom theo tenant trong aggregator cùng node, nên số event là O(số tenant × số node), không tỉ lệ với lưu lượng. Chấp nhận tính thiếu khi mất node. WarpStream 2024
  • 2025 · CockroachDB: vector index có cột tiền tố tenant (ví dụ user_id): mỗi tenant một cây K-means riêng, chi phí ghi/tìm tỉ lệ với dữ liệu của tenant đó, và index theo tenant cũng là ranh giới an toàn; ghép REGIONAL BY ROW để dữ liệu ở region nhà. Cockroach Labs 2025
  • 2025 · Cloudflare: Tenant Service nằm trong logic phân quyền của mọi API request; một bản deploy chồng với bug ở dashboard làm nó quá tải, API và dashboard sập, bản vá làm sập đợt hai. Service metadata tenant là phụ thuộc cứng, đúng điều Atlassian 2019 cảnh báo. Cloudflare 2025
  • 2025 · HRT: chống noisy neighbor bằng giới hạn concurrency hoặc cấp hẳn hệ lưu trữ riêng cho team để lại dung lượng và băng thông chết; một filesystem dùng chung (Blobby) thiết kế cho thông lượng tổng hợp, có rate limit ở proxy. Hudson River Trading 2025
  • 2026 · Inngest: queue trên Valkey: một tenant đầy backlog làm hết RAM là cả cụm sập. Chuyển sang FoundationDB để dữ liệu nằm trên đĩa, công bằng theo key để tenant ồn không bỏ đói tenant khác; shard theo nhóm tenant (bậc giá free/self-serve/enterprise) với bảng ánh xạ có cache. Theo Inngest, "một tenant làm sập cả cụm" là lỗi thiết kế. Inngest 2026 Inngest 2026
  • 2026 · Salesforce: rate limit theo từng instance không thấy tổng tải của một khách trên fleet autoscale, nên một khách tăng đột biến ảnh hưởng khách khác. Thay bằng quota toàn cục không coordinator: server chia sẻ mức dùng của từng khách, mỗi server tự throttle. Salesforce 2026
  • 2026 · Uber: quản lý tải DB tách hai bài toán chạy song song: bảo vệ hệ khi quá tải (theo ưu tiên) và công bằng giữa tenant khi khoẻ (Scorecard: giới hạn concurrency theo tenant, tất định, chạy cả lúc hệ khoẻ). Uber 2026
  • 2026 · Airbnb: metrics storage multi-tenant với tenant theo service (khoảng 1.000), không theo team vì quyền sở hữu team hay đổi; shuffle sharding (mỗi tenant chỉ ghi vào một tập con node, query dùng một tập con worker); control plane tự onboard và suy các giới hạn từ vài tham số. Chia nhiều cụm để giảm blast radius thì query liên cụm đắt gấp 5–10 lần. Airbnb 2026
  • 2026 · Atlassian: OpenSearch hơn 300 cụm, có cả cụm dùng chung và cụm theo tenant; tách tenant lớn khỏi index dùng chung là thao tác thường xuyên nên phải rẻ, và routing key theo tenant làm phức tạp reindex. Ở hệ webhook, một lần import CSV 10.000 issue sinh nhiều event hơn cả tuần bình thường của tenant đó; rate limit theo app và theo tenant, hết bucket thì hoãn chứ không bỏ. Theo Atlassian, công bằng phải được thiết kế sẵn, không "lớn dần lên" sau mỗi sự cố. Atlassian 2026 Atlassian 2026
  • 2026 · Upstash: một tiến trình chứa hàng nghìn DB, mỗi DB nhiều index; mô hình thread mặc định của Tantivy (nhiều thread cho mỗi index) không scale, nên fork tối thiểu để writer chạy foreground trên goroutine của index. Upstash 2026
  • 2026 · Notion: workspace ID là khoá định tuyến và phân vùng chính từ 2021, nên data residency EU chỉ là thêm một "mạng cô lập" mới; bảng ánh xạ workspace → region là nguồn sự thật khi dời workspace. Notion 2026
  • 2026 · HRT: WAN giữa các site là tài nguyên chung; quy byte cho từng user/workflow bằng eBPF + log dịch vụ để tự động throttle workflow làm bão hoà mạng. Hudson River Trading 2026

Các lựa chọn và đánh đổi

Trục chia dữ liệu theo tenant (từ dùng chung nhất tới cô lập nhất):

Mức Ví dụ Được Mất
Cột tenant_id trong bảng chung DoorDash L1, Stack Overflow Sites Rẻ nhất, thêm tenant không tốn gì Một query quên lọc là lộ dữ liệu; noisy neighbor ngay trong bảng
Index/alias/schema theo tenant Neon schema, Stack Overflow alias, CockroachDB vector index Ranh giới rõ, chi phí theo kích thước tenant Số đối tượng tăng theo số tenant, chạm giới hạn ẩn
Shard/pod theo nhóm tenant Shopify pod, Notion, Inngest, Atlassian Jira Blast radius nhỏ, scale ngang, dời được Tenant khổng lồ vẫn không vừa một shard; thao tác xuyên tenant khó
DB/cụm riêng cho tenant Neon database-per-user, Stripe tenant riêng, Atlassian cụm OpenSearch riêng Cô lập nhất, đáp ứng quy định Đắt, độ phức tạp dồn sang provisioning và deploy

Các cách chống noisy neighbor:

  • Giới hạn theo tenant (concurrency, series, rate): Uber Scorecard, Airbnb guardrail, Atlassian bucket theo tenant. Phải nhìn tổng tải toàn fleet, không theo từng instance (Salesforce).
  • Hàng đợi/công bằng theo key: queue ảo (Segment), key queue (Inngest). Đổi lại phải có DB/queue hỗ trợ đổi thứ tự.
  • Shuffle sharding: mỗi tenant một tập con tài nguyên ngẫu nhiên (Airbnb), lỗi của một tenant chỉ hạ vài node.
  • Tách tenant lớn ra: Atlassian, Stripe. Cần một công cụ dời dữ liệu trực tuyến; không có thì đây là dự án mỗi lần.
  • Đổi khoá shard khỏi tenant: Slack 2020. Hết hot spot theo khách nhưng mất cô lập theo khách.

Pool dùng chung hay đơn vị riêng cho compute: pool ấm gắn tạm (Wix), isolate trong tiến trình chung (Deno), thread do runtime chung điều phối (Upstash) đều chọn dùng chung để trả theo nhu cầu chứ không theo số tenant.

Quy tắc rút ra

  1. Đặt khoá tenant theo thứ ổn định (service, workspace, organization), không theo thứ hay đổi như team (Airbnb 2026). Sản phẩm thêm cấp tenant mới thì phải trả bằng một đợt migrate ID (Slack 2017).
  2. Mỗi request chỉ chạm một đơn vị cô lập. Thao tác lặp qua mọi shard phá cô lập lỗi (Shopify 2018).
  3. Công bằng giữa tenant phải thiết kế từ đầu, và chạy cả khi hệ khoẻ, tách khỏi cơ chế cắt tải lúc quá tải (Uber 2026, Atlassian 2026). "Một tenant làm sập cả cụm" (OOM) là lỗi thiết kế (Inngest 2026).
  4. Service ánh xạ tenant → vị trí là phụ thuộc cứng của mọi request: cache ở client, deploy có tự rollback, cấp dư năng lực (Atlassian 2019, Cloudflare 2025).
  5. Dời tenant phải là thao tác thường ngày: tách khách lớn, gộp khách nhỏ, dời giữa shard/region đều đi qua cùng một công cụ trực tuyến, thử với tenant nội bộ trước (Stripe 2024, Inngest 2024, Atlassian 2026).
  6. Ngữ cảnh tenant truyền qua mọi hop (header → baggage) và được kiểm ở biên; cùng cơ chế dùng được cho test trong production và data residency (DoorDash 2022, Notion 2026).
  7. Chạy code lạ thì cần nhiều lớp cách ly cộng một cơ chế phát hiện và giết ở cuối (Deno 2024).
  8. Đo theo tenant ở đường nóng thì gom theo tenant trước khi gửi, để chi phí đo tỉ lệ với số khách chứ không với lưu lượng (WarpStream 2024).

Câu hỏi mở

  • Shard theo tenant hay theo dữ liệu? Shopify 2018 giữ pod theo shop để cô lập lỗi; Slack 2020 bỏ shard theo workspace vì hot spot và tính năng xuyên khách. Bài Shopify không nói cách xử lý shop rất lớn trong một pod; chưa có nguồn so hai hướng trên cùng một hệ.
  • Tenant khổng lồ: Notion 2023 chỉ ra resharding đều không giải được; Atlassian và Stripe tách ra cụm/tenant riêng. Ngưỡng nào thì tách, và ai trả chi phí (giá theo bậc như Inngest)? Chưa có nguồn nêu tiêu chí định lượng.
  • Giới hạn ẩn khi số tenant lớn: alias Elasticsearch (Stack Overflow), thread mỗi index (Upstash). Cách phát hiện trước khi chạm, ngoài shadow cluster với traffic thật như Airbnb?
  • Chargeback: Airbnb nói tenant theo service mở đường cho chargeback, WarpStream tính tiền theo usage; chưa có nguồn về chargeback nội bộ đã chạy và tác động lên hành vi team.
  • Cô lập tenant trong lúc đọc nặng ở hệ messaging (Yahoo 2015 để ngỏ) đã được giải thế nào ở Pulsar về sau? Chưa có nguồn.
  • Liên hệ: Sharding và tách database (chọn khoá shard nói chung), Hot partition và thundering herd (tenant lớn là một dạng hot key), Load shedding, rate limit và backpressure (giới hạn theo tenant), Độ tin cậy và multi-region (cell, data residency), Migration không downtime (dời tenant), Xác thực và phân quyền (authn/authz).