美文网首页
一种Java后端集群限流(限带宽和qps)解决方案

一种Java后端集群限流(限带宽和qps)解决方案

作者: 魂之挽歌w | 来源:发表于2019-09-28 22:34 被阅读0次

  对于限流我们一般都是采用漏桶法和令牌桶算法,这两种方法说的官方一点肯定都是各有千秋的嘛,对于一般的限流肯定都能达到效果,本文这里只介绍令牌桶算法集群限流方案(这名字听着就靠谱,哈哈!)
下面介绍下令牌桶算法:

令牌桶算法
  令牌桶算法的思想很简单:例如,我们需要限制每秒的请求数量(qps),那么我们每次请求都需要申请令牌,如果令牌桶中没有令牌那么该请求就会拒绝或做其他处理,有则请求通过;而令牌桶在单位时间(一般为1s)内存在的令牌数是固定的,按照我们设置的速率进行生产,但最大不能超过桶容量,如果设置qps为10个/s,那100ms生产一个令牌,也就是平均100ms通过一个请求,以此来达到限流(qps)效果。在实际高并发业务场景中,直接舍弃过时的请求或者返回异常,让客户再次发送请求肯定是不合理的,用户体验极差,就跟现在政府机构一样,我们需要让客户“只跑一次”,所以通常来说我们可以返回一个等待时间,告诉这个请求:您好,我们收到了,现在有点忙,过会儿就给你处理,回去等消息吧,不需要再来啦!
限流简单理解
如上图所示,qps设置为100个/s,但实际我们在一秒内收到了120个请求,或许在0.8s就处理完前100个请求了,但后面的20个请求就只能延长到下一秒进行处理了。令牌桶算法最关键的就是对令牌的生产和消费,消费就是我们每次获取令牌后扣除桶中的令牌(这里令牌可以为负数,负数就延时嘛),对于生产可以有两种方案:
方案一:定时器生产
方案二:消费令牌时进行生产(需要用事务)
方案二比较灵活一些,我偏向与二,我们在申请令牌时可以记录下当前申请令牌的时间,申请令牌时,首先读取上次申请令牌的时间结合当前时间计算出该段时间生产的令牌+桶中现有令牌数,再与桶的容量取小即可。
  令牌桶算法直接在内存中创建完全可以解决单机限流问题,但是如果在分布式集群中限流就需要解决集群整体的限流效果了,其关键就在于对整体流量的统计,我们需要将所有节点的请求进行统计来达到总体限流效果,这时候我们的缓存数据库Redis就出场了,Redis最大的有点就是查询速度快,单线程,完全符合我们用来做数据记录载体的需求。我们选主节点Redis作为令牌桶的载体,所有节点对该节点redis进行读写操作,申请令牌。这里说明一下:限带宽和限qps是一个道理,只不过带宽令牌桶里存放的是数据量比如字节数,通过申请一定字节数来进行流量的控制。下面是简要的流程图:
集群限流数据统计同步方案
再贴一张简要流程图:
限流(qps+带宽)方案流程图
最后建议:
虽然redis读取效率很高,但每次请求都进行redis数据库操作还是有性能限制的,可以将令牌用map缓存到内存中,定时进行redis令牌桶更新处理。

相关文章

网友评论

      本文标题:一种Java后端集群限流(限带宽和qps)解决方案

      本文链接:https://www.haomeiwen.com/subject/zljeyctx.html