首先我写这篇博客所要探讨的问题是什么,自己查询资料得出的结论或者理解记录下来,产生了这篇博客

问题背景:

我相信现在几乎我们每个人都在使用微信,那么你知道微信平台每天的信息量有多大吗?2017年微信官方在知名论坛上公布了其今年9月平均日登陆用户达9.02亿,同比增长17%。你在这9亿人里吗?每天有如此多的用户使用微信,你能想象到每天发送多少微信消息呢?380亿!是不是很吃惊,微信朋友圈消息,语音、视频消息较往年都有较大增长,微信每天要处理这么多的消息,那他是怎么保证消息传递的可靠性并且有效的降低服务器或者客户端的压力呢?下面就跟我一起来了解并且揭开解决这一问题的方法之一的读写扩散技术。

初期:

要知道微信早期定位是一个通讯工具,并没有象现在这样分支很多,作为一个通讯工具,跟qq一样,最重要的就是收发消息,并且保证消息的可靠性,这里有必要说一下我想说的一种可靠性不足的场景:假设A,B客户端通过服务器S通信,如果A    发送了消息,但是B却不在线,这时候微信是如何保证消息可以在B上线的时候把消息推送给B的,或者说B是如何获取“离线消息”的呢?

这里我找到了微信早期的消息模型:存储转发(下图)。

所谓存储转发就好像邮箱的处理方式一样,当客户端A发送消息给B,B这时候并不在线,,那么消息会临时存在服务器,当然了消息不能一直在服务器持久化存储,因为服务器的内存资源毕竟有限,当时的解决方法就是服务器暂存了消息以后,会尽快发送消息通知给接收端,从而使接收端更快的将消息接收,客户端收到通知以后主动到服务器收取消息,然后服务器会释放这块消息存储。

第二阶段:

因为用户的账户、联系人和消息都在服务器存储,如何将数据同步到客户端就成了很大的问题,于是有了下面的方案,做一个同步协议来同步这些基础数据。

方案一:

客户端记录一个本地数据的快照(Snapshot),需要同步消息的时候,客户端将这个Snapshot带到服务器,服务器通过计算Snapshot和服务器数据的差异,将差异数据发送到客户端,客户端再保存差异数据完成同步。这种方案存在两个问题:

1.随着微信客户的越来越多,需要同步的数据就越来绝大,增大了流量开销

2.客户端每次同步都要计算Snapshot,会带来额外的性能开销和实现复杂度。

那这个问题怎么解决呢?

方案二:

解放客户端, 让服务器来计算Snapshot,然后跟消息一起发送给客户端,这时候客户端不需要知道这个Snapshot是什么,他只需要把这个Snapshot存储起来,在下一次数据同步的时候发送给服务器,这样服务器通过对比客户端的Snapshot和之前服务器保存的Snapshot进行对比,如果客户端发送过来的Snapshot是最新的,则服务器可以判断已经完成了数据同步,采用这个方案的另一个好处是,客户端不用发送ack到服务器来通知消息收到,因为服务器通过对比快照就能判断消息发送并且客户端接收成功,同步完以后服务器可以大胆的清楚暂存的消息。

如今微信的功能越来越丰富了。其中很重要的就是群聊和朋友圈,同样是之前的问题,群聊和朋友圈又是如何解决的呢?

在说这个问题之前,我们先来了解一下读写扩散的概念:

inbox: 收件箱,你收到的消息,即你所关注的人发布的消息。
outbox: 发件箱,你发布的消息。

写扩散(Push)

该方式为每个用户维护一个订阅列表,记录该用户订阅的消息索引(一般为消息ID、类型、发表时间等一些元数据)。每当用户发布消息时,都会去更新其follower的订阅列表。
优点:读很轻。初始化时仅需要读取自己的inbox即可。
缺点:写很重。每发布一个消息,会导致大量的写操作。
注:一般来说,用户发布消息,并不会更新所有followers的订阅列表,仅更新在线followers即可。

读扩散(Pull)

该方式为每个用户维护一个发送列表,记录该用户所有发表过的消息索引。
优点:写很轻,节省空间。用户每发布一条消息,仅需更新自己的outbox。
缺点:读操作很重,计算量大。假设你收听了1k用户,则初始化时,需要从1k个用户的outbox拉取消息,然后计算获得最新的n条消息。

混合模式(Push+Pull)

该方式既为读写扩散的结合,根据用户followers的数量来决定是读扩散还是写扩散。例如followers大于1k的,则使用读扩散,否则使用写扩散。

从目前现在网上的一些资料来看,Twitter是写扩散,腾讯微薄是读扩散,新浪微薄则是二者结合。

好,下面我们就结合群聊和朋友圈的场景来看一下读写扩散是怎么使用的。

这里要知道微信每个人的好友有上限,群聊的人数也有上限,所以这就限制了微信的设计复杂度没有新浪微博那样复杂,因为群聊是个耗时的操作,所以可以采用异步队列写扩散的方式来实现消息的发送。当A用户在群里发送了一条消息(在outbox)以后,会在群中其他所有人的inbox中添加一条这条消息的索引,即使你并没有在线,当离线用户上线的时候,只需要检查自己的inbox列表就能收到“离线消息”。换句话说就是:消息扩散写到每个人的消息存储(消息收件箱)后,接收者到后台同步数据时,只需要检查自己收件箱即可,同步逻辑跟单聊消息是一致的,这样可以统一数据同步流程,实现起来也会很轻量。至于为什么不采用读扩散,一是因为一个群聊的人数相对较少,利用写扩散更加合适,二是如果采用读扩散,微信群聊每秒钟都可能有消息产生,那么用户会执行大量的读操作,这个过程并不是完全可靠的,很可能发生数据丢失。

下面再看一个微信朋友圈的例子(转载自:例子):

比如有两个用户小王和Mary。小王和Mary各自有各自的相册,可能在同一台服务器上,也可能在不同的服务器上。现在小王上传了一张图片到自己的朋友圈。上传图片不经过微信后台服务器,而是直接上传到最近的腾讯CDN节点,所以非常快。图片上传到该CDN后,小王的微信客户端会通知微信的朋友圈CDN:这里有一个新的发布(比如叫K2),这个发布的图片URL是什么,谁能看到这些图片,等等此类的元数据,来把这个发布写到发布的表里。

在发布的表写完之后,会把这个K2的发布索引到小王的相册表里。所以相册表其实是很小的,里面只有索引指针。相册表写好了之后,会触发一个批处理的动作。这个动作就是去跟小王的每个好友说,小王有一个新的发布,请把这个发布插入到每个好友的时间线里面去。

然后比如说现在Mary上朋友圈了,而Mary是小王的一个好友。Mary拉自己的时间线的时候,时间线会告诉到有一个新的发布K2,然后Mary的微信客户端就会去根据K2的元数据去获取图片在CDN上的URL,把图片拉到本地。

在这个过程中,发布是很重的,因为一方面要写一个自己的数据副本,然后还要把这个副本的指针插到所有好友的时间线里面去。如果一个用户有几百个好友的话,这个过程会比较慢一些。这是一个单数据副本写扩散的过程。但是相对应的,读取就很简单了,每一个用户只需要读取自己的时间线表,就这一个动作就行,而不需要去遍历所有好友的相册表。

为什么选择这样一个写扩散的模型?因为读是有很多失败的。一个用户如果要去读两百个好友的相册表,极端情况下可能要去两百个服务器上去问,这个失败的可能性是很大的。但是写失败了就没关系,因为写是可以等待的,写失败了就重新去拷贝,直到插入成功为止。所以这样一个模型可以很大的减少服务的开销。

虽然我不知道微信后台具体采用的什么技术或者工具来实现的读写扩散,但是我觉得这可以通过Redis的list和set两个数据解耦来实现,比如微信朋友圈都知道的功能,当你发布一个朋友圈的时候,只有和你拥有共同好友的人才能看到评论,这里就可以使用redis的set的求交集、并集、差集等操作来找到你的而共同好友进而决定向哪些用户发送消息索引。

微信后台架构浅析--读写扩散技术相关推荐

  1. [转]微博后台架构浅析——读扩散pull、写扩散push、混合模式(push+pull)——相关cache(redis,memcache)...

    原文地址:http://blog.163.com/xychenbaihu@yeah/blog/static/1322296552013430114959121/ 之前在网上看到关于Twitter.Si ...

  2. 从0到10亿,微信后台架构及基础设施设计与实践!

    摘要:微信后台业务类型众多,包括即时通信,社交网络,金融支付等等.本次分享着重讨论如何在海量用户场景下,后台架构设计中的共性部分如高可用.强一致.快速迭代等等,微信是如何在不断变化的背景下设计统一的架 ...

  3. 微信后台基于时间序的海量数据冷热分级架构设计实践

    写在前面 微信的后台数据存储随着微信产品特性的演进,经历了数次的架构改造,才形成如今成熟的大规模分布式存储系统,有条不紊的管理着由数千台异构机型组成的机器集群,得以支撑每天千万亿级的访问.键值以及 P ...

  4. 微信后台基于时间序的新一代海量数据存储架构的设计实践

    本文作者腾讯WXG后台开发工程师jeryyzhang,收录时有改动,感谢原作者的分享. 1.引言 大约3年前,微信技术团队分享了<微信后台基于时间序的海量数据冷热分级架构设计实践>一文,文 ...

  5. 微信与朋友圈后台架构

    微信朋友圈技术之道:三个人的后台团队与每日十亿的发布量 视屏讲解 概述 截止到2015年7月,微信每月活跃用户约5.49亿,朋友圈每天的发表量(包括赞和评论)超过10亿,浏览量超过100亿.得益于4G ...

  6. 微信强大后台架构从0到1的演进历程

    阶段一:从无到有 2011.1.21 微信正式发布.这一天距离微信项目启动日约为2个月.就在这2个月里,微信从无到有,大家可能会好奇这期间微信后台做的最重要的事情是什么? 我想应该是以下三件事: 1确 ...

  7. 【转】微信与朋友圈后台架构

    微信朋友圈技术之道:三个人的后台团队与每日十亿的发布量 视屏讲解 概述 截止到2015年7月,微信每月活跃用户约5.49亿,朋友圈每天的发表量(包括赞和评论)超过10亿,浏览量超过100亿.得益于4G ...

  8. 微信后台技术“干货们”带来的启发

    本篇算是我阅读完微信后台技术相关的干货文章后得到的一些启发,如果去年中那篇属于技术干货的选择问题,这篇大概就是选择之后的消化吸收问题了. 循证与决策路径 在前文中提过,循证大概是我们读技术干货文章的一 ...

  9. 架构周报:微信后台系统的演进之路

    经典案例 \\ <阿里无线11.11 : Weex--关于移动端动态性的思考.实现和未来>--今天在移动端,尤其是像手机淘宝这样的 app 中,动态性问题逐渐成为一个比较棘手的问题.所谓动 ...

最新文章

  1. Java 技术篇-利用exe4j工具生成exe文件实例演示,IntelliJ IDEA将项目转化为jar包方法,运行生成后的程序弹出exe4j提示处理,生成的程序显示控制台设置方法
  2. php xml expat,PHP Expat :XML的解析器
  3. [CF]Round514
  4. cuda、cudnn相关问题链接
  5. 【并查集】家族 (ssl 1896)
  6. vue 父组件与子组件之间的传值(普通传值)
  7. C# 将内存中的datatable数据导出为Excel(方法二,创建Excel对象导出)
  8. 1.7 LINUX启动流程
  9. aws rds恢复数据库_使用AWS Glue将数据从AWS S3加载到AWS RDS SQL Server数据库
  10. 根据名称获取对应的拼音码首字母大写
  11. [实操记录]mysql5.7如何恢复被删除数据
  12. 网站seo淘宝客不能做了?我是怎么用网站做淘客月入过万的
  13. Dynamic Knowledge Graph Completionwith Jointly Structural and Textual Dependency
  14. 51单片机系列——定时/计数器
  15. Viterbi-Algorithm(维特比)算法
  16. #Python中创建一个字符串映射表
  17. 能否在虚拟平台里构建真实的生活体验?
  18. WEP/WPA/WPA2加密标准有什么区别?
  19. CVPR2020:Seeing Through Fog Without Seeing Fog
  20. Android 性能优化必知必会

热门文章

  1. docker 及docker compose笔记
  2. Xcode 更改默认版本 xcode-select
  3. u-collapse折叠面板双层for循环渲染无法加载内层
  4. ForkJoinPool 大型图文现场
  5. HDU 4348 To the moon(主席树区间修改)
  6. 前端 300题 —— 牛客网
  7. [普通物理]波动方程
  8. sqlserver根据经纬度查询距离范围
  9. CSS第七天学习总结—— vertical-align 属性应用
  10. VINS-mono 学习之 三角化