Navigating the Spark 3 and EMR 6 Upgrade Journey at Slack
Bài tóm tắt Slack 2024 4. Điều chỉnh Độ khó: Trung bình
Slack · 2024 · 4. Điều chỉnh · Độ khó: Trung bình — bài gốc
Bối cảnh
- Data Engineering của Slack (2024): mô hình liên bang hơn 60 cụm EMR phục vụ hơn 40 team, hàng nghìn DAG Airflow. Dữ liệu trên S3, metadata trong Hive Metastore (trên RDS); phần lớn là SQL, một số Scala/PySpark; Airflow nộp job qua Livy bằng operator tự viết.
- Mọi workload chạy trên EMR 5.36, Spark 2.4.8, Hive 2.3.9. Khối lượng dữ liệu tăng làm pipeline quan trọng thường xuyên trễ SLA (gồm dữ liệu billing và usage của khách).
- Lý do nâng: hiệu năng (Adaptive Query Execution cho dataset lệch), bảo mật (log4j mới), chi phí.
Thay đổi chính
- Dự án một năm, hai pha: nâng EMR 5 → 6, rồi Hive 2/Spark 2 → Spark 3.
- Chọn một engine: khách nội bộ muốn Hive 3 (ít sửa code), nhưng họ gom về Spark 3 để dùng AQE, dồn chuyên môn vào một engine và tinh chỉnh cụm chỉ cho Spark.
- Chạy song song EMR 5 và EMR 6 suốt thời gian migrate để team không phải dừng roadmap. Năm câu hỏi phải trả lời:
- Catalog chung: nâng Hive Metastore 2.3 lên 3.1 bằng Hive Schema Tool (có backup, có downtime xử lý job lúc nâng schema); HMS 3 tương thích ngược nên cả hai thế hệ cụm dùng chung một catalog.
- Cấp cụm: một cấu hình JSON gốc cho mọi cụm, ghi đè theo cụm; cụm EMR 6 mới bật autoscale với mức tối thiểu thấp; thu dần fleet EMR 5, nới dần fleet EMR 6 theo mức dùng để giữ chi phí.
- Build hai phiên bản: Bazel dựng song song JAR cho Spark 2 và Spark 3 (
--config=spark3), mọi thay đổi cấu hình áp vào cả hai. - Định tuyến job: operator Airflow thêm một cờ boolean chọn cụm cũ hay mới, đổi là xong; thêm bốn cỡ cấu hình Spark (SMALL, DEFAULT, LARGE, EXTRA_LARGE) để người quen Hive migrate mà không cần hiểu cấu hình Spark.
- Sửa code: phần lớn chạy được nguyên. Ngoại lệ:
RAND()trong khoá join để chống lệch dữ liệu bị Spark 3 cấm, nên bỏ hết code tự xử lý lệch và để AQE lo; một số ép kiểu cầnstoreAssignmentPolicy=Legacy; lệch giữa schema Parquet và metastore gâyStackOverflowError, tắtconvertMetastoreParquet. - Kiểm chứng dữ liệu khớp chính xác, không lấy mẫu (dữ liệu billing): chạy bản Spark 3 ghi vào schema test với đúng dữ liệu production, so bằng
EXCEPTvàCOUNTtrên Trino, lệch thì phân tích bằng framework Python nội bộ. Nguồn lệch giả: cột timestamp hiện tại (loại khỏi so sánh),ORDER BYkhông phân định được khi hoà (sửa code), hàm dựng sẵn khác hành vi vớiNULLnhưGREATEST(sửa theo logic nghiệp vụ đúng).
Kết quả (theo Slack)
- Phần lớn task Airflow nhanh hơn 30–60%, có job tới 90% (đo bằng cột
durationtrong DB metadata của Airflow). - AQE: tự xử lý join lệch, tự gộp shuffle partition (ví dụ 3.000 còn 348). S3-optimized committer của EMR 6 chữa lỗi ghi thiếu và trạng thái SUCCESS sai với format dạng text, bỏ được bước list/rename trên S3.
- Không gây sự cố nào trong toàn bộ quá trình; mở đường cho Iceberg/Hudi.
Vì sao
- Chạy hai thế hệ song song với catalog chung và một cờ định tuyến cho phép migrate từng job, quay lại từng job (Migration không downtime).
- Engine mới tự làm việc mà code cũ phải tự xoay (xử lý lệch, chọn số partition), nên migration cũng là dịp xoá code (Pipeline dữ liệu và analytics).
Bài học cho SWE
- Tìm chỗ dùng chung giữa hai thế hệ (catalog) và nâng nó trước, tương thích ngược; còn lại để chạy song song.
- Ẩn cấu hình phức tạp sau vài cỡ đặt sẵn để người dùng tự migrate được.
- Với dữ liệu quan trọng, so khớp chính xác toàn bộ; liệt kê sẵn các nguồn lệch không phải lỗi (thời gian, thứ tự khi hoà, NULL).
- Đo trước và sau bằng metadata có sẵn của bộ điều phối.
Liên quan
#Spark 3#EMR 6#Hive#Hive Metastore#Airflow#Bazel#Adaptive Query Execution#Data validation#Trino#Migration
Được nhắc tới trong
Công ty (1)