美拍:大中型 SNS 系统设计漫谈 | UPYUN Open Talk NO.4

图片描述

洪小军 美拍架构平台负责人前端

业务系统架构演化

1、计数器服务mysql

谈到业务系统的架构,首先要说计数器服务,虽然看起来是个小功能,若是将计数器整个历程和深层次的东西掌握清楚,会发现不少东西是相通的。经过简单的业务,挖掘背后的技术,是一个很好的学习过程。redis

SNS最重要的就是社交关系,以及用户信息。在美拍你能够看到美拍评论,有评论数、点赞数,微博有评论数、转发数、点赞数,这些都须要经过计数器来完成。sql

图片描述

一、实现计数器最粗暴的方式:数据库直接count

一些产品在开始上线的时候,会用很是粗暴的方式——在数据库中把数据count出来。数据库

计数器服务在SNS系统中属于TOP级别的访问大户,甚至是TOP1,这个简单粗暴的方式天然会面临一些问题:由于没有独立的计数器,每次都须要从数据库count,会出现大量慢查询、慢请求问题。后端

二、大部分公司经常使用的方案:独立的计数器表

上面粗暴的计数器方式,没有独立的计数器,每次都要从数据库count。而今大部分公司或系统会独立维护计数器,创建计数器表,包括ID表和纯计数表,每次变动都须要update,与此同时前面还有一个memacached,用来扛大量热的请求。这个方案在前期没有什么问题,但发。展到一段阶段,会出现不少接口响应时间过长的问题。缓存

回到SNS系统的特色,数据库中会有大量的update/select操做。好比美拍,某一个明星发了一条信息,瞬间会有不少评论、点赞,计数表会频繁的update。另一种状况是,大量的信息是没有被评论和转发。SNS系统只要存放这些评论和转发数等于0的数据,就会有大量的select,这就须要缓存的容量足够大,将全部的数据装进去。性能优化

SNS系统还有一个特色,就是长尾特性很明显,数据分布上有一条很长的尾巴。好比最近三个月占90%,好比第四、五、6个月,占比是很均衡的,这就是长尾的特色,这对缓存提出很大的挑战。假设你可能要保证缓存命中率90%,可能要花5G内存,若是到95%,就须要10G,若是要到99%,可能就要100G或200G,这就对容量提出很高的要求。架构

可进行的优化:并发

数据库合并写入,即程序段合并写入请求,有起到必定效果,可是不会太明显。
缓存金扩容尽量存放更多数据,但因为SNS系统的长尾效应仍是很难达到很是高的命中率。

三、必定规模公司采用的方案:Redis内存存储

3.1 架设在内存基础上的架构

图片描述

内存缓存,从请求的访问策略来看,从缓存读取,cache不到,再从mysql读取;命中率取决于它的容量。若是是内存存储,命中率是100%。对于容量要求,不少地方会说存储须要的容量比缓存大不少,但在具体的产品中并不彻底是这样。好比,在计数器服务中,采用存储的方式,50%的美拍是没有评论的,存储只须要存50%有被评论过的就足够了。可是采用内存缓存的方式,是没有这个策略的,可能须要存不少没有被评论过的信息。

Redis 内存存储:

图片描述

Redis是全内存存储,在SNS系统计数器中只需存存放全部计数器>0的数据 ,具备高速的读取性能,保证接口的响应时间可控,这也是大多数公司采用的方案,也比较可控。

3.2 长尾数据
随着时间增加,会出现大量的长尾数据,尤为是SNS系统,就像微博发展四、5年前的数据特别多,所有写入内存成本过高。长尾访问,不须要用内存这么高的成本去支撑。

长尾问题解决方案:
1)作冷热数据分离,将最近个月的数据放在内存,更早的宕到SSD上,成本比较低,这是一个折中方案;
2)经过修改redis,实现更紧凑的存储。

2、FEED服务

FEED业务指的是,好友的消息列表,美拍上的好友动态,微博就是首页的列表。FEED经常使用推、拉两种模式。

推模式:

推模式写入消息的成本会比较高,至关于发一条美拍须要推给全部关注我美拍的人。推的数量取决于有多少人关注我。相反获取信息的成本很是低,只需简单的SELECT就能够取出来,推模式是基于空间去换时间的策略。

在这种状况下,须要考虑3个问题:
1)容量是否会成为瓶颈;
2)推送量大的状况下,会出现延迟问题;
3)加关注/减关注这类变动通知的成本很是高。

拉模式:

拉模式是和推模式相反的方式,轻量写入。获取消息,先将关注的列表取出来,再将关注的每一个人反的美拍列表取出来,最终合并。这是用时间换空间,拉取须要不少计算,会影响到接口的响应时间,须要大量的计算,须要获取大量的资源,这样会形成需求的带宽增多。

所以,在好友多、粉丝少的状况下,推的模式最好。好友少和粉丝多的状况,比较适合拉的方式。

如今的SNS系统大多都是好友多,粉丝又多。在这种状况下,一些业界公司采用了推拉结合的方法,好比Twitter。普通用户(粉丝数少的用户)采用推的方式,大V采用拉的方式。

在发布信息的时候会经过粉丝数及其余策略包括是否在线等情况作推拉的判断。微博,公开性的微博都是基于拉的方式,私密性的功能,都是基于推的方式。

FEED服务中的重点:

FEED服务中数据库和缓存是两个很重要的点。
在业务快速发展的阶段,须要频繁的增长新的产品属性,每一个属性都须要在线变动,这样会对在线用户产生影响,同时也很增长成本。
经常使用的解决方法:索引和内容分离,各司其职。索引保证高效的查找,全部的查找都在索引里完成。索引可能会有不一样级别、维度的索引。内容使用KV结构(V为二进制数据),便于数据变动。在这里内容须要尽量紧凑的存储。

数据库定位:

数据库只是做为存储,不该该有任何逻辑,由于系统追求的是高性能的读取访问。最多有V条件,不该有任何业务逻辑,业务逻辑应该放到程序端处理。

数据库面临很大的写压力,经常使用的是分库分表的方式,但会出现两个问题,大部分数据库都有自身的IP,跟其余的表关联,分库分表就不能用智能IP,可能会形成IP冲突。

分库分表策略:

最多见的就是,每一个库里都有N张表,基于HASF分表。但到必定阶段会出现一些问题:

1)特殊用户查询性能很高,这种用户可能有几百万甚至上千万的记录,一旦穿透到数据库,性能会很糟糕。
2)到必定规模后,会考虑进行硬件的升级,若是将全部的历史数据存放SSD,很浪费。

为解决这个问题,不少公司采用了基于时间分片的方案。最好的方法是创建一个索引表,在索引表里存放每月用户有多少条数据。

3、缓存:雪崩

说道缓存,先补充一个雪崩的概念。

假设系统有4,5个节点,每一个缓存节点命中率是90%,也就是每一个节点要承担接近20%的访问量,若是这个时候有1个节点坏了,这个请求会所有打到memacache,整个系统极可能就直接宕掉。这就是所谓的雪崩。

解决方案:

一、在这个阶段,程序端作两节缓存,使得请求在某个节点坏掉了的时候,不会直接到memache,而后请求另一个节点。
二、随着业务增加,须要扩充。解决方法:
1)扩充节点到20个,但可能出现multiget hole问题,在这种状况下,致使性能降低。
2)搭建多集群。

系统设计的基本原则

CAP原则:一致性、可用性、可扩展性
在SNS场景中,每每上面的三个点,只能选择其中两个,须要必定的折中。最主要的是扩展性和可用性。固然不是说一致性不重要,能够采用最终一致的方法作补充。

前期:快速搭建系统上线。

中期:重点解决可扩展性问题。
经过硬件升级、单机性能优化,提升单机性能,以及采用SACLE分布式支持,能够解决扩展性问题。
SNS系统高可扩展性须要关注如下几个点:

一、支持高并发读取,首先第一点就是支持大量级的接口调用。其次还须要保证很低的响应时间。

二、支持峰值的写入。最重要的一点是先后端分离,前端处于永远可写的状态。(用户成功发布内容后,显示成功,实际并无彻底成功,后面的事情交给后端去作)
三、作好分布式部署,包括一个机房内部多集群,最好是有条件作到多机房。多机房部署,要保证每一个机房之间有可靠的消息同步,要避免跨机房读调用。
(多机房如何将主要资源同步:SYSQL可采用master方式,Redis有条件的可采用master/salve方式)

中后期:不少系统须要解决可用性问题。 可用性问题比前面的问题都更加有挑战。 一、避免单点故障。 二、保证响应时间。

相关文章
相关标签/搜索