从头搭建一个“微博”有多难

article/2025/8/21 4:52:10

本文始发于个人公众号:TechFlow,原创不易,求个关注


今天是分布式专题的第13篇,今天的文章我们不讲空洞的理论,来聊一个实际点的问题。

众所周知,微博的程序员经常不定期加班。和别的程序员不同,别的岗位的程序员可能加班是可控的,但是微博的程序员不是。为什么呢?因为程序员们无法预知明星们什么时候有新的大料产生,一旦有新料,微博崩溃是妥妥的。甚至很多粉丝用微博有没有崩溃来衡量一个明星的知名度。

这当然只是个段子,但是对于我们搞技术的来说总忍不住问一个问题,微博也算是一个蛮大不小的公司,不缺钱也不缺人,为什么系统这么不稳定呢?

当然我没有在微博呆过,为了严谨起见,我们假设我们现在开了一个类似的新的app,就叫做微特好了。我们来看看微特这个app从0开始成长的过程当中究竟会遇到哪些问题。通过微特这个虚假的项目,我们多少也可以推测一下微博不稳定背后的原因。

微特的诞生

某年某月某天,微特诞生了,为了简化问题,我们假设微特只有两个功能,就是发微特和看微特

刚刚诞生的小企业嘛,请不起知名的架构师,当然是怎么简单怎么来。我们拆分一下功能,会发现一共只有三个功能,用户发微特、关注其他用户和查看微特,这三个功能都很简单,几乎就是裸的增删改查,我们一个一个看。

先看用户发微特,用户发微特我们只需要用一张表记录微特的内容即可。这个表呢大概长这样:

第二个功能是关注用户,我们再用一张表记录一下用户之间的关注关系即可,这也非常简单:

有了这两张表之后,我们要查看微特就简单了,我们只需要通过userid去关注表里面去关联关注的用户,然后在用关注的用户的id去关联发过的微特即可。

我们用SQL来表示一下这个查询关系。

select wetwi.*
from (select followeeidfrom followerwhere followerid = curid
)a join wetwi
on a.followeeid = wetwi.userid

经过一番测试之后,微特顺利上线,老板试用了一下,觉得很满意。新用户也涨得很快,负责的程序员A得到老板的赏识,一路晋升上去变成管理层,不再直接负责项目的技术问题了。

此人的一个手下B被委以重任,负责起了项目,但是就在这个时候,问题出现了。

微特一阶段

随着用户数量的增大,用户们关注的数字开始了迅速增长,很快平均一个用户都关注了好几十个其他用户。每次用户刷新的时候,都会同时加载这好几十人发布的微特内容。加上微特支持图片,最多的时候一时刻需要加载好几十张图片和大量文本,服务器来不及传输这么多数据,频繁的有用户反馈说刷新的时候总是超时。

B想了想,这个简单啊,我们可以分成开源和节流两步。

首先我们需要开源,除了加大机器数量之外,我们需要租借CDN,将用户上传的图片放到CDN上而不存储在数据库里,从而加速数据传输的速度。

节流怎么办呢,也简单我们再用一张表来存储用户最近一次刷新的时间。这样我们在查询的时候,只需要查询这个时间点之后的数据就行了。于是我们多了一张记录时间的表。

这么一搞,系统总算稳定住了,用户抱怨的人数进一步变少。很快用户量又有了爆炸式的提升,终于有一天,热点事件一个接着一个,系统终于扛不住了,接二连三地宕机。

为什么会宕机呢?

因为数据库的查询需要时间,本来就比较慢,加上了join操作之后,系统变得更慢。现在由于要判断微特发送的时间来做过滤,额外增加了一次查询,到达瓶颈之后自然就扛不住了。

B绞尽脑汁,终于想到了办法,就是缓存。他缓存了用户最后一次刷新的时间,这样就可以减少一次数据库的查询。系统稍微变快了一点,但是并没有坚持多久,终于老板忍无可忍开除了B,花大价钱从大公司挖来了一个架构师C。

与此同时,微特的用户量进一步增长,到了第二个阶段。

微特二阶段

C熟悉了环境之后,气得直骂娘,不从架构考虑问题,只会修修补补要不得啊。怎么可以直接用DB存储数据呢,搞成这样不崩溃才有鬼。

新官上任三把火,搞走了几个混吃等死的老白兔,C又招来当年的几个手下,开始大张旗鼓地重构系统。在分布式系统当中,DB往往都是瓶颈,能不用DB的就不应该用DB。而且微特的模式非常明显,用户发布了新内容之后,最关心的就是他的粉丝,那么我们直接在他更新的时候,就把内容推送到粉丝的缓存里,当用户刷新的时候,直接从缓存拉取数据,这不是要方便得多吗?

C画出了新的架构图(可见C也是灵魂画手):

微特直接通过kafka等消息系统推送给用户,效率要比DB高多了,C的一帮手下也给力,很快就完成了架构升级。上线之后,果然效果非凡,系统立刻变得稳定了许多,用户抱怨大幅减少。

在这几年里,公司声名鹊起,积累了大量的资源,一举去美国上市了。公司的高管都财富自由了,C来得晚没分到多少,并且看到当年埋了大坑的A混的风生水起,加上长久以来的不和,气不过跑路了。

就在这风生水起的时候,意想不到的事情又发生了。而我们的微特也来到了阶段3。

微特三阶段

C走了之后,系统从此再也没有大的改动,大家都只想把眼前修修补补的工作做好。反正公司也上市了,老板也自由了,底层的员工只想安安稳稳赚点工资。加上系统也稳定得很,没有人觉得有什么改动的必要。

但是由于微特现在太火了,使用的用户越来越多,除了普通用户之外,还把明星艺人吸引来了。这些明星艺人,一个个都有好几千万的粉丝。不是之前升级了架构,改成了通过kafka推送消息而不是去DB查询吗?这下好了,这些明星每次一发微特,都需要发送好几千万次消息。

有几天不知道是过节还是碰巧,这些明星艺人偏偏一起发推,直接就把发送消息的系统挤压挂了。这一挂,虽然微特整个系统没有崩溃,但是吃瓜群众发现再也搜索不到微特了。于是一起在网上骂微特,这一骂,需要发送的消息更多,系统更加扛不住,彻底成了死循环,公司的口碑急转直下。

公司也想解决这个问题,奈何之前做了太多修修补补的工作,整个系统变得非常复杂,很多模块耦合在了一起,加上也没有一个很好的方案,一直也没有一个人下得了决心整个重构,反而往上加了更多补丁

直到后来,A离职了之后,公司新来的CTO招来了一个业内技术骨干D。D提出了新的想法,将前面两种方案作了折中。大V发送的时候,并不推送到所有粉丝,而是只推送给当前在线的粉丝。离线的粉丝还是通过查询来获取数据。这样一来对流量进行了分流,微特系统变得稳定了许多。

但是这并没有真正彻底解决问题,系统仍然有时候会宕机,但是一时半会也没有什么特别好的办法,系统也变得极为臃肿彻底经不起折腾。于是微特就这样修修补补,变成了程序员加班不规律的公司。

后续

所谓的微特当然是个段子,故事也不是真的,但是技术架构的变迁还是很有参考意义。一个看似简单的问题,真正落地到应用场景当中,往往没有那么简单。系统眼前的稳定也不能代表长远,这也是我们在开始一个项目的时候就需要眼光长远做好规划的原因。更是一个优秀的架构师的价值所在,只不过可惜的是,世上的道理总是这样,知道的人太多,做到的太少。

希望今天这个的这个故事在博君一笑的同时也能给大家一点启发,一个成功的优秀的系统背后,究竟藏着多少思考和心血呢?

今天的文章就是这些,如果觉得有所收获,请顺手点个关注或者转发吧,你们的举手之劳对我来说很重要。

在这里插入图片描述


http://chatgpt.dhexx.cn/article/wwcgJZeV.shtml

相关文章

劫持流量是什么,常见的流量劫持手法有哪些呢?

网络流量劫持是什么?其实就是大坏蛋动用一切技术手段,当亲们输入一个网址然后点击回车的时候,把亲们忽悠另一个网站上去哦,或者向亲们原本想访问的的网站内容里加点花椒大料。 IIS7网站监控可以及时防控网站风险,快速准确监控网站是否遭到各种劫持攻击,网站在全国是否能正…

html时分选择器,HTML常用标签+CSS选择器-2018年8月14日20时20分提交

实例 HTML>标签的使用及布局 body{ width:auto; height:auto; padding: 0px; margin: 0px; font-weight:bold; background-color: #0d0410; }/*宽、高设置自动,内外补丁设置0PX,字体宽度默认,背景颜色黑色*/ a{ text-decoration: none; co…

私厨菜谱app的设计与实现(二)

一.准备工作 1.注册API账号 2.添加第三方依赖 首先添加首先添加RecyclerView、OkHttp、 Glide、Gson的依赖 implementation com.android.support:recyclerview-v7:28.0.0 implementation com.squareup.okhttp3:okhttp:4.4.0 implementation com.github.bumptech.glide:glide:4.…

Node.js学习(三)常用模块与网络爬虫

学习视频 Node.js学习(一)介绍 Node.js学习(二)异步、缓存区、文件系统 path模块 nodejs中,提供了一个path模块,在这个模块中,提供了许多实用的、可被用来处理与转换文件路径的方法和属性 什么…

Escript氨基酸对比图怎么看_23张和田玉真假皮色对比图,看懂了再也不怕被坑

在玉石珠宝这个行业中,利益的驱使常常使很多商贩有各种各样不同的手段来造蒙骗。不管哪一个品种里有或多或少的假货掺杂。比如和田玉,假皮种类形形色色、多种多样。如果是初学者,辨别其真伪的确有一定难度,高科技下的造假皮色&…

鹅肉是凉性还是热性 鹅肉怎么做好吃

鹅肉鲜嫩味美,很多人都非常爱吃,那么你知道鹅肉是凉性还是热性吗?鹅肉怎么做好吃呢?一起了解一下。 鹅肉是凉性还是热性 中医认为,鹅肉性平、味甘,具有益气补虚、和胃止渴、止咳化痰,解铅毒、祛风湿、防衰老等作用…

红烧肉怎么做好吃 红烧肉的做法

很多人都爱吃红烧肉,入口香味浓郁简直是人间美味啊,那么红烧肉怎么做好吃呢?红烧肉的做法了解一下。 原料 猪带皮五花肉 调料 葱姜蒜、八角、桂皮、小茴香、花椒、绍酒、盐、酱豆腐汤、酱油、冰糖、干辣椒 做法: https://www.chachaba…

素饺子馅的做法大全 素饺子馅如何做

素饺子,要的就是一个“素”字,寻常百姓家,希望新的一年没有什么大起大落,平平安安,用天津话就是“素素静静过一年”。素饺子馅儿有白菜,豆腐干儿,香菜,木耳,粉条&#xf…

我用Python爬取美食网站3032个菜谱并分析,没有我不会做的菜!

这是巨变的中国,人和食物,比任何时候走的更快。近日,J哥为了寻味中国,奔走于某五线城市的大街小巷,结果除了累,啥也没寻到。 于是,J哥默默打开了各大美食网站,如豆果美食、下厨房、…

【知识图谱导论-浙大】第二章:知识图谱的表示

前文: 【知识图谱导论-浙大】第一章:知识图谱概论本节内容的视频讲解如下: 【知识图谱理论】(浙大2022知识图谱课程)第二讲-知识图谱的表示 什么是知识表示 简而言之,知识表示(Knowledge Representation, KR)就是用易于计算机处理的方式来描述人脑知识的方法。KR不是…

我用Python爬取美食网站3032个菜谱并分析,真香!

这是巨变的中国,人和食物,比任何时候走的更快。近日,J哥为了寻味中国,奔走于某五线城市的大街小巷,结果除了累,啥也没寻到。 于是,J哥默默打开了各大美食网站,如豆果美食、下厨房、…

JLink重刷固件(win7/win8/win10亲测可用)

转 [转]JLink重刷固件(win7/win8/win10亲测可用) 2017年09月12日 14:31:55 醒着的树懒 阅读数:6329 去年刚刚用上J-link的时候坏过一次,当时在网上也看了很多重刷固件的方法,但绝大多数的都是win7甚至有些需要xp&#…

洋姜的腌制方法 怎样腌制洋姜好吃

怎样腌制洋姜好吃?提到洋姜很多人都很喜欢吃,洋姜吃法很多,但是最广为人知和受欢迎的就是腌洋姜了,味道佳营养丰富。下面本文来讲解一下洋姜的腌制方法: **洋姜的腌制方法**材料:洋姜、水、花椒、丁香、桂皮、食盐 做…

香料图片加名称及其作用

良姜:别名小良姜、高良姜(中药材,本品为姜科植物Alpinia officinarum Hance)基原物料的生态:多年生草本。根茎圆柱形, 其性温、味辛;具有芳香气,有节,节处有环形膜质鳞片…

BlogEngine.net---httpHandlers与httpModules

httpHandlers是什么?httpModules又是什么?原来我都不知道,只得先搞清楚这两样,再来研究blogengine了。Two Interceptors:HttpModule and HttpHandlers 这是我在codeproject上搜到的标题,翻译过来是两个拦截器&#xff…

jquery html解码字符串,jquery如何编码和解码url?

jquery如何编码和解码url?下面本篇文章给大家介绍一下用jquery编码和解码url的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 在jQuery中,我们可以使用以下方法实现URL的编码和解码:encodeURIComponent(url) :可把字符串作为 URI 组件进行编码。…

Node-JS-第三方模块.0603

1.什么是第三方模块? 写好的、具有特定功能的、我们能直接使用的模块即第三方模块,由于第三方模块通常都是由多个文件组成并且被放置在一个文件夹中,所以又名包。 1.1 第三方模块有两种存在形式: 以js文件的形式存在,提供实现项目具体功能的API接口。 以命令行工具形式…

node.js

nodeJS 学习方法 掌握思想 ​ 编程思想很重要,语言只是工具。不仅仅只是记住了API。 查资料的方式 ​ API文档:比二阶段的API多出了3倍多。 https://blog.csdn.net/jiang7701037/article/details/95734911?ops_request_misc%257B%2522request%255Fi…

nodejs知识点总结

nodeJS 1、搭建服务器 2、mongodb 用 注册和登录增删改查新闻(bootstrap) 3、api server 注册和登录增删改查新闻(bootstrap) 4、bcrypt加密 注册和登录 5、session 登录和其它需要验证身份的模块(如:添加,删除) 6、token 登…

5.2jquery案例2

1.仿qq列表分组 <!DOCTYPE HTML> <html> <head> <meta http-equiv"Content-Type" content"text/html; charsetutf-8" /> <title>好友列表</title> <style type"text/css"> body{font-family: "微…