朋友圈架构设计
1. 朋友圈复杂度分析
先从朋友圈的业务复杂度和质量复杂度来逐一分析。
业务复杂度:微信朋友圈的业务复杂度并不高,简单拆解下来主要有:发朋友圈、看朋友圈、评论、点赞等
质量复杂度:质量复杂度是朋友圈的难点,因为微信作为国内社交 App 的老大,拥有大量的活跃用户,对性能和高可用存在有较高要求。
所以我们重点从质量复杂度来进行分析。
以 2021/1/21 数据为分析依据:微信日活 10.9 亿;每天 7.8 亿人看朋友圈;每天 1.2 亿人发朋友圈。
发朋友圈:每天 1.2 亿人发朋友圈,假设平均发 1 篇,那么一天至少产生 1.2 亿朋友圈。我们假设 80%的朋友圈都在 8:00-24:00 发出,平均来说,至少要支持 1.2 亿*0.8/57600 秒=1666TPS;同时一天 1.2 亿,一年就是 438 亿,意味着存储上要支持千亿的数据
看朋友圈:这里假设每天看朋友圈的人平均刷 10 次,80%的流量在 8:00-24:00 ,平均来说至少要支持 78 亿*0.8/57600=11W QPS
点赞/评论:评论按照发朋友圈的数据近似推算 1666TPS,点赞一般高于评论,以 3 倍算约 5000TPS。点赞和评论我们也归在看朋友圈的 7.8 亿人群中。
因为以上只考虑了平均情况,系统性能以峰值情况算,按经验值 3 倍来预估,预计要求写入在 1-2W TPS,读取在 30-40W QPS。
2. 发朋友圈设计思路
2.1 发朋友圈高性能应对思路
单机方面,计算高性能复用原有的框架体系,存储高性能则可以采用关系型数据库或文档型数据库。
集群方面,计算高性能考虑任务分配,需要多实例负载均衡。又考虑到朋友圈的几个功能内聚性都比较强,故暂不考虑分解成多个服务。存储高性能需要考虑到海量数据的存储,一方面是如何存的下,另外一方面是海量数据下检索够快。所以存储肯定是要考虑分片的。
2.2 发朋友圈高可用应对思路
计算层面考虑部署多实例,甚至分区来实现高可用;
存储方面,复制采用命令格式。考虑到对发布内容丢失的容忍度不高,所以复制方式采用多数复制或者半同步,保障数据的可靠性
状态决策方面,如果是用关系型数据库那么用独裁式的 MySQL Router;如果是用文档数据库,那么用 MongoDB 的副本集,采用 Raft 协议
2.3 发朋友圈架构
最终发朋友圈的架构如上图所示:
选用了 MongoDB 分片副本集模式,原因是 MongoDB 天生带分片架构,可以支持千亿数据存储。业务是不断发展的,不可能一开始就千亿数据,如果用 MySQL,每次扩容都会比较麻烦,而 MongoDB 可以用较少代价进行扩容,保障业务不中断,适合本场景。
MongoDB 副本集每个分片都带复制库,保障了数据不丢失,还能自动故障转移,保障了高可用的目标
采用用户 ID 作为分片键,这样同一用户的朋友圈都会落在一个分片上,看自己发的朋友圈的时候不需要跨分片聚合
3.看朋友圈设计思路
3.1 看朋友圈高性能应对思路
单机情况下,基本保留原有框架。
集群情况下,计算层面采用任务分配,多实例负载均衡,暂时不需要任务分解。存储层面要支撑如此高的 QPS,需要使用 Redis,考虑到活跃用户数量很高,Redis 也要进行分片
3.2 看朋友圈高可用应对思路
计算高可用通过任务分配,即多实例负载均衡来实现。
存储高可用,使用命令格式,采用异步复制。采用异步复制的原因是考虑到 redis 中仅做缓存,在 MongoDB 中还保留有完整数据,所以即使极端情况发生产生一致性问题,最终也可以通过数据库中的数据恢复
3.3 看朋友圈架构
看朋友圈的架构如上图所示:
计算层面采用多实例负载均衡,保障性能即高可用
存储层面采用 Redis Cluster 来存储热点用户的 TimeLine 数据;Redis Cluster 支持动态扩缩容,支持主备故障转移,满足了我们对于数据量和高可用的要求
4. 点赞/评论设计思路
点赞/评论和发朋友圈类似,查看点赞和评论和看朋友圈类似,这里就不赘述了。
5. 整体架构
在构建整体架构前,还要考虑几个细节:
朋友圈/评论/点赞如何同步到 Redis 的 Timeline 中:可以采用异步同步机制。因为用户对于朋友圈的失效可以有一定的容忍度,为了保障写入的高效,可以在写入 MongoDB 后发一条 MQ 消息触发异步写入 Timeline。因为微信的好友有上限,不像微博有大 V,将一次 MongoDB 的写入扩散为多条 Redis 的写入操作还是可控的。
Redis 中可以只存活跃用户的 timeline,少数非活跃用户如果上线了,再临时用数据库构建 timeline 也可以接受
最终架构如上图所示,此处展示的是单机房的架构,微信的体量是要考虑多机房的。
所有的看朋友圈、看评论、看点赞都走 Redis Cluster,保障低延迟,高吞吐;
朋友圈、评论、点赞的写入走 MongoDB 集群,能够支撑千亿数据量;
朋友圈和 Timeline 的同步可以采用 RocketMQ 集群进行异步同步。
由于 Redis 集群和 MongoDB 集群都是支持动态扩容的,可以随着业务的发展进行动态扩张。
版权声明: 本文为 InfoQ 作者【intelamd】的原创文章。
原文链接:【http://xie.infoq.cn/article/30273e8c23e905f7d10028c11】。文章转载请联系作者。
评论