如何优化系统架构设计来缓解流量压力提升并发性能?

以直播互动为例:来感受读多写多情况下如何应对流量压力。

例如:QQ直播,微信直播,快手,B站、抖音......

这种属于一种实时互动服务,因为要求时效性很高,很多场景下无法用缓存来降低核心数据的压力。所以,为了降低这类互动服务器压力,我们可以从架构入手,做一些灵活拆分改造。

使用混合服务设计,直播场景可以分为可预估用户量不可预估用户量

1、可预估用户量服务:游戏创建房间

我们都有网游体验(QQ飞车,英雄联盟),创建房间的经历,这种设计主要是通过设置一台服务器可以开启房间数量上限,来限制一台服务器能同时服务多少用户。

从服务器端资源分配角度分析一下,创建房间是如何资源调配的:创建房间后,用户通过房间号就可以邀请其他伙伴加入游戏,房主和加入的伙伴都会通过房间的标识由调度服务统一分配到同一服务集群上进行互动。

开房间动作不一定需要用户主动完成,可以设置游戏开启自动分配房间。这样可以能提前预估用户量和掌控服务资源。

如何评估一个服务器支持多少人同时在线?

可以通过压测测试一台服务器的服务人数,以此精准的预估带宽和服务器资源,算出一个集群(集群里包含若干服务器)需要多少资源,可以承担多少人在线进行互动,再通过调度服务分配资源,将新来的房主分配到空闲的资源。

如上图,在创建房间阶段,我们的客户端在进图区域服务器集群之前,都是通过请求调度服务来进行调度的。调度服务器会定期接收各组服务器用户在线情况每,以次来评估需要调配多少用户进入

到不同区域集群同时客户端收到调度后,回那这调度服务给token,去不同区域申请出创建房间,房间创建后,调度服务会在本地集群内维护这个房间的列表和信息,提供给其他要加入 游戏的玩家展示。而加入的玩家同样会接入对应房间的区域服务器,与房主及同房间玩 家进行实时互动。 这种通过配额房间个数来做服务器资源调度的设计,不光是对战游戏里,很多场景都用 了类似设计,比如在线小课堂这类教学互动的。我们可以预见,通过这个设计能够对资 源做到精准把控,用户不会超过我们服务器的设计容量。

2、不可预估用户量的服务-直播-购物

有很多场景是随机的,我们无法把控有多少用户会进入这个服务器进行互动。

全国直播就无法确认会有多少用户访问,为此,很多直播服务首先按主播过往预测用户 量。通过预估量,提前将他们的直播安排到相对空闲的服务器群组里,同时提前准备一 些调度工具,比如通过控制曝光度来延缓用户进入直播,通过这些为服务器调度争取更 多时间来动态扩容。 由于这一类的服务无法预估会有多少用户,所以之前的服务器小组模式并不适用于这种 方式,需要更高一个级别的调度。 我们分析一下场景,对于直播来说,用户常见的交互形式包括聊天、答题、点赞、打赏 和购物等形式的体现出不同特点。

2.1、聊天:信息合并

聊天的内容普遍比较短,为了提高吞吐能力,通常会把用户的聊天内容放入分布式队列 做传输,这样能延缓写入压力。 另外,在点赞或大量用户输入同样内容的刷屏情境下,我们可以通过大数据实时计算分 析用户的输入,并压缩整理大量重复的内容,过滤掉一些无用信息

压缩整理后的聊天内容会被分发到多个聊天内容分发服务器上,直播间内用户的聊天长 连接会收到消息更新的推送通知,接着客户端会到指定的内容分发服务器群组里批量拉 取数据,拿到数据后会根据时间顺序来回放。请注意,这个方式只适合用在疯狂刷屏的 情况,如果用户量很少可以通过长链接进行实时互动。

2.2、答题:瞬时信息拉取高峰

除了交互流量极大的聊天互动信息之外,还有一些特殊的互动,如做题互动。直播间老 师发送一个题目,题目消息会广播给所有用户,客户端收到消息后会从服务端拉取题目 的数据。 如果有 10w 用户在线,很有可能导致瞬间有 10w 人在线同时请求服务端拉取题目。这 样的数据请求量,需要我们投入大量的服务器和带宽才能承受,不过这么做这个性价比 并不高。

理论上我们可以将数据静态化,并通过 CDN 阻挡这个流量,但是为了避免出现瞬时的 高峰,推荐客户端拉取时加入随机延迟几秒,再发送请求,这样可以大大延缓服务器压 力,获得更好的用户体验。 切记对于客户端来说,这种服务如果失败了,就不要频繁地请求重试,不然会将服务端 打沉。如果必须这样做,那么建议你对重试的时间做退火算法,以此保证服务端不会因 为一时故障收到大量的请求,导致服务器崩溃。 如果是教学场景的直播,有两个缓解服务器压力的技巧。第一个技巧是在上课当天,把 抢答题目提前交给客户端做预加载下载,这样可以减少实时拉取的压力。 第二个方式是题目抢答的情况,老师发布题目的时候,提前设定发送动作生效后 5 秒再 弹出题目,这样能让所有直播用户的接收端“准时”地收到题目信息,而不至于出现用 户题目接收时间不一致的情况。 至于非抢答类型的题目,用户回答完题目后,我们可以先在客户端本地先做预判卷,把 正确答案和解析展示给用户,然后在直播期间异步缓慢地提交用户答题结果到服务端, 以此保证服务器不会因用户瞬时的流量被冲垮。

2.3、点赞:客户端互动合并

对于点赞的场景,我会分成客户端和服务端两个角度带你了解。 先看客户端,很多时候,客户端无需实时提交用户的所有交互,因为有很多机械的重复 动作对实时性要求没那么高。 举个例子,用户在本地狂点了 100 下赞,客户端就可以合并这些操作为一条消息(例 如用户 3 秒内点赞 10 次)。相信聪明如你,可以把互动动作合并这一招用在更多情景, 比如用户连续打赏 100 个礼物。 通过这个方式可以大幅度降低服务器压力,既可以保证直播间的火爆依旧,还节省了大 量的流量资源,何乐而不为。

2.4、点赞:服务端树形多层汇总架构

如果我们的集群 QPS 超过十万,服务端数据层已经无法承受这样的压力时,如何应对 高并发写、高并发读呢?微博做过一个类似的案例,用途是缓解用户的点赞请求流量, 这种方式适合一致性要求不高的计数器,如下图所示

这个方式可以将用户点赞流量随机压到不同的写缓存服务上,通过第一层写缓存本地的 实时汇总来缓解大量用户的请求,将更新数据周期性地汇总后,提交到二级写缓存。 之后,二级汇总所在分片的所有上层服务数值后,最终汇总同步给核心缓存服务。接着, 通过核心缓存把最终结果汇总累加起来。最后通过主从复制到多个子查询节点服务,供 用户查询汇总结果。 另外,说个题外话,微博是 Redis 重度用户,后来因为点赞数据量太大,在 Redis 中缓 存点赞数内存浪费严重,改为自行实现点赞服务来节省内存。

2.5、打赏&购物:服务端分片及分片试试扩容

前面只要保证最终一致性就可以,但打赏和购物的场景下,库存和金额需要提供事物一致性。

因为事物一致性的要求,这种服务我们不做成多层缓冲方式,提供服务,而且这种服务的数据特征是读多写多,所以我们可以通过数据分片的方式是实现这一类服务。

可以按用户id做了hash拆分,通过网关将不同用户uid取模后,根据范围分配到不同分片服务上,然后分片内的服务队类似的请求进行内存实时计算更新。

、通过这个方式,可以快速方便的实现负载切分,但缺点是hash分配容易出现个别热点,

当我们流量扛不住的时候需要扩容。

但是hash这个方式如果出现个别服务器故障的话,会导致hash映射错误,从而请求到错误的分片,类似的解决方案如:一致性hash算法,这种算法可以对局部的区域扩容,不会影响整个集群的分片,但是这个方法很多时候因为算法不通过,无法人为控制,使用起来很麻烦,需要开发配套工具。除此之外,另外一种方式——树形热迁移切片,这是一种类似虚拟桶的方式,

比如我们将全量数据拆分256份,一份代表一个桶,16个服务器每个分16个桶,当服务器压力过大时,可以给这个服务器增加两个订阅服务器去做主从同步,迁移这个服务器的16个桶的数据,

待同步迁移成功后,将这个服务器的请求流量拆分转发到两个 8 桶服务器,分别请求这 两个订阅服务器继续对外服务,原服务器摘除回收即可。 服务切换成功后,由于是全量迁移,这两个服务同时同步了不属于自己的 8 个桶数据, 这时新服务器遍历自己存储的数据,删除掉不属于自己的数据即可。当然也可以在同步 16 桶服务的数据时,过滤掉这些数据,这个方法适用于 Redis、MySQL 等所有有状态 分片数据服务。

这个服务的难点在于请求的客户端不直接请求分片,而是通过代理服务去请求数据服 务,只有通过代理服务才能够动态更新调度流量,实现平滑无损地转发流量。 最后,如何让客户端知道请求哪个分片才能找到数据呢?我给你分享两个常见的方式: 第一种方式是,客户端通过算法找到分片,比如:用户 hash(uid) % 100 = 桶 id,在 配置中通过桶 id 找到对应分片。 第二种方式是,数据服务端收到请求后,将请求转发到有数据的分片。比如客户端请求 A 分片,再根据数据算法对应的分片配置找到数据在 B 分片,这时 A 分片会转发这个 请求到 B,待 B 处理后返回给客户端数据(A 返回或 B 返回,取决于客户端跳转还是服 务端转发)。

3、服务降级:分布式队列汇总缓冲

即使通过这么多技术来优化加架构,我们服务仍然无法完全承受过高的瞬发流量,

对于这种情况,我们可以做一些服务降级的操作,通过队列将修改合并或者做网关限流,

虽然这会牺牲一些实时性,但是实际上,很多数字可能没有我们想像中那么重要。像微博点赞统计数据,如果客户端点赞无法请求到服务器,那么这些数据会在客户端暂存一段时间,在用户看到数据时看到的只是短期历史数字,不是实时数字。

十万零五的点赞数跟十万零三千的点赞数,差异并不大,等之后服务器空闲了,结果追上来最终一致的,但作为降级方案,这么做能节省大量的服务器资源。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值