高并发设计_限流

高并发设计

一思路

缓存、降级和限流。

1. 缓存

提升系统访问速度和增大系统能处理的容量。

2. 降级

当服务出问题或者影响到核心流程的性能则需要暂时屏蔽掉,待高峰或者问题解决后再打开

3. 限流

用来处理前面2种不能解决的情况,比如稀缺资源(秒杀、抢购)、写服务(如评论、下单)、频繁的复杂查询(评论的最后几页),因此需有一种手段来限制这些场景的并发/请求量,即限流。


##二限流

操作

###1. 操作
通过对并发访问/请求进行限速或者一个时间窗口内的的请求进行限速来保护系统,一旦达到限制速率则可以拒绝服务(定向到错误页或告知资源没有了)、排队或等待(比如秒杀、评论、下单)、降级(返回兜底数据或默认数据,如商品详情页库存默认有货)。
###2. 常见的限流
1. 限制总并发数(比如数据库连接池、线程池)
2. 限制瞬时并发数(如nginx的limit_conn模块,用来限制瞬时并发连接数)
3. 限制时间窗口内的平均速率(如Guava的RateLimiter、nginx的limit_req模块,限制每秒的平均速率)
4. 其他还有如限制远程接口调用速率、限制MQ的消费速率。
5. 根据网络连接数、网络流量、CPU或内存负载等来限流。

###3. 注意
1. 好处:不用担心瞬间流量导致系统挂掉或雪崩,最终做到有损服务而不是不服务;
2. 缺陷: 限流需要评估好,不可乱用,否则会正常流量出现一些奇怪的问题而导致用户抱怨。

###4限流算法

常见的限流算法有:令牌桶、漏桶。计数器也可以进行粗暴限流实现。


##三令牌桶算法

令牌桶算法是一个存放固定容量令牌的桶,按照固定速率往桶里添加令牌。
令牌桶算法的描述如下:

1. 假设按照100毫秒的固定速率往桶中添加令牌;
2. 桶中最多存放1000个令牌,当桶满时,新添加的令牌被丢弃或拒绝;
3. 当一个5个字节大小的数据包(5个请求)到达,将从桶中拿走5个令牌,接着数据包被发送到网络上;
4. 如果桶中的令牌不足5个,数据包大于等于5个,且该数据包将被限流,因为没有足够的令牌(要么丢弃,要么缓冲区等待)。

在这里插入图片描述

##四漏桶算法

可以用于流量整形和流量控制。
漏桶算法的描述如下:

1. 一个固定容量的漏桶,按照常量固定速率流出水滴;
2. 如果桶是空的,则不流出水滴;
3. 可以以任意速率流入水滴到漏桶;
4. 如果流入水滴超出了桶的容量,则流入的水滴溢出了(被丢弃),而漏桶容量是不变的。

在这里插入图片描述
##五漏桶算法与令牌桶算法比较

  1. 流入
    1. 令牌桶:固定
      1. 按照固定速率往桶中添加令牌,请求是否被处理要看桶中令牌是否足够,当令牌数不够则拒绝新的请求
      2. 允许一定程度的突发:一下子要处理很多请求
    2. 漏桶:任意
  2. 流出
    1. 令牌桶:任意
      1. 允许突发请求,只要有令牌就可以处理,支持拿多个令牌,并允许一定程度突发流量;
    2. 漏桶:固定
      1. 按照固定速率流出:按照固定的速度来处理
      2. 平滑突发流入速率:就是让高并发的请求按照固定的速度来处理

##六在我们项目中的应用
###1项目的环境
当前我们项目,当用户登录的时候,会触发10多个接口同时请求,当我们服务端向客户端推送消息后(参与活动有奖励),大量的用户(30W)在短时间内登录我们服务,会造成很大的数据库和接口请求压力。当然我们有做了优化。

  1. 一般固定不变的数据预先准备好
  2. 固定数据放缓存
  3. 特性数据(用户个性化推送数据),预先处理,定时刷新
    ###2使用借鉴漏桶算法
  4. 我们请求来源终端操作,且请求速度是任意的,为了让请求不丢失,我们一定要处理来只请求的所有数据,怎么让所有的请求不丢失呢,我们先把所有的请求放到阻塞队列中(桶),开启多个线程(线程池管理)执行队列中的任务(固定速度(一个时刻有几个线程处理任务)处理任务),并返回响应结果。
  5. 后期优化,原先我们处理请求的线程数是固定的,后来我们做了优化,我们对请求的数量做了一个梯度,当超过某个梯度的时候,我们会自动增加线程的数量,当然线程的数量不是可以无限增加的,最大的线程数和cpu,内存有关,当超过我们能处理的最大线程数的时候,我们开启等待队列,将所有新的请求放到等待队列中,同时开启请求优化服务,将那些请求能个短时间返回结果的请求优先执行,那些要花大量时间的请求,我们对响应的接口做了服务降级。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章