Con chim xanh Duolingo và bài toán gửi 4 triệu notification trong 5s
Anh em nhìn các thông báo này có quen không:
Và đó là các thông báo từ con chim xanh "bố láo" của ứng dụng Duolingo 😂😂😂. Những chiến dịch truyền thông và đội content của Duolingo đã rất thành công để giữ chân người dùng. Góp phần đưa ứng dụng này trở thành một ứng dụng nổi tiếng có 500 triệu người đã đăng ký tài khoản, với 32.4 triệu daily active user. Có đến 100 khóa học cho hơn 40 ngôn ngữ khác nhau.
Đó là nhờ đội marketing vô cùng đỉnh của chóp. 🤓🤓🤓
Cùng tìm hiểu một bài toán cực khoai mà đội Dev phải đối mặt do yêu cầu từ đội marketing này nha****
Chúng mình có tạo Group cho các bạn cùng chia sẻ và học hỏi về thiết kế hệ thống nha 😄😄😄
Các bạn tham gia để gây dựng cộng đồng System Design Việt Nam thật lớn mạnh nhé 😍😍😍
Cộng Đồng System Design Việt Nam: https://www.facebook.com/groups/sydexa
Kênh TikTok: https://www.tiktok.com/@sydexa.com
1. Thông báo từ sếp đến đội Developer
Để thêm quảng bá cho sản phẩm thì team marketing đã có kế hoạch chạy một quảng cáo dài 5 giây trong Super Bowl (sự kiện thể thao lớn nhất tại Mỹ, diễn ra hàng năm vào đầu tháng Hai), sự kiện có 123,4 triệu người xem, con số cao nhất trong lịch sử. Quảng cáo dự kiến sẽ có sự xuất hiện của "mông Duo" (linh vật của Duolingo) và đội marketing cũng muốn gửi thông báo đẩy (Push notification) đến thiết bị của người dùng ngay khi quảng cáo được phát sóng
Còn đây là ảnh về mông con chim xanh nếu anh em nào thấy hay:
Nhưng việc quảng cáo chỉ chiếu trong 5 giây và cần gửi để người dùng có thể nhận ngay thông báo ngay khi quảng cáo được phát sóng đã đặt ra một bài toán vô cùng khó khăn cho anh em dev tại Duolingo.
Họ cần phải gửi Push notification đến 4 triệu người trong vòng 5s, tương đương cần gửi 800.000 noti mỗi giây. Trong khi hệ thống thông báo của họ hiện tại đang chỉ chịu tải khoảng 10,000 thông báo mỗi giây. Tức là cần nâng cấp để có thể xử lý gấp 80 lần hệ thống hiện tại.
Nhưng chiến dịch quảng cáo này không chỉ khó ở việc cần gửi lượng thông báo lớn mà họ cần xem xét cẩn thận mọi thứ, ví dụ điển hình là hệ thống Coinbase vào năm 2022, Coinbase đã tung ra một chiến dịch quảng cáo với mã QR nảy trên màn hình. Chiến dịch này đã thu hút quá nhiều người truy cập vào trang web của Coinbase đến mức làm sập trang web của chính họ. Nghĩa là họ đã tự DDOS chính mình 😗😗😗
Ứng dụng Android của Duolingo có một vấn đề là khi mỗi thông báo được gửi đi sẽ tạo ra một yêu cầu ngược lại về phía máy chủ. Điều này có thể gây quá tải hệ thống nếu gửi một lượng lớn thông báo cùng lúc. Và họ không muốn bị như Coinbase.
Duolingo phải đối mặt với thử thách xây dựng hệ thống gửi thông báo nhanh chóng trong khi đảm bảo hệ thống không bị quá tải và có thể xử lý lượng truy cập tăng đột biến do người dùng nhận thông báo có thể truy cập vào app để học luôn. Khoai phết nhỉ, vậy họ đã làm thế nào
2. Kiến trúc hệ thống
Để làm được bài toán này đội ngũ kỹ sư tại Duolingo có 3 bài toán khó:
- Tốc độ: họ cần phải đạt được tốc độ gấp 80 lần hệ thống hiện tại: 800,000 noti/s
- Scale: Do triển khai hạ tầng trên AWS, họ cần đảm bảo hệ thống có thể scale đáp ứng được lượng tải cao, và tối ưu chi phí phải bỏ ra
- Thời gian: Vì do quảng cáo vào một sự kiện thể thao, nên thời điểm nhà đài phát quảng cáo của sẽ rất khó xác định do thời gian bù giờ, thời gian chấn thương. Do đó họ không biết chính xác khi nào quảng cáo của bạn sẽ được phát sóng
Và họ đã triển khai hệ thống có design như sau:
Do họ không biết chính xác khi nào quảng cáo của bạn sẽ được phát sóng. Họ đã thiết kết hệ thống với một nút màu đỏ hình vuông, và đội marketing sẽ theo dõi trực tiếp truyền hình và bấm nút ngay khi quảng cáo vừa xuất hiện trên tivi.
Còn tại sao là nút hình vuông thì mình sẽ nói sau ha. Và đội ngũ cần đảo bảo nếu hai người trong đội marketing bấm nút cùng lúc thì sẽ không bị gửi trùng lặp đến người dùng.
Tổng quan thì đây là một kiến trúc bất đồng bộ và sử dụng các service trên AWS
Vậy hệ thống hoạt động như nào nhỉ???
- Trước sự kiện vài tháng:
Họ sẽ tạo ra một chiến dịch thông báo gồm danh sách toàn bộ User Id sẽ nhận được thông báo. Server sẽ lấy dữ liệu từ DynamoDB một cách bất đồng bộ (asynchronously). Dữ liệu được lấy về sẽ được xử lý và đẩy vào lưu trữ tại AWS S3. Kết quả cuối cùng được ghi log lại vào Cloudwatch để đội kỹ sư có thể theo dõi.
- Vài tiếng trước khi sự kiện diễn ra
Đội kỹ sư sẽ scale số lượng Interim worker trong ECS Cluster lên khoảng 20 con interim worker, cụm notification được scale lên hơn 5000 con notification worker, giúp cho số lượng worker đủ để chịu tải.
20 interim workers này sẽ chịu trách nhiệm lấy trước dữ liệu từ Amazon S3 đã được lưu từ trước và lưu trữ vào bộ nhớ in-memory. Bước này rất quan trọng vì nó cho phép hệ thống truy cập nhanh chóng vào dữ liệu cần thiết khi quá trình gửi thông báo bắt đầu, từ đó giảm độ trễ và đảm bảo rằng các thông báo có thể được gửi đi trong vòng vài giây. Dữ liệu này bao gồm cả thông tin mapping giữa UserId và DeviceId. Toàn bộ quá trình sẽ được log để theo dõi trên CloudWatch.
- Thời điểm diễn ra sự kiện
Vào ngày diễn ra sự kiện, đội marketing cầm trên tay bỏng ngô và cái nút kích hoạt hình vuông màu đỏ, theo dõi và chờ thời điểm quảng cáo của Duolingo được phát sóng.
Thời điểm vàng đã đến, họ bấm nút, API server sẽ nhận request và gửi hơn 50 message đến FIFO Queue.
Interim Worker nhận message từ FIFO queue và phân phối hơn 10,000 message đến queue tiếp theo.
Các con worker hoạt động song song và lượng message được gửi đến SQS này cần đạt tới 800,000 message/s. Nhưng do SQS có giới hạn chỉ được gửi 120.000 mỗi giây. Họ đã gom nhóm 500 IOS user vào chung 1 message, 250 Android User vào chung một message. Rồi mới đẩy các nhóm vào SQS, điều này giúp họ lách được giới hạn của queue và đạt được rate 800,000 message/s
Hơn 500 con worker có nhiệm vụ gửi noti đang chờ sẵn và nhận các message và tiến hành gửi push noti bằng cách gọi đến API của APNS (Apple Push Notification Service) và FCM (Firebase Cloud Messaging), và từ đó các thiết bị Apple, Android của người dùng sẽ nhận được 1 push noti của Duolingo ngay khi quảng cáo vừa được phát vài giây.
Tại sao họ lại dùng FIFO queue nhỉ?
Một phần là do AWS SQS FiFO queue giúp loại bỏ các message trùng lặp dựa trên ID. Qua đó họ đảm bảo được việc nếu như hai người nhấn nút cùng lúc, người dùng cũng không bị nhận 2 thông báo trùng lặp nhau. Giúp giảm bớt công việc cho hệ thống API Server.
3. Kiểm thử hiệu năng
- Tìm ra bottlenecks
Họ tiến hành push các noti có payload rỗng đến các thiết bị và tìm các cách nút thắt cổ chai (bottlenecks) trong hệ thống.
Hệ thống đã được xây bằng python, và do đó hệ thống đã gặp các vấn đề khóa thông dịch toàn cục (GIL).
Nó là một cơ chế trong trình thông dịch Python (CPython) nhằm đảm bảo rằng chỉ một luồng (thread) có thể thực thi mã Python tại một thời điểm nhất định, nhưng lại khiến cho hệ thống có hiệu suất đa luồng kém, và dễ trở thành một nút thắt cổ chai
Để giải quyết họ đã giảm số thread từ 10 xuống 5 và xuống 1, sau đó bin packing được sử dụng để tối ưu hóa việc phân phối các tác vụ (tasks) vào các tài nguyên hệ thống (như CPU, bộ nhớ) sao cho sử dụng tối thiểu số lượng tài nguyên mà vẫn đảm bảo hiệu suất qua đó họ đã tìm ra thiết lập tối ưu, giúp hệ thống đạt được hiệu suất mong muốn.
- Kiểm thử với các thông báo thật với số lượng tăng dần
Đội ngũ kỹ sư đã kiểm thử với người dùng thật với các nội dung khác nhau. Vào tháng 10, họ đã test trên 1 triệu người dùng bằng thông báo chủ đề Halloween. Vào tháng 11, thông báo chủ đề tổng kết năm. Vào tháng 1/2024, họ đã thử nghiệm trên 4 triệu người dùng bằng thông báo chào mừng trở lại sau năm mới.
Trên app Duolingo có một công cụ khá hay ho đó là chế độ "Zombie mode" được đội ngũ kỹ sư sử dụng. Chế độ này được sử dụng khi có lượng request tăng đội biến, hệ thống của Duolingo có thể chuyển sang chế độ zombie, khi đó app duolingo sẽ hạn chế gửi các request về phía backend trong một khoảng thời gian nhất định, giúp cho hệ thống backend có thời gian để phục hồi để đáp ứng lượng tải lớn
4. Thành quả xứng đáng
Vào ngày diễn ra sự kiện Super bowl, các kỹ sư theo dõi mọi thứ qua zoom cùng nhau để scale hệ thống, khi quảng cáo xuất hiện, đội marketing bấm nút, Bum. Hệ thống được kích hoạt, 99% thông báo đã được gửi trong 5.7s, trong đó có 95% được gửi trong 3.9 giây. Một kết quả vô cùng ấn tượng, tạo ra hiệu ứng lan truyền mạnh mẽ trên mạng xã hội. Chiến dịch này không chỉ giúp Duolingo tăng lượng người dùng đáng kể mà còn củng cố hình ảnh thương hiệu độc đáo và hài hước với hình ảnh mông của con chim xanh
After Credit
Việc họ dùng nút màu đỏ hình vuông thay vì hình tròn là do họ phát hiện ra, với các nút hình tròn khi nhấn vào các góc của nút bấm, mặc dù các góc này có màu trắng và không nằm trong vùng tròn, nhưng nó vẫn kích hoạt chức năng của nút.
Hiện tượng này trong thuật ngữ trò chơi điện tử được gọi là "hitbox" (vùng tương tác), nơi vùng tương tác thực tế của nút vẫn là một hình vuông dù nút hiển thị là hình tròn.
Do đó, để tránh lỗi do con người và đảm bảo mọi người đều biết rõ vùng nào cần nhấn, nhóm đã quyết định thay đổi nút bấm từ hình tròn sang hình vuông. Việc này giúp người dùng nhận biết rõ ràng hơn về vùng tương tác của nút, giảm nguy cơ nhấn nhầm.
Qua đó thấy được sự tỉ mỉ của anh em dev tại Duolingo
Nếu thấy bài viết hay thì cho chúng mình xin một upvote để lấy động lực nha
Chúng mình có tạo Group cho các bạn cùng chia sẻ và học hỏi về thiết kế hệ thống nha 😄😄😄
Các bạn tham gia để gây dựng cộng đồng System Design Việt Nam thật lớn mạnh nhé 😍😍😍
Cộng Đồng System Design Việt Nam: https://www.facebook.com/groups/sydexa
Kênh TikTok: https://www.tiktok.com/@sydexa.com
Tham khảo:
Bài chia sẻ của kỹ sư tại Duolingo: https://www.infoq.com/presentations/on-demand-notification-system/
All rights reserved