Fork me on GitHub

高并发之缓存、限流、降级

首先必须要从代码层面上提升性能,利用缓存等,如果在访问量大,确实无法处理的情况下就要考虑限流,或者防刷也是要考虑限流,然后如果服务确实不可用的话就把服务进行降级,比如当无法获取评论信息的时候,但是写的朋友圈是要正常返回的。不能因为评论服务无法提供,连朋友圈也不能看了。

缓存

可以通过注解把技术相关的,读缓存,写日志,写缓存的功能,使用注解加反射来进行操作。

伪代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
Cache cache =getCache();

if(cache!=null){
return cache;
}

Data result= getDatabase();
lg.info("获取数据");
if(result!=null){
setCacheData(result)
}

return result;

业务上,实际只有getDatabase才有用。

伪代码:

1
2
3
4
5
6
7
@getCache()
@setCache()
@log()
public getData(){
Data result= getDatabase();
return result;
}

通过注解反射如果有getCache的话直接使用缓存中的数据,如果有直接返回,如果有log写日志,如果有set则把获取到的数据写到cache中。

1
2


限流

限流瞬时流量

双11,秒杀,之类的属于瞬时流量很大,平时相对稳定。

限流总并发量

限流平均流量

  • 滑动窗口

  • 令牌桶,每秒生成n个,限制平均流量

  • 漏桶,这个是应对瞬时流量过大的一种方法,一定的速率进行消费,MQ,削峰,解耦,异步。但是能解决的瞬时流量也是有一个最大值。

  • 计数器,限制总的并发数,比如说每秒钟只能请求100次,是限制总并发量。通常可用redis缓存,请求增加incr来实现。

采用:Google开源工具包Guava提供了限流工具类RateLimiter,该类基于令牌桶算法来完成限流,非常易于使用。

降级

当服务调用者使用同步调用的时候,会产生大量的等待线程占用系统资源,一旦线程资源被耗尽,
服务调用者提供的服务也将处于不可用状态,于是服务雪崩效应产生了!
这时候就需要比如说:当失败了多少次之后,

1,超时机制
2,服务限流
3,服务熔断
4,服务降级

超时机制
如果我们加入超时机制,例如2s,那么超过2s就会直接返回了,那么这样就在一定程度上可以抑制消费者资源耗尽的问题

服务限流
通过线程池+队列的方式,通过信号量的方式。比如商品评论比较慢,最大能同时处理10个线程,队列待处理5个,那么如果同时20个线程到达的话,其中就有5个线程被限流了,其中10个先被执行,另外5个在队列中

服务熔断
这个熔断可以理解为我们自己家里的电闸。
当依赖的服务有大量超时时,在让新的请求去访问根本没有意义,只会无畏的消耗现有资源,比如我们设置了超时时间为1s,如果短时间内有大量请求在1s内都得不到响应,就意味着这个服务出现了异常,此时就没有必要再让其他的请求去访问这个服务了,这个时候就应该使用熔断器避免资源浪费

服务降级
有服务熔断,必然要有服务降级。
所谓降级,就是当某个服务熔断之后,服务将不再被调用,此时客户端可以自己准备一个本地的fallback(回退)回调,返回一个缺省值。 例如:(备用接口/缓存/mock数据),这样做,虽然服务水平下降,但好歹可用,比直接挂掉要强,当然这也要看适合的业务场景

文章目录
  1. 1. 缓存
  2. 2. 限流
    1. 2.0.1. 限流瞬时流量
    2. 2.0.2. 限流总并发量
    3. 2.0.3. 限流平均流量
  • 3. 降级
  • ,