Cách Roblox sử dụng Theta Sketches để mở rộng phân tích người sáng tạo

Phân tích là yếu tố thiết yếu đối với các trò chơi nhiều người chơi thời gian thực ngày nay. Tại Roblox, chúng tôi tập trung vào việc phát triển các công cụ đo lường để giúp các nhà sáng tạo của chúng tôi phát triển mạnh mẽ. Công cụ phân tích miễn phí, sẵn sàng sử dụng của chúng tôi cung cấp cho các nhà sáng tạo cái nhìn sâu sắc tức thì về sự phát triển, thu hút người dùng và duy trì người dùng của trải nghiệm của họ, giúp họ tối đa hóa thành công.
Xây dựng hệ thống phân tích dữ liệu cập nhật mà hàng triệu nhà sáng tạo Roblox phụ thuộc vào là một thách thức quan trọng. Để giải quyết vấn đề này, chúng tôi đã tối ưu hóa công cụ truy vấn phân tích của mình để một cụm xử lý 120 lõi có thể xử lý hơn 6 triệu truy vấn mỗi ngày từ khoảng 300.000 lượt truy cập hàng ngày, truy cập vào 86 TB dữ liệu. Trái tim của giải pháp của chúng tôi là cơ sở dữ liệu xử lý phân tích trực tuyến (OLAP) mà chúng tôi đã chọn vì khả năng mở rộng và tích hợp với các thuật toán xấp xỉ. Bằng cách kết hợp các kỹ thuật tổng hợp dữ liệu cùng với các thuật toán HyperLogLog và Theta Sketch, chúng tôi cung cấp phân tích cho hàng triệu trải nghiệm Roblox1.
Hướng dẫn cơ bản về phân tích OLAP
Càng nhiều dữ liệu được truy vấn, thời gian để tạo ra kết quả càng lâu. Khi chúng tôi có thể giảm lượng dữ liệu cần thiết và tăng tốc quá trình phân tích, các nhà sáng tạo có thể nhận được thông tin chi tiết gần như theo thời gian thực từ các hành động của họ. Một số kỹ thuật mà chúng tôi sử dụng bao gồm:
- Lưu trữ theo cột: OLAP, Druid, chỉ đọc các cột cần thiết.
- Bộ lọc phân vùng và sắp xếp: OLAP chỉ đọc các tệp có liên quan được lập chỉ mục trực tiếp vào các khối dữ liệu cần thiết.
- Rollup: OLAP tổng hợp một phần các sự kiện bằng cách sử dụng các nhóm chung.
Đặc biệt, tổng hợp (Rollup) cho phép OLAP hoạt động giữa các công cụ truy vấn SQL lớn nhất, như Spark hoặc Presto (với độ trễ hàng chục giây), và truy vấn điểm hoặc SQL giới hạn, vốn thường cung cấp dữ liệu đã được tổng hợp hoàn toàn. Với tổng hợp, các truy vấn được chỉ định theo các nhóm chiều, dẫn đến việc giảm đáng kể tổng số hàng. Khi xem xét hàng tỷ hoặc thậm chí hàng nghìn tỷ sự kiện thô, việc tổng hợp chúng thành hàng triệu nhóm có thể được tổng hợp với độ trễ dưới một giây sẽ hiệu quả hơn nhiều. Ví dụ:

Mặc dù rollup mang lại những lợi thế về giảm thiểu như đã đề cập ở trên, nhưng một số chỉ số nhất định vẫn không thể áp dụng rollup, bao gồm các truy vấn yêu cầu sắp xếp toàn bộ bảng dữ liệu thô, như đếm số lượng khác biệt, phân vị và truy vấn tần suất.
May mắn thay, chúng ta có thể khắc phục những hạn chế này bằng các kỹ thuật trả về kết quả gần đúng có giới hạn thống kê dựa trên các cấu trúc dữ liệu phức tạp chứa mẫu của tập dữ liệu đầy đủ. Các cấu trúc dữ liệu này được thiết kế để sử dụng trong các kỹ thuật tổng hợp và kết hợp hai số đếm riêng biệt thông qua một phép toán hợp nhất, tương tự như việc cộng hai số lại với nhau.
Phân tích khối lượng công việc của Roblox Analytics
Tại Roblox, chúng tôi cung cấp cho các nhà sáng tạo một bảng điều khiển tập trung, nơi họ có thể tìm thấy những thông tin chi tiết quan trọng nhất. Những thông tin này bao gồm:
- Tương tác: người dùng hoạt động hàng ngày (DAU), người dùng hoạt động hàng tháng (MAU), tỷ lệ giữ chân và các kênh chuyển đổi
- Kiếm tiền: doanh thu, doanh thu trung bình trên mỗi người dùng, doanh số bán hàng và nền kinh tế
- Dữ liệu thu hút người dùng
- Tùy chỉnh hình thu nhỏ và kết quả thử nghiệm
- Phân tích đề xuất trên trang chủ
- Và nhiều tính năng khác sẽ được cập nhật.

Chọn và tối ưu hóa công cụ truy vấn
Vượt qua những thách thức về hiệu suất
Trong vòng thử nghiệm sản xuất cuối cùng, chúng tôi đã phát hiện ra một thách thức quan trọng: Hiệu suất truy vấn MAU của chúng tôi cần được cải thiện sau khi chuyển từ các truy vấn lớn đơn lẻ sang các mẫu tổng hợp theo ngày. Những điều này rất quan trọng đối với các biểu đồ phân tích người sáng tạo của chúng tôi.
Chúng tôi nhận thấy rằng cấu trúc của truy vấn ảnh hưởng rất lớn đến hiệu suất cơ bản của giải pháp OLAP của chúng tôi. Các truy vấn tiêu chuẩn với nhiều giai đoạn thực thi (như các câu lệnh “GROUP BY” lồng nhau2) thường đẩy một phần lớn công việc sang các nút trung gian nhẹ.
Đây là một vấn đề điển hình của dữ liệu lớn, trong đó một phần của truy vấn cuối cùng được thực thi trên các nút phục vụ nhỏ quan trọng. Chúng tôi kỳ vọng các cấu trúc dữ liệu xấp xỉ của mình sẽ hoạt động như các phép đếm hoặc tổng đơn giản, nhưng chúng tôi phát hiện ra rằng chúng thực tế hoạt động hoàn toàn khác.
Hình dưới đây minh họa vấn đề này. Nó cho thấy cách các nút lịch sử của chúng tôi thực hiện tổng hợp một phần, tổng hợp một Theta Sketch cho mỗi ngày và sau đó đẩy dữ liệu của chúng trở lại broker. Sau đó, broker cố gắng hợp nhất từng bản phác thảo hàng ngày lớn thành một giá trị hàng tháng duy nhất cho mỗi ngày. Đối với 30 ngày MAU, điều này có nghĩa là phải hợp nhất 1.800 bản phác thảo Theta có kích thước tối đa trên một máy chủ trung gian, dẫn đến truy vấn chậm hơn, dễ gặp lỗi và chiếm dụng CPU của máy chủ trung gian.

Giải pháp của chúng tôi là chạy OLAP với ít công cụ xử lý dữ liệu lịch sử hơn để tối đa hóa tính cục bộ dữ liệu cho các nguồn dữ liệu dựa trên các truy vấn xấp xỉ. Trong thực tế, điều này đã đẩy một hoạt động hợp nhất có thể yêu cầu xử lý hơn 100 MB dữ liệu trở lại các nút lịch sử của chúng tôi.
Để thực hiện điều này trong SQL, chúng tôi đã sử dụng phép nối nội tuyến để các truy vấn truyền thông tin cần thiết đến các nút lịch sử và chuẩn bị một truy vấn với danh sách các ngày kết quả nội tuyến. Sau đó, mỗi ngày kết quả có thể thu thập dữ liệu liên quan từ các phân đoạn nút lịch sử. Dữ liệu sau đó được truyền trở lại nhà môi giới, nơi các kết quả nhanh chóng được hợp nhất thành một bản đồ duy nhất về ngày kết quả với dữ liệu chỉ số, như được thấy bên dưới.

Việc tối ưu hóa này đã có tác động đáng kể đến hiệu suất của các truy vấn quy mô lớn. Đối với phân tích MAU theo quốc gia của một trải nghiệm lớn, hiệu suất truy vấn trung bình đã cải thiện gấp 5 lần (từ 17,53 giây xuống còn 3,23 giây), như thể hiện trong biểu đồ dưới đây. Chúng tôi cũng nhận thấy thời gian CPU trên máy chủ trung gian giảm 50 lần (từ 16,83 giây xuống còn 0,34 giây).
Mặc dù kết quả có thể khác nhau, điều này nhấn mạnh tầm quan trọng của việc xử lý các thao tác phức tạp (như hợp nhất hàng triệu bản phác thảo) một cách cẩn thận. Giả định rằng các thao tác này tương đương với các phép tổng hợp đơn giản có thể dẫn đến các vấn đề hiệu suất nghiêm trọng, đặc biệt trên các hệ thống nơi các phép tổng hợp cuối cùng của client là phổ biến.
Các bản tổng hợp và Hình khối Theta Lý thuyết

Chúng tôi cũng đã nghiên cứu về khối theta, hay một phương pháp tổng quát để thu hẹp khoảng cách giữa các bảng tổng hợp cơ bản và các bảng dữ liệu thô thông qua các giao cắt tập hợp xấp xỉ. Phương pháp này giải quyết một hạn chế cơ bản: Các bảng tổng hợp mất đi lợi thế khi các truy vấn cần truy cập nhiều lớp của các chiều có độ lớn cao. Điều này là do mỗi chiều khiến độ lớn của bảng tổng hợp tăng theo ∏dim (sản phẩm của các chiều).
Chúng tôi đã thiết kế một hệ thống tổng hợp theo các nhóm chiều chung với giới hạn độ lớn, cho phép thực hiện các truy vấn hiệu suất tổng hợp trên bất kỳ đối tượng nào trong nhóm. Sau đó, khi tìm kiếm các kết hợp chiều giữa các nhóm, chúng tôi sẽ thực hiện phép nối xấp xỉ (join4) giữa các tập hợp và trả về kết quả chỉ số cùng với ước tính lỗi. Một truy vấn có ước tính lỗi cao sẽ được chuyển đến bảng dữ liệu thô, nơi các bộ lọc đa dạng cho phép tối ưu hóa đẩy xuống quy mô lớn.


Vì chúng ta có thể tính toán tỷ lệ lỗi này một cách nhanh chóng, nó cũng đóng vai trò như một tín hiệu mạnh mẽ cho thấy việc đọc bảng thô có khả năng sẽ mang lại hiệu suất cao. Trong những trường hợp mà dữ liệu trùng lặp là nhỏ so với tập hợp (ví dụ: những người nói tiếng Nhật ở Đức), một số lượng lớn các hàng trong bảng thô sẽ bị lọc ra. Điều đó dẫn đến các tối ưu hóa đẩy xuống hiệu quả. Một hệ thống sử dụng các nhóm chiều, các phép nối xấp xỉ và việc đọc bảng thô dựa trên lỗi sẽ thực sự tối đa hóa hiệu suất tổng hợp trên các truy vấn thân thiện với xấp xỉ.
Đối với Roblox, giải pháp này sẽ phù hợp hơn ở cấp độ mở rộng tiếp theo của chúng tôi — có thể là cho phân tích kênh chuyển đổi động hoặc sự kiện tùy chỉnh — trong khi bản sao tổng hợp đơn giản hiện tại của chúng tôi đáp ứng được nhu cầu hiện tại.
Xây dựng nền tảng tự phục vụ
Sau khi tối ưu hóa hệ thống trung gian, chúng tôi chuyển sang phát triển các công cụ để tích hợp và truy vấn các bộ dữ liệu được thêm vào giải pháp OLAP của chúng tôi. Chúng tôi đã xây dựng một thư viện UDAF mã nguồn mở cho Spark và Trino dành cho các hàm datasketch, cho phép Spark sử dụng định dạng nhị phân datasketch giống như OLAP6 của chúng tôi. Điều này giúp giữ phần lớn khối lượng công việc tính toán trong Spark và giúp chuẩn hóa việc tính toán xấp xỉ trên toàn Roblox, có khả năng giảm chi phí tính toán tới 80% cho một số bộ dữ liệu nhất định.
Chúng tôi đã đơn giản hóa quá trình tích hợp dữ liệu bằng một tiện ích mở rộng nội bộ cho trình lập lịch công việc hàng loạt và định nghĩa một API theo phong cách DataFrame để hướng dẫn các nhà phát triển xác định các chỉ số và chiều dữ liệu chính xác, từ đó giảm thiểu tác động của các truy vấn mở. Chúng tôi cũng đã mã nguồn mở một số quy trình làm việc mẫu về cách chúng tôi tải và truy vấn dữ liệu này trong giải pháp OLAP của mình.
Các bộ dữ liệu phân tích được tối ưu hóa của chúng tôi hiện đang cung cấp những thông tin chi tiết sâu sắc cho các nhà sáng tạo. Các tối ưu hóa của chúng tôi đã cải thiện hiệu suất trung bình gấp 4 lần và hiệu suất trong trường hợp xấu nhất gấp 50 lần. Nền tảng tự phục vụ cho phép đội ngũ Phân tích Nhà sáng tạo của chúng tôi tiếp tục phát triển các bộ dữ liệu mới cho các nhà phát triển. Chúng tôi rất hào hứng khi thấy các nhà phát triển ở mọi quy mô sử dụng các công cụ này để tạo ra những trải nghiệm tuyệt vời trên Roblox.
1 Được tính toán dựa trên 60 ngày gần nhất của các tập hợp duy nhất có bất kỳ lượt truy cập nào
2 Giống như truy vấn
MAU đơn giản này 3 Kết quả từ ngày 21 đến 28 tháng 3 năm 2025
4 Thực hiện như sau: SELECT c.experience_id, c.country, p.platform, THETA_INTERSECT(c.user_theta, p.user_theta) from (select experience_id, country, user_theta from theta_cube where agg_level = country) c union (select experience_id, platform, user_theta from theta_cube where agg_level = platform) p
5 https://datasketches.apache.org/docs/Theta/ThetaSketchSetOpsAccuracy.html
6 Thông qua hàm SQL của Druid COMPLEX_DECODE_BASE64('HLLSketch', sketch_col_name ).


