Hành Trình Momo Thống Nhất Vượt Qua Bẫy Cơ Sở Dữ Liệu (Phần 1) - nói dối e blog

Hành Trình Momo Thống Nhất Vượt Qua Bẫy Cơ Sở Dữ Liệu (Phần 1)

Dự án Momo Thống Nhất không mang tên này từ buổi đầu tiên. Vào giữa năm 2013, nó chỉ là một dự án thí điểm khiêm tốn của công ty nhằm “dò đá qua sông” trong lĩnh vực game di động. Mục tiêu khởi đầu rất rõ ràng: tựa game Clash of Clans (COC) đã khơi gợi cảm hứng của tôi về một thiết kế game mạng trên nền tảng di động hoàn toàn khác biệt so với các game MMO truyền thống. Tôi tin rằng chỉ cần tách lấy phần cốt lõi nhất của COC, chúng tôi có thể nhanh chóng xây dựng một sản phẩm đơn giản nhưng mang tính đột phá, từ đó phát triển thành hệ sinh thái game riêng.

Cơ duyên hợp tác với Momo đến một cách bất ngờ. Khi chúng tôi hoàn tất giai đoạn thử nghiệm, bài toán phân phối game lại chưa có lời giải (vì thể loại này đòi hỏi cộng đồng người chơi nhất định để vận hành). Trong khi đó, nền tảng game Momo vừa ra mắt đang đối mặt với tình trạng doanh thu bết bát từ tựa game đầu tiên (một phiên bản tương tự Bejeweled). Nhờ mối quan hệ thân thiết từ thời làm việc chung tại NetEase giữa hai nhà sáng lập, sản phẩm của chúng tôi đã được phát hành chỉ sau một tháng thương thảo và triển khai kỹ thuật.

Ban đầu, tôi chỉ bố trí A-Nam - người vừa hoàn thành dự án công cụ khởi động Kiếm Cuồng - thay thế vị trí của tôi trong dự án. Sau khi hoàn tất phần thiết kế engine đồ họa, tôi giao toàn bộ phần triển khai game cho anh ấy. Chúng tôi tập trung vào phát triển phía client vì đây là phần cần xây dựng lại kinh nghiệm kỹ thuật. Về phía server, do đã có hệ thống skynet - framework đã được nghiên cứu suốt nhiều năm, chúng tôi cho rằng không cần nhiều thay đổi để áp dụng cho dự án mobile này.

Khi mùa hè 2013 đến, chúng tôi bắt tay vào thiết kế kiến trúc server. Nhân sự chủ chốt là Hiểu Tĩnh, người vừa tích lũy kinh nghiệm phong phú từ dự án game PC Đấu La Đại Lục và cũng là chuyên gia thứ hai hiểu rõ skynet sâu sắc nhất sau tôi. Nếu chỉ cần một lập trình viên cho phần server, anh ấy là ứng cử viên hoàn hảo nhất.

Trong quá trình thiết kế kiến trúc, vấn đề lựa chọn cơ sở dữ liệu trở nên trọng yếu. Skynet có mô hình I/O riêng, để tối ưu hiệu suất, tốt nhất là tự xây dựng driver cơ sở dữ liệu dựa trên thư viện socket của skynet. Vì giao thức Redis cực kỳ đơn giản, tôi đã ưu tiên phát triển driver Redis đầu tiên. Trong khi đó, dự án Kiếm Cuồng đang sử dụng MongoDB, để thuận tiện vận hành, chúng tôi cũng xây dựng driver MongoDB cơ bản cho skynet. Đến thời điểm bắt tay vào phát triển server, chúng tôi có hai lựa chọn.

Kinh nghiệm hơn mười năm trong ngành game của tôi dạy rằng trong các game online có tính tương tác cao, cơ sở dữ liệu chủ yếu đóng vai trò lưu trữ dữ liệu dự phòng, hiếm khi được dùng làm phương tiện trao đổi thông tin. Nhiều lập trình viên ngoài ngành game thường dùng cơ sở dữ liệu làm cầu nối giữa các module nghiệp vụ, cách tiếp cận này dễ gây ra vấn đề hiệu năng nghiêm trọng.

Về mặt lý thuyết, do server game hoạt động 24/7 với tính tương tác mạnh mẽ, phần lớn dữ liệu tồn tại trong bộ nhớ suốt quá trình vận hành. Sau khi server khởi động và tải dữ liệu xong, hầu như không cần đọc thêm dữ liệu từ bên ngoài. Nếu có thể giả định bộ nhớ là vô hạn và server không bao giờ sập, cơ sở dữ liệu thậm chí không cần tồn tại.

Tuy nhiên hai giả định này không thể thành hiện thực. Với giới hạn bộ nhớ, game MMO truyền thống tiêu tốn O(n) tài nguyên (n là tổng số người dùng). Tuy nhiên, bằng cách chỉ lưu trữ dữ liệu của người dùng hoạt động (active user), chúng tôi có thể kiểm soát được mức tăng trưởng tài nguyên. Khi người dùng không hoạt động, chúng tôi sẽ “đổ” dữ liệu xuống ổ cứng, và tải lên lại khi họ quay trở lại. Trong giai đoạn đầu của game PC, tiêu chí xác định hoạt động đơn giản là trạng thái online/offline. Chúng tôi chỉ cần lưu dữ liệu khi đăng nhập và ghi lại khi đăng xuất, thậm chí chỉ cần ghi thành file văn bản có tên là ID người dùng - phương pháp từng được NetEase áp dụng.

Về độ ổn định server, dù muốn hay không, chúng tôi phải sao lưu dữ liệu định kỳ - có thể theo chu kỳ thời gian hoặc sau các hành động quan trọng. Để xử lý lượng dữ liệu vận hành khổng lồ (không gian phức tạp O(n*m) với n là số người chơi và m là thời gian vận hành), chúng tôi thiết lập hệ thống “log vận hành” riêng biệt, tách biệt khỏi log debug thông thường để tránh nhầm lẫn.

Với tư duy này, chúng tôi xây dựng kiến trúc server cho Momo Thống Nhất như sau:

  • Redis: Dùng để lưu trữ dữ liệu người chơi. Với quy mô dự kiến lớn, chúng tôi phân thành 32 kho Redis theo ID người chơi. Giai đoạn đầu, nhiều kho có thể chạy chung trên một máy vật lý, sau đó tách dần khi người dùng tăng. Nếu cần mở rộng hơn, việc chia nhỏ kho Redis cũng không quá phức tạp.

  • MongoDB: Cho các dữ liệu vận hành và ghi hình chiến đấu - những loại dữ liệu tăng dần theo thời gian. Để xử lý khối lượng dữ liệu lớn, chúng tôi áp dụng phân mảnh (sharding) thông qua mongos.

Giai đoạn đầu, chúng tôi chưa cần xử lý dữ liệu “nguội” vì hầu hết đều là dữ liệu “nóng”. Với tiến độ phát triển gấp rút, việc tối ưu hóa xử lý dữ liệu nguội được dời lại cho các giai đoạn sau. Với Redis, chúng tôi tận dụng sẵn chức năng BGSAVE và tinh chỉnh các thông số phù hợp.

Thiết kế này đã được giữ nguyên cho đến hôm nay, dù trong quá trình vận hành đã gặp không ít “hố” đáng nhớ, những câu chuyện đầy tính giáo dục mà tôi sẽ kể lại trong các phần tiếp theo.

Hẹn gặp lại các bạn vào bữa tối nay, phần tiếp theo sẽ tiết lộ một bí mật nóng hổi về tựa game thứ hai trên nền tảng Momo - Momo Audition, trò chơi ra mắt sớm hơn Momo Thống Nhất

0%