最近有不少晋升、跳槽的同学在后台留言,说他们在考核或面试上,都不约而同地遇到了「高并发架构设计」难题。
确实,从普通程序员到架构师,从编程思维升级到架构思维,“高并发架构设计”是绕不开的,如今更成为了进大厂的高频面试题。
困难点是,很多人在工作中没有高并发项目场景,今天通过模拟设计一个支持 10 亿 级用户体量的微博系统,带你身临其境地实践高并发架构设计。
这个设计案例,来自同程旅行交通首席架构师李智慧的新专栏《高并发架构实战课》,主要选取 15 个典型高并发系统案例,采用架构师最常用的“软件设计文档”形式,为你呈现架构师的高并发架构设计思路
我们知道微博的一个特点是:当明星大 V 发布一条比较有话题性的动态,比如鹿晗宣布,就会引起大量的阅读、评论和传播。这种突发的热点事件导致的高并发访问会给系统带来极大的负载压力,处理不当甚至会导致系统崩溃。
那么,类似微博的信息流系统架构要如何设计,才能解决热点消息产生的突发高并发访问压力,保障系统的可用性?
今天我们就来设计一个可以支持 10 亿 级用户体量的微博系统,系统名称为“Weitter”。主要分为三步:需求分析、概要设计和详细设计。
需求分析
Weitter 的核心功能只有三个:发微博,关注好友,刷微博。此外,用户还可以收藏、转发、评论微博。
负载指标估算
- 文本内容存储空间:100 GB/ 天
- 多媒体文件存储空间:60 TB/ 天
访问并发量估算
- QPS:46296/ 秒,高峰期 QPS 按平均值 2 倍计算:10 万 QPS
- 网络带宽:4.8 Tb/s
概要设计
从需求分析中可以看到,Weitter 的业务逻辑比较简单,但是并发量和数据量都比较大,所以,系统架构的核心就是解决高并发的问题,系统整体部署模型如下:
图中包括 “Get 请求”和“Post 请求”两条链路。
Get 请求
用户访问微博的数据中心、图片以及视频等极耗带宽的请求,绝大部分可以被 CDN 缓存命中,也就是说,4.8Tb/s 的带宽压力,90% 以上可以通过 CDN 消化掉。
Post 请求
客户端不需要通过 CDN 和反向代理,而是直接通过负载均衡服务器到达应用服务器。应用服务器一方面会将发表的微博写入 Redis 缓存集群,一方面写入分片数据库中。
详细设计
微博的发表 / 订阅问题
这是微博的核心业务问题,即微博用户关注好友后,如何快速得到好友最新发表的微博内容。
当用户在线时,我们可以使用“推模式”:建一张用户订阅表,用户关注的好友发表微博后,立即在用户订阅中为该用户插入一条记录,记录用户 ID 和好友发表的微博 ID。
如果用户目前不在线,那么系统就会将该订阅表删除,当用户登录刷新的时候,用“拉模式”为其重新构建列表:用户刷新微博的时候,根据其关注的好友列表,查询每个好友近期发表的微博,然后将所有微博按照时间顺序排序后构建一个列表。
缓存使用策略
微博整体的缓存架构采用了时间淘汰算法:缓存用户 7 天内发表的全部微博。缓存的 key 为用户 ID,value 为用户最近 7 天发表的微博 ID 列表。而微博 ID 和微博内容分别作为 key 和 value 也缓存起来。
此外,对于特别热门的微博内容,启用本地缓存模式:若用户粉丝在 100 万 以上,缓存其 48 小时内发表的全部微博。应用服务器在内存中缓存特别热门的微博内容,应用构建微博刷新页的时候,会优先检查微博 ID 对应的微博内容是否在本地缓存中。
数据库分片策略
微博的数据库我们采用分片部署的分布式数据库。分片的规则采用的是用户 ID(的 hash 值) 分片:一个用户发表的全部微博都会保存到一台数据库服务器上。当系统需要按用户查找其发表的微博的时候,只需要访问一台服务器就可以完成。
但是这样做也有缺点,对于一个大 V 用户,其数据访问会成热点,进而导致这台服务器负载压力太大。同样,如果某个用户频繁发表微博,也会导致这台服务器数据增长过快。
对于用这个问题,可以通过优化缓存来改善;而某个用户频繁发表微博的问题,可以通过设置每天发表微博数上限来解决。