How We Improved Our Performance Using ElasticSearch Plugins: Part 1
Bài tóm tắt Tinder 2019 3. Quy mô lớn Độ khó: Khó
Tinder · 2019 · 3. Quy mô lớn · Độ khó: Khó — bài gốc
Phần 1 trong hai bài; phần 2 (9/2019): Tinder 2019.
Bối cảnh
- Hệ gợi ý của Tinder lưu document người dùng trong Elasticsearch (6.3); mỗi lượt lấy gợi ý là một query lọc rồi sắp theo hàm relevance viết bằng Painless script.
- Khi đưa thuật toán ML vào (nhiều feature hơn), query chậm hẳn. Painless có giới hạn cứng 16.384 ký tự mà script đã gần chạm; tách nhỏ script thì chậm hơn. Painless không có biến/hàm static, nên một mảng hằng phải dựng lại cho mỗi document được chấm, tốn cấp phát và GC.
- Plugin Java nhanh hơn, nhưng mỗi lần cập nhật plugin phải khởi động lại cả cụm: đắt và giảm độ tin cậy.
Thay đổi chính
- Script plugin tự nạp lại lúc chạy: ScriptEngine không trực tiếp chứa thuật toán mà thành lớp định tuyến: dựa vào tên + phiên bản trong trường
sourcecủa query, lấy factory tương ứng từ cache (Guava LoadingCache, có eviction cho script lâu không dùng). - ClassLoader tự viết tải class từ file jar trên kho lưu trữ, ghi đè định nghĩa cũ (class phụ thuộc cũng được thay), nên thuật toán mới lên không cần restart. Lý do cần cache: tải jar không chịu nổi vài nghìn QPS.
- Tách phần tính một lần mỗi query (Factory) khỏi phần tính mỗi document (LeafFactory).
- Đổi hành vi bằng tham số trong query (ví dụ
use_new_algorithm), không cần gắn ES với hệ feature flag. - Observability: không chạy Prometheus trên từng node ES; thêm API
_cat/pluginmetrics(ActionPlugin) theo mẫu_cat/nodes, gọi qua load balancer là ra metric gộp của cả cụm theo định dạng Prometheus. - Bảo mật: jar được ký bằng khoá trong key vault, plugin kiểm chữ ký, repo có protected branch và người duyệt.
- Quy trình phát hành script: (1) staging thử thủ công; (2) cụm canary chép dữ liệu production để bắt dữ liệu lệch schema lịch sử (trường ngày khi là chuỗi ISO, khi là UNIX timestamp); (3) dark run trên production: gửi query fire-and-forget với script mới, giữ vài ngày để lộ lỗi chậm như rò bộ nhớ; (4) tăng dần traffic.
- Kết quả bản đầu (chỉ dịch y nguyên script Painless sang Java): latency từ hơn 500 ms xuống dưới 400 ms.
Vì sao
- Muốn tốc độ của code native mà vẫn đổi thuật toán thường xuyên; với cụm search đang phục vụ, restart là chi phí vận hành lớn nhất.
Bài học cho SWE
- Khi phải chạy code tuỳ biến bên trong cụm search, tách "nạp code" khỏi "vòng đời node" để deploy không đồng nghĩa restart cụm (Hạ tầng tìm kiếm).
- Logic chạy trong hệ dữ liệu cũng cần pipeline phát hành nhiều tầng: canary trên bản sao dữ liệu thật để bắt dữ liệu bẩn, dark run để bắt lỗi hiệu năng chậm lộ (Deploy và release an toàn).
- Bản đầu nên dịch y nguyên để có so sánh công bằng trước khi tối ưu.
Liên quan
- Cùng công ty: Tinder 2019 · Tinder 2019 · Tinder 2019 · Tinder 2022 · Tinder 2019
- Hạ tầng tìm kiếm · Deploy và release an toàn
#Elasticsearch#Plugin#Script engine#Painless#ClassLoader#Hot reload#Recommendation#Dark run#Canary#Prometheus
Được nhắc tới trong
Chủ đề (2)
Công ty (1)
Bài tóm tắt (1)