一个分布式限流系统的设计思路

70 篇文章 0 订阅
37 篇文章 0 订阅

问题背景

今天在参与面试的时候,候选人提到了一个他们项目做的一个项目中使用的限制系统的设计。大致思路如下,通过一个配置中心去获取每台机器的配额,然后本地做限流。当时就被挑战了这个思路,如果其他机器挂了,如何快速感知?马上就没答上来了。基于这个话题,今天想来简单分析一下,一个限流系统的设计思路。

基本算法

1、先讨论最简单的场景,单台机器,用什么方式来限制流量?通常一个非常简单的做法,暂且叫它为时间哈希法
描述如下:例如每秒100次,那我用时间戳做key, 每次请求对这个key进行自增操作,并判断这个value值是否会会大于100这个值,如果是大于,则触发限流逻辑。
存在问题:
1)如果在t=0.9s~1.0s这0.1S内,收到了100次请求,不会触发限流。如果t=1.0S到1.1S内,收到100次请求,由于是一个新的时间key,也不会触发限流,那在t=0.2S到1.2S这1S时间内,则收到了200次请求,超出了限流值。
2)或者你会想到,那我把时间粒度再切分细一些,按0.1S允许10个请求。这样又会引入另一个问题。我如果在1S内,前0.9S没有请求,最后0.1S如果来100个,那就会有90个被限制,无法应对突发流量问题。

2、令牌桶算法
这是网络中处理流控的一个经典算法。这个算法的描述参考维基百科token bucket,这里简单描述如下:

A token is added to the bucket every 1/r seconds.
The bucket can hold at the most b tokens. If a token arrives when the bucket is full, it is discarded.
When a packet (network layer PDU) of n bytes arrives,
if at least n tokens are in the bucket, n tokens are removed from the bucket, and the packet is sent to the network.
if fewer than n tokens are available, no tokens are removed from the bucket, and the packet is considered to be non-conformant.

分布式业务系统

现在把问题扩大一些来讨论。如果你的业务系统不是一台机器,会有多台机器,假设有四台机器,限流系统假设还是一台机器,这种场景如何设计?

方案一

每次业务系统请求的时候,都来限流系统中询问一下,是否已经超过流量限制。这样本质上跟单机系统没有什么区别,存在的问题在于:网络开销是不是太大,有没有必须每次都去询问?

方案二

三台业务机器,能否开始的时候,就把每台机器分配一个配额,然后每台业务机器自己通过本地来做限流。(来面试的同学在他们线上就是用这种方案)这种方案问题也比较明显:如果其中某如机器挂了,那就是无法自动适配总流量,会让系统的流量限制变成更小,例如原先每台机器限制25,总共限100,那死了一台机器,则总流量会被限制成75。

方案三

令牌桶算法的延伸。每秒去请求一次服务器,去服务器端拿令牌数。令牌数则是由限流系统来分配。初始值的时候,可以按照平均分的方式来分配。例如:第t=0s时刻,A、B、C、D服务器都去获取令牌,每个业务服务都能获取25个令牌。每次令牌快消费完的时候,去向限流服务请求令牌。
两个异常场景:
1、如果四台服务器流量不平均,如何解决?
2、如果某台机器挂了,如何将限流额度分摊到其他机器?

解法一:
通过在限流服务中去统计每个服务的请求次数,去按比例分配令牌。例如:过去10S钟内,A、B、C、D去请求的次数分别为20、10、5、5。那下一个10S周期内,则A、B、C、D来请求的时候,令牌数就按照20/40,10/40,5/40,5/40这个数量来分配。如果某台机器挂了,那么在一个周期内他的请求次数必为0,那必须额度会被其他机器所分掉。问题1、2得到解决。

解法二:
解法一曾经拿出去与人讨论过,被挑战到:我作为限流系统,我为什么还需要关注谁来请求,我这样是不是设计会非常复杂?
于是有了如下方案:按一个经验值来算,例如每次请求时候,就直接分配20的配额。然后谁用得快,谁就勤快些过来取,这样是不是就比较好的解决了限流的复杂性问题。

分布式业务&分布式限流

上一个问题中,还假设限流系统是单点,如何解决限流系统的可靠性问题?

方案一

通过主备方式:两台服务器做成主备,通过客户端心跳感知的方式进行主备切换。
存在问题:如果主挂了,那么系统访问备。但如果只是某一次心跳抽风,那某台机器可能就访问到备机了,那么此时,就可能主备都在工作,限流逻辑失效!

方案二

主备两个服务,只允许一个进行工作,引用分布式锁解决问题。
通过主备启动的时候,抢占到分布式锁的服务优先对外服务。通过引入一个分布式锁来解决主备同时工作的问题。

扩展性

如果需要访问的节点足够多的情况下,限流服务如果扛不住,如何扩容?
简单的办法,可以通过再多一层的方式。我一层作为总的配额,然后二层水平扩展为多实例,通过多实例对外服务。

总结

至此,目前能考虑到的问题已经罗列出来,如果有哪些没考虑到或者逻辑上有问题的地方,请大家指正!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值