1、总体架构设计原则
去中心化
异步化
模块无状态化
拆分(数据拆分、服务拆分、部署拆分...)
容量规划、监控与工具自动化
服务化
针对具体业务做特殊优化
...
2、遇到的一些问题
单点故障
微博发表慢
微博数据量太大
大V用户发微博,推送给粉丝的时间延迟(指某些粉丝看到大V发表的微博的时间延迟)无法忍受
如何快速定位用户发表的某一页的微博?(微博数据假设已按月拆分)
复杂的关注关系(我的粉丝、我关注的、互粉、我关注的人也关注、共同关注等等)如何设计?
未读信息数如何设计?
...
3、上面问题的解决方案
3.1、单点故障
单点故障概念太宽泛,可以包括数据库节点单点、服务节点单点、Web服务器单点等,新浪微博为防止单点,主要采用MPSS(Multiple Port Single Server)技术,每个服务器上部多个端口,一个服务单元可以分布在三台机器上,以及去中心化技术:比如避免Master/Slave模式,因为Master节点存在单点故障问题
3.2、微博发表慢
采用异步化解决微博发表慢问题
3.3、微博数据量太大
数据量大,自然而然可以通过数据拆分(或者Sharding)来解决,关键在于如何拆。主要包含如下:
按用户ID拆,比如微博用户账户数据
可以按时间拆分,比如用户发表的微博数据
可以按业务拆,比如用户数据单独提出到一个数据库集群,微博数据提出到另外一个数据库集群
可以按冷热数据拆分
可以按哈希后的结果进行拆分,这种相当于又做了一次索引,能够加快访问速度
具体而言,是将新写入的微博数据放入Cache中,然后有一个定时任务轮询淘汰一段时间之前的缓存数据,并且自动将冷数据写入硬盘。
3.4、大V用户发微博时推送数据的时间延迟问题
业务上将用户划分为热用户(比如最近一天内登陆过的用户是热用户)和冷用户,大V用户发表一条微博后,只推送给粉丝中的热用户。粉丝中的冷用户等他再次登录微博时自己去拉取。这是一种典型的从业务角度进行性能优化的例子。
3.5、如何快速定位用户发表的某一页微博?(微博数据假设已按月拆分)
将用户每个月发表微博的条数、每月发表微博的最小ID和最大ID都记录下来,这样即可快速定位到分页数据(原理是根据该用户发表微博的最小ID以及每个月发表微博数、页大小计算)。其实相当于多建了一级索引。
3.6、复杂的关注关系如何设计?
新浪微博大量使用Redis,主要利用Redis的高性能、开源和丰富数据结构,关注关系同样用Redis来存储(主要是Redis Hash结构)。按多维度构建索引。
3.7、未读信息数如何设计?
基于偏移,记录用户已读取的消息ID(比如100)和系统该用户的最新ID(比如105),那么该用户未读信息数就是5。新浪微博开发了一个计数器服务来支持一些业务数据的计数。
4、一些架构设计原则说明
4.1、模块无状态
模块无状态最主要的是为了能够支持线性扩展或者水平扩展。
4.2、数据分级存储
访问越频繁的数据要放在用户越容易取到的地方。比如大V用户的微博数据直接放在本地缓存。用户自己最近发表的微博数据放L1 Cache。用户发表的历史微博数据按照发表时间分表放L2 Cache和数据库。等等。
4.3、服务化
按照业务数据内聚性拆分基础服务,比如微博数据基础服务、用户数据基础服务,这些基础服务构成服务层,服务层与分布式存储、分布式缓存、消息系统等中间件打交道,拆分服务除了带来复用性,还能避免业务集中瘫痪,也有利于针对单个服务进行升级;
服务层上面是应用层,应用层通过组合使用不同的基础服务来实现功能,它们也一般不需要直接与那些中间件打交道;应用层再上去就是API接口层,它们主要提供给第三方开发者使用。
4.4、容量规划、监控和工具自动化
这三个主要是运维层面来保障,是保证网站高可用性的前提。
容量规划比如根据业务数据增长量估算硬件资源消耗。
监控主要包括下面三方面:
硬件资源监控:对CPU、IO、内存、网络带宽等硬件资源的监控
业务接口监控:接口调用频率、接口调用成功比例等
工具自动化主要是因为人总会出错,所以尽量让一些任务通过工具进行自动化,从而也能大大减少重复繁杂的人力成本。
4.5、多机房数据复制问题
多机房数据复制问题主要包括数据延迟和数据一致性。一般有下面三种数据复制策略,新浪微博采用的第二种:
Master/Slave:单点风险,并且不同地区访问Master节点的延迟也不一样,不可接受
Multi-Master:多主节点,注意避免多个Master节点同时修改
Paxos算法:这个算法具体我不是很清楚(只在浏览网络博客时接触过),这种算法的最大缺点是延迟非常大
4.6、平台安全
主要划分为接口安全和内容安全,接口安全通过安全系统控制,内容安全通过权限系统控制。
安全系统包含两类安全处理措施:
实时处理:根据发布微博频率、内容相似度、敏感词匹配等处理
离线处理:离线分析处理