Maxjourney: Pushing Discord's Limits with a Million+ Online Users in a Single Server

Bài tóm tắt Discord 2023 3. Quy mô lớn Độ khó: Nâng cao

Discord · 2023 · 3. Quy mô lớn · Độ khó: Nâng cao — bài gốc

Bối cảnh

  • Mỗi server (guild) là một process Elixir làm điểm định tuyến trung tâm; mỗi client kết nối là một process session. Guild fan-out mọi hành động tới session, session đẩy qua websocket.
  • Công việc tăng theo bình phương số người online: hoạt động tỉ lệ với số người, và mỗi tin cũng phải gửi tới số người đó (1.000 người mỗi người nói một câu = 1 triệu thông báo; 100.000 người = 10 tỉ).
  • Midjourney (2023): hơn 10 triệu thành viên, hơn 1 triệu online cùng lúc trong một guild.

Thay đổi chính

  • Đo trước: lấy stack trace của process theo chu kỳ; đo số lượng và thời gian từng loại message trong vòng xử lý của guild để bỏ qua các thao tác dưới 1% tổng thời gian; thư viện ước lượng bộ nhớ heap bằng lấy mẫu map/list lớn.
  • Passive session: user ít khi mở guild thì không nhận mọi tin cho tới khi bấm vào; khoảng 90% kết nối user-guild trong guild lớn là passive, cắt 90% việc fan-out (nhưng giảm 10 lần việc chỉ nới khoảng 3 lần kích thước guild tối đa, vì công việc tăng bình phương).
  • Relay: tầng giữa guild và session chia việc fan-out ra nhiều process/máy, đưa lên hàng trăm nghìn thành viên. Ban đầu mỗi relay giữ toàn bộ danh sách thành viên; ở quy mô Midjourney thì hàng chục bản sao hàng chục triệu thành viên trong RAM và tạo relay mới làm guild đứng hàng chục giây, nên chỉ gửi phần thành viên relay cần.
  • ETS + worker process: danh sách thành viên để trong ETS (bảng bộ nhớ dùng chung giữa process), heap guild chỉ giữ tập thay đổi gần đây; thao tác duyệt mọi thành viên (ping @everyone, chuyển guild sang máy khác khi deploy) chạy ở worker, cắt nhiều phút đứng mỗi lần handoff.
  • Manifold offload: để process "sender" riêng làm fan-out tới node khác. Bật lên lại chậm hẳn: erlang.trace cho thấy GC toàn phần liên tục bị kích hoạt bởi virtual binary heap (thu hồi vài trăm KB mà phải chép heap nhiều GB). Tăng min_bin_vheap_size lên vài MB thì hết, và offload mới cho lợi ích.

Vì sao

  • Một guild cần cái nhìn toàn cục (danh sách voice, member list) nên không chia guild thành nhiều process; phải đẩy việc ra quanh nó và giữ process trung tâm luôn rảnh.

Bài học cho SWE

  • Khi chi phí tăng bình phương, giảm hằng số (passive) chỉ mua thời gian; cần đổi kiến trúc (relay).
  • Tối ưu "làm ít việc hơn" có thể chậm hơn vì tác dụng phụ ở runtime (GC); cần công cụ trace đến tận nguyên nhân kích hoạt.
  • Tách thao tác hiếm nhưng dài ra khỏi vòng xử lý chính để giữ độ phản hồi, không chỉ thông lượng.

Liên quan