高并发系统中保护系统的三把利器:缓存、降级、限流
缓存:缓存的目的是提升系统访问速度和增大系统处理容量
降级:降级是当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心任务的正常运行
限流:限流的目的是通过对并发访问/请求进行限速,或者对一个时间窗口内的请求进行限速来保护系统,一旦达到限制速率则可以拒绝服务、排队或等待、降级等处理
对于系统中的接口调用,如果不考虑限流,会成系统的连锁反应,轻者响应缓慢,重者系统宕机,整个业务线崩溃。限流算法通常是为了限制qps。主要有如下几种:
基于信号量Semaphore
只有数量维度,没有时间维度。普通的并发访问控制策略如锁也属于这种。
基于固定窗口(fixed window)
带上了时间维度,但在两个窗口的临界点容易出现超出限流的情况,比如限制每分钟10个请求,在00:59请求了10次,在01:01又请求了10次,而从00:30-01:30这个时间窗口来看,这一分钟请求了20次,没有控制好。为了避免这种情况,可以要求在最后一个请求到来后的1/qps时间内部接受请求或让请求等待延后,不过此法导致这个等待时间内资源浪费。
基于滑动窗口(rolling window)
解决了fixed window没解决的窗口临界问题,主要有leak bucket算法、token bucket算法,前者不能应对突发流量(流量突发时对于超发请求只能丢弃或让之排队)。两种算法具体可参阅:https://blog.csdn.net/tianyaleixiaowu/article/details/74942405
漏桶:出水速度恒定,意味着对于短时打流量将有大部分请求被丢弃掉(即所谓的溢出)。出水速度恒定,所以更适合用于整流场景,使流向下游的流量整体稳定。
令牌桶:生成令牌的速度恒定,而请求去拿令牌没有速度限制。意味着面对瞬时大流量可以在短时间内请求拿到大量令牌,而且拿令牌的过程并不是消耗很大的事情。
上述限流算法都是指单机下的限流算法,对于分布式环境下不能直接适用。
参考资料:
https://segmentfault.com/a/1190000015967922
https://blog.wangqi.love/articles/Java/%E9%99%90%E6%B5%81%E6%8A%80%E6%9C%AF%E6%80%BB%E7%BB%93.html