大家工作生活中可能经常使用微信、钉钉、微博这样的软件,作为技术开发的你有没有想过它们后端的技术架构是如何做的?

阿里P7面试被问到亿级聊天架构如何用Netty设计,感觉凉了

IM核心功能

一般来说,钉钉和微信后端主要就是一个IM的即时通讯软件,再加上很多周边功能,我们先来看下IM这块的核心功能包含哪些模块:

0)用户系统的使用者。

1)消息是指用户之间的沟通内容(通常在IM系统中,消息会有以下几类:文本消息、表情消息、图片消息、视频消息、文件消息等等)。

2)会话通常指两个用户之间因聊天而建立起的关联。

3)通常指多个用户之间因聊天而建立起的关联。

4)终端指用户使用IM系统的机器(通常有Android端、iOS端、Web端等等)。

5)未读数指用户还没读的消息数量。

6)用户状态指用户当前是在线、离线还是挂起等状态。

7)关系链是指用户与用户之间的关系,通常有单向的好友关系、双向的好友关系、关注关系等等(这里需要注意与会话的区别:用户只有在发起聊天时才产生会话,但关系并不需要聊天才能建立。对于关系链的存储,可以使用图数据库(Neo4j等等),可以很自然地表达现实世界中的关系,易于建模)。

8)单聊一对一聊天。

9)群聊多人聊天。

10)客服在电商领域,通常需要对用户提供售前咨询、售后咨询等服务(这时,就需要引入客服来处理用户的咨询)。

11)消息分流在电商领域,一个店铺通常会有多个客服,此时决定用户的咨询由哪个客服来处理就是消息分流(通常消息分流会根据一系列规则来确定消息会分流给哪个客服,例如客服是否在线(客服不在线的话需要重新分流给另一个客服)、该消息是售前咨询还是售后咨询、当前客服的繁忙程度等等)。

12)信箱本文的信箱我们指一个Timeline、一个收发消息的队列。

读扩散 vs 写扩散

IM系统里经常会涉及到读扩散和写扩散这两个技术概念,我们来看看。

读扩散

读扩散也称为“拉模式”,这应该是最符合我们认知直觉的一种技术实现方式。

原理如下图

阿里P7面试被问到亿级聊天架构如何用Netty设计,感觉凉了

如上图所示每一个内容发布者都有一个自己的发件箱(“我发布的内容”),每当我们发出一个新帖子,都存入自己的发件箱中。当我们的粉丝来阅读时,系统首先需要拿到粉丝关注的所有人,然后遍历所有发布者的发件箱,取出他们所发布的帖子,然后依据发布时间排序,展示给阅读者。


这种设计阅读者读一次消息流,后台会扩散为N次读操作(N等于关注的人数)以及一次聚合操作,因此称为读扩散。每次读消息流相当于去关注者的收件箱主动拉取帖子,因此也得名——拉模式。


这种模式

1)好处是:底层存储简单,没有空间浪费。

2)坏处是:每次读操作会非常重,操作非常多。


设想一下如果我关注的人数非常多,遍历一遍我所关注的所有人,并且再聚合一下,这个系统开销会非常大,时延上可能达到无法忍受的地步。


因此读扩散主要适用系统中阅读者关注的人没那么多,并且刷消息流并不频繁的场景。

拉模式还有一个比较大的缺点就是分页不方便,我们刷微博或朋友圈,肯定是随着大拇指在屏幕不断划动,内容一页一页的从后台拉取。如果不做其他优化,只采用实时聚合的方式,下滑到比较靠后的页码时会非常麻烦。

写扩散

据统计大多数消息流产品的读写比大概在100:1,也就是说大部分情况都是刷消息流看别人发的朋友圈和微博,只有很少情况是自己亲自发一条朋友圈或微博给别人看。

因此读扩散那种很重的读逻辑并不适合大多数场景。

我们宁愿让发帖的过程复杂一些,也不愿影响用户读消息流的体验,因此稍微改造一下前面方案就有了写扩散。写扩散也称为“推模式”,这种模式会对拉模式的一些缺点做改进。

原理如下图

阿里P7面试被问到亿级聊天架构如何用Netty设计,感觉凉了

如上图所示系统中每个用户除了有发件箱,也会有自己的收件箱。当发布者发表一篇帖子的时候,除了往自己发件箱记录一下之外,还会遍历发布者的所有粉丝,往这些粉丝的收件箱也投放一份相同内容。这样阅读者来读消息流时,直接从自己的收件箱读取即可。


这种设计每次发表帖子,都会扩散为M次写操作(M等于自己的粉丝数),因此成为写扩散。每篇帖子都会主动推送到所有粉丝的收件箱,因此也得名推模式


这种模式可想而知发一篇帖子,背后会涉及到很多次的写操作。通常为了发帖人的用户体验,当发布的帖子写到自己发件箱时,就可以返回发布成功。后台另外起一个异步任务,不慌不忙地往粉丝收件箱投递帖子即可。


写扩散的好处在于通过数据冗余(一篇帖子会被存储M份副本),提升了阅读者的用户体验。通常适当的数据冗余不是什么问题,但是到了微博明星这里,完全行不通。比如目前微博粉丝量Top2的谢娜与何炅,两个人微博粉丝过亿。

阿里P7面试被问到亿级聊天架构如何用Netty设计,感觉凉了

设想一下如果单纯采用推模式,那每次谢娜何炅发一条微博,微博后台都要地震一次。一篇微博导致后台上亿次写操作,这显然是不可行的。


另外由于写扩散是异步操作,写得太慢会导致帖子发出去半天,有些粉丝依然没能看见,这种体验也不太好。


通常写扩散适用于好友量不大的情况,比如微信朋友圈正是写扩散模式。每一名微信用户的好友上限为5000人,也就是说你发一条朋友圈最多也就扩散到5000次写操作,如果异步任务性能好一些,完全没有问题。


那对于上面说的超级大V到底是采用读扩散还是写扩散了,其实都不是,在业界还有另一种读写混合模式

亿级架构核心点

由于概念比较多,一篇文章是不可能全部描述清楚的,还有像钉钉、微信与微博这种亿级海量用户的系统架构实现其实有很多难点,随便给你说几个,看下你自己是否知道!

1、亿级用户同时在线聊天如何保证高并发聊天消息正常推送

2、公众号千万级粉丝大V发文章如何让粉丝高效收取

3、高并发聊天系统如何保证发送的消息不乱序

4、微信钉钉后端海量离线消息如何高效存储与获取

5、高并发聊天系统如何保证发送的消息不丢失

6、单聊与群聊数据收发机制用读扩散还是写扩散

7、如何设计微博上亿粉丝大V消息收发架构

8、微信后端PB级海量历史聊天消息数据如何存储

9、应该如何架构微信春晚抢红包高并发系统

10、微信钉钉后端如何保证消息收发核心链路高可用

11、微信钉钉的群聊为什么要设置人数上限

12、如何架构微信后端百万在线直播互动系统

13、如何设计微信钉钉后端系统的缓存架构抗高并发

14、微信朋友圈日均千亿访问量背后会有哪些技术挑战


看完懵了么?再继续看下图,给大家写了一套亿级钉钉微信后端IM架构核心(1.0)的图,感觉怎么样?

阿里P7面试被问到亿级聊天架构如何用Netty设计,感觉凉了

阿里P7面试被问到亿级聊天架构如何用Netty设计,感觉凉了

学完将收获

1、深入到源码级别,带你彻底理解Netty高并发高性能的架构设计思想

2、通过企业级实战IM项目,帮你掌握类似钉钉微信这种亿级用户架构项目的核心设计

3、 在简历上增加精通NIO模型与高性能框架Netty的底层原理与项目实战一项

4、在金九银十的面试中,能够很好地应对关于NIO与Netty的面试问题

2021最新版大厂面试真题集

阿里P7面试被问到亿级聊天架构如何用Netty设计,感觉凉了
需要资料的小伙伴点赞+关注,【双击此处】即可获取