Scaling Our Geo-Search Service For 10x Load
Bài tóm tắt Gojek 2022 2. Tăng trưởng Độ khó: Trung bình
Gojek · 2022 · 2. Tăng trưởng · Độ khó: Trung bình — bài gốc
Bối cảnh
- Available Driver Service (ADS) trả lời: "quanh vị trí này, tài xế nào thoả điều kiện?" (ví dụ xe có nước rửa tay). ADS sập thì không phân được tài xế cho đơn.
- Ban đầu trên Postgres: tài xế gửi vị trí vài giây một lần, mỗi lần cập nhật lại phải re-index, không chịu nổi tải ghi. Chuyển sang Redis, nhưng trần chỉ khoảng 10.000 request/phút. GoRide dùng một hệ khác; khi GoFood và Logistics lớn lên thì ngày nào cũng có cảnh báo vi phạm SLA.
- Thundering herd: hệ gọi ADS retry mỗi 15 giây, lúc cao điểm kéo sập toàn bộ hệ khoảng một giờ.
Đánh đổi
- Vị trí cũ vài giây không sao; có một vài tài xế còn hơn không có ai. Theo PACELC, ADS chọn PA/EL: khi phân mảnh mạng thì ưu tiên availability, bình thường thì ưu tiên latency hơn consistency. Tức là đổi tính đầy đủ và độ chính xác lấy availability và latency thấp.
Thay đổi chính
- Tách đọc/ghi trên Redis Cluster (multi-master, mỗi master một shard, nhiều replica). Lọc geo chạy bằng Lua
EVAL, nhưngEVALkhông được coi là lệnh chỉ đọc nên bị đẩy hết về master, và client go-redis mặc định cũng vậy. Gojek đề xuấtEVAL_RO/EVALSHA_ROcho Redis và được chấp nhận (script có lệnh ghi thì lỗi an toàn), đồng thời đóng góp vào go-redis để tạm gọi replica bằngEVAL. - Mỗi query đi tới nhiều node: chia một query láng giềng gần nhất thành nhiều query vùng nhỏ, chạy song song trên các replica khác nhau. Một node chậm hay chết vẫn có node khác trả về. Chia vùng nhỏ còn giúp trộn vùng cao điểm với vùng ít tải khi chia shard, tránh hot shard.
- Best effort search: đặt timeout cho query; hết giờ thì trả những tài xế đã lấy được, không chờ node chậm. Phần lớn node đạt SLA p99.99.
Kết quả (theo Gojek)
- Cao điểm 600.000 lượt ghi/phút và 200.000 lượt tìm/phút; tăng capacity chỉ cần thêm node (trước chỉ scale dọc được). ADS trở thành thứ "mọi người mặc định là chạy".
- Việc tiếp theo: autoscale replica Redis (đang chỉnh tay) vì cao điểm chỉ vài giờ mỗi ngày.
Bài học cho SWE
- Dữ liệu ghi liên tục, đọc chấp nhận cũ (vị trí) không hợp với index của RDBMS (Chọn database theo workload).
- Đẩy đọc sang replica cần cả server lẫn client hiểu lệnh nào là chỉ đọc (Scale dọc trước khi scale ngang).
- Scatter-gather kèm timeout và trả kết quả một phần: hợp với API "luôn có dữ liệu, không cần đủ".
- Retry cố định mỗi 15 giây của client là nguồn thundering herd (Hot partition và thundering herd).
Liên quan
- Tinder 2019 (cũng chia shard theo vùng địa lý, cân bằng theo tải thay vì theo diện tích)
- Scale dọc trước khi scale ngang · Hot partition và thundering herd · Chọn database theo workload
Được nhắc tới trong
Chủ đề (3)
Công ty (1)
Bài tóm tắt (1)