Design Whatsapp

Scenario

  • 基本功能
    • 用户登录注册
    • 通讯录
    • 用户互发信息
    • 群聊
    • 用户在线状态
  • 其他功能
    • 历史消息
    • multi device

Whatsapp

  • 1B 月活跃
  • 75% 日活跃 750M
  • 计算方便取 100M QPS:
  • 每个用户平均每天20条。 100M 20/86400 ~ 20k, peak QPS= 20k 5 = 100k Storage
  • 2030bytes(每条)100M = 60G

Service

Message Service - 负责信息管理 Real-time Service - 实时推送

Storage

不能存储在手机上,关机问题

  • Message Table (NoSQL)
    • 数据量很大,不需要修改,就跟log一样
  • Tread Table (SQL) 会话
    • 需要同时index by
      • owner id + thread id (primary key)
      • owner id + updated time (按照更新时间倒序排列)
    • NoSQL 对multiple indexes的支持并不好

updated_at 是用来给对话在inbox里排序用的 此时primary key是thread_id + owner_i

Work Solution

  • 发消息
    • client把消息和接受者的信息发给server
    • server为每个接受者(包括发送者自己)创建一条thread
    • 创建一条message(with thread_id)
  • 接收消息
    • 每隔十秒钟找服务器要一下最新的inbox
    • new message notification

Scale

Message 是NoSQL,自带Scale Thread可以按照owner_id进行sharding,因为每个client都属于同一个owner

how to speed up (Socket)

  • Socket, 通过Push Service提供Socket链接服务,可以与Client保持TCP的长连接。
  • 当用户打开App后,就连接上push service中一个属于自己的socket
  • 有人发消息的时候,Message Service收到消息,再通过push service把消息发出去。
  • 如果有一个用户长期不活跃(10mins),可以断开链接,释放掉网络接口。之后再打开App后,主动pull
  • vs Http
    • http,只能client向server要data
    • socket,server可以push data to client

很多个socket,有时候需要多个push service,shard by user_id

group chat

  • 假如有500人,不做优化,则需要一个个发消息,但其实同时只有10人在线,这样当消息到了push server才发现490人没有连上,浪费了490个消息传递
  • 增加一个Channel Service

    • 对每个聊天的thread增加一个channel信息。
    • user需要先subscribe channel,即用户上线时,web server(message service)找到用户所属的channel,并且通知channel service完成订阅,这样channel就知道哪些channel还有用户。如果用户断线了,则push service会通知channel service从所属的频道里移除
    • message service在收到用户发的信息以后,找到对应的channel,把发消息的请求发送给channel service,所以只需要发一条消息
    • channel service再找到当前在线的用户,发给push service 吧消息push出去

    channel service可以用内存存储数据,因为数据重要程度不高,挂了重启即可。

How to check/update online status

Push

  • 告知服务器
    • 用户上线的时候,与push service保持socket链接
    • 用户下线的时候,告诉服务器断开链接
    • server无法知道何时下线
  • server 告诉好友
    • 用户上下线时候,通知服务器
    • server通知好友
    • server无法知道何时下线,大部分好友不在线

Pull

  • 告知server
    • 上线后,client每隔3-5s,heart beat一次
  • server告知好友
    • 在线的好友,每隔3-5s问server要一次大家的status
  • 综上可以每隔10s,talk to server, heart beat and request friends' statuses

results matching ""

    No results matching ""