Facebook Messenger - Data Storage
Ở hai phần trước chúng ta đã phân tích cách thức để hệ thống hoạt động hiệu quả, kèm theo cách gởi nhận tin nhắn.
Phần này mình sẽ tập trung vào lưu tin nhắn vào database và dùng DB nào cho hiệu quả nhất.
Khi nhận được tin nhắn đến server, server cần đẩy tin nhắn đó vào database bằng 2 cách sau:
- Tạo thread mới chỉ để làm việc với database
- Gởi request bất đồng bộ đến database
Cần chú ý một số điểm khi tạo database như sau:
- Hiệu quả của việc tạo kết nối đến database server
- Retry nếu request lỗi
- Log lại các request bị lỗi sau khi đã retry
- Cách xử lý các request dù đã retry nhưng bị lỗi.
Theo kinh nghiệm của mình làm với webhook thường xuyên xảy ra vấn đề này, nên cần có cơ chế gởi lại các request không gởi thành công sau một khoảng thời gian nào đó.
Nên chọn Database System nào để lưu?
Vì tin nhắn gởi nhận liên tục nên db cần hỗ trợ insert/update cực kỳ nhanh, và query một đoạn ngắn nhanh. Chúng ta không thể dùng MySQL hoặc NoSQL như MongoDB vì không thể vừa đọc vừa ghi khi user gởi tin nhắn đến, latency sẽ rất cao nếu nhiều người cùng online và gởi tin nhắn.
Có một DB có thể giải quyết bài toán trên là HBase. HBase là Column-oriented NoSQL database có thể lưu key, value với value là nhiều columns. HBase được mô hình hoá dựa theo Google BigTable và chạy trên Hadoop Distributed File System (HDFS). HBase gom nhóm dữ liệu mới để lưu trong bộ đệm memory và khi bộ đệm đầy sẽ tự động ghi ra ổ cứng. Cơ chế nãy giúp lưu dữ liệu nhỏ (tin nhắn) nhanh hơn và truy cập nhanh hơn.
Client lấy dữ liệu như thế nào?
Paginate, luôn luôn query theo từng đoạn cần thiết không query quá nhiều. Số lượng record khi paginate tuỳ theo kích thước màn hình có thể xem ở client (mobile, tablet hoặc pc).
http://sites.computer.org/debull/A12june/facebook.pdf
https://www.slideshare.net/brizzzdotcom/facebook-messages-hbase
Hai tài liệu này có miêu tả khá đầy đủ về Facebook dùng HBase như thế nào.
Vấn đề cuối cùng ở phần này mà mình muốn đề cập đến là làm thế nào để quản lý trạng thái online/offline của user hiệu quả. Giả dụ có 50M user cùng online, chúng ta phải nắm giữ 50M kết nối với toàn bộ user, và thông báo trạng thái 1 user thay đổi đến toàn bộ những user liên quan, tốn rất nhiều resource. Chúng ta có thể optimize như sau:
- Khi user mở app, có thể lấy list status của toàn bộ user đã là friend
- Khi user gởi tin nhắn đến user đã offline, chúng ta có thể send ngược lại là tin nhắn đã gởi không thành công và thể hiện trạng thái offline của user nhận
- Khi user online, server broadcast trạng thái online (có thể delay một lúc để thực sự user online tránh trường hợp offline ngay tức thì) đến những user có liên hệ với user này.
- User có thể pull to refresh để cập nhật tức thì trạng thái
- Khi 2 user bắt đầu chat với nhau có thể thấy được trạng thái của nhau.
Tổng quan:
Client sẽ mở kết nối đến Chat server để gởi tin nhắn, server sẽ gởi tin nhắn đến user được nhận.
Tất cả active users sẽ giữ kết nối đến Chat server để nhận tin nhắn.
Khi tin nhắn đến, chat server sẽ push tin nhắn về user nhận theo kiểu long poll request.
Tin nhắn sẽ lưu ở HBase, hỗ trợ cập nhật dữ liệu nhỏ và tìm kiếm theo đoạn.
Server có thể broadcast trạng thái online của một user đến những user liên quan.
Phần này kết thúc ở đây nhé. Phần cuối mình sẽ miêu tả cách phân mảnh dữ liệu và xử lý lỗi.
Thân. Happy cheating.