查看原文
其他

【干货总结】如何设计WhatsAPP

2016-06-19 Mengying Tian 论码农的自我修养

今天讲一讲如何设计WhatsAPP,这是一款非常流行的聊天软件,也是一个非常通用的架构。



从数据结构开始,我们需要什么表呢?首先肯定是user表,有用户id和一些参数;然后有friend表,是用户id 的互相关联;还有channel表,即群关系,要有群id;还有message表,就是用户发送的消息。


有了这些表,我们如何选择合适的数据库呢?一般有SQL和NoSQL两种选择。SQL是关系型数据库,便于修改,能保证数据一致性,适用于组合状态。NoSQL有很多种,处理大规模数据性能更好,比较适合append操作,但是可能有数据不一致的情况,适用于序列化的数据。所以user,friend和channel表选用SQL数据库,因为数据互相关联,可能会经常更新。而message表一般只需要append操作就可以了,而且数据量大,选用NoSQL更合适


然后再聊聊架构。User manager负责用户服务相关的管理,Channel manager负责频道(群)服务相关的管理;聊天服务往往要维护与用户的连接,所以用独立服务器开放多个socket监听请求;中间通过router转发请求。

有了基本架构,我们来谈一个很有趣的话题:如何支持百万群聊?

首先计算一下需求,假设有一百万用户同时在线,但是用户发消息的频率一般来说并不高,大概十分钟一条,每条30B。所以每秒有50GB的数据量,是一个很大的值,有没有办法缩减呢?



一个基本的方法就是将消息打包,之前每条信息都有一个头一个尾,有很多流量耗费在了协议上。所以我们可以多个消息一起发送,共用头和尾,这样就将流量缩减到了30GB/s。


还可以将消息进行压缩,能缩减到15GB/s,这样就比最初减少了75%的流量,是不是棒棒的。



如果用户当前不在线,发给他的消息怎么办呢?如果用户换了一台设备,还可以查阅历史记录吗?能不能搜索历史记录呢?


这些问题有没有感觉似曾相识?之前有一期视频讲了Twitter架构的push和pull模型,Twitter架构实际上就实现了离线消息的发送和消息的检索,所以我们可以把Twitter架构跟WhatsAPP架构相结合,就解决了离线消息发送和搜索历史记录的需求。

Twitter架构设计中讲了非常通用的push/pull模型。push模型就是当用户写了新的tweet就发送给所有的follower;而pull模型就是用户只写在自己的timeline里,当follower查看消息的时候才从timeline里获取数据。


这个push/pull模型是数据层面的,如果我们想实现新消息提醒这样的功能,我们可以使用link层面的push/pull模型。link-pull是用户和服务器之间不建立长连接,而采用轮巡的策略,每隔几秒check一下有没有新消息;或者采用link-push模型,维护服务器和用户之间的长连接,这样有新消息服务器就可以直接push给用户了。


那么push和pull各有什么优缺点呢?push比较快更及时,但是如果用户并不需要经常check的话维护这么多长连接是很浪费的。pull会有一些delay,而且如果用户并没有新消息,不断轮巡其实也很浪费,还会耗费带宽。



所以一种方式是将push/pull模型进行组合,可以push给用户新消息的数目,当用户想要查看的时候pull获取所有消息。


还有一个问题是如何通知用户上线/下线的消息呢?如果用户上线/下线就立刻发送消息的话,网络状况不稳定的时候可能会出现用户不断上线/下线的情况。

所以没有必要通知地那么及时,可以适当地lazy一点,等待5s再通知就避免了上述情况。



太阁实验室有趣,有用,有效;刷项目,做实战,捅破技术那层纸论码农的自我修养WeChat ID: bit_tiger长按二维码,关注我哟~
点击下方“阅读原文”跳转视频页面
↓↓↓ 

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存