限流-分布式

652 阅读2分钟

之前介绍的都是单机。如果提供接口的服务是集群,那怎么办?

那这个时候,只能是分布式限流。

核心

1.时间 1s
2.次数 1000次 //这个是计数器

就是把这2个数据,弄到一个中心化的地方存储,而不是在一个服务里面,这样就解决了集群/分布式服务的限流问题。


限流算法分布式改造: 分布式限流算法

相对于单机限流算法,分布式限流算法的是指: 算法可以分布式部署在多台机器上面,多台机器协同提供限流功能,可以对同一接口或者服务做限流。分布式限流算法相较于单机的限流算法,最大的区别就是接口请求计数器需要中心化存储,比如我们开源限流项目 ratelimiter4j 就是基于 Redis 中心计数器来实现分布式限流算法。

分布式限流算法在引入 Redis 中心计数器这个独立的系统之后,系统的复杂度一下子高了很多,因为要解决一些分布式系统的共性技术问题:

  1. 数据一致性问题
    接口限流过程包含三步操作:

Step 1:“读”当前的接口访问计数 n;

Step 2:”判断”是否限流;

Step 3:“写”接口计数 n+1, if 接口限流验证通过

在并发情况下,这 3 步 CAS 操作 (compare and swap) 存在 race condition。在多线程环境下,可以通过线程的加锁或者 concurrent 开发包中的 Atomic 原子对象来实现。在分布式情况下,思路也是类似的,可以通过分布式锁,来保证同一时间段只有一个进程在访问,但是引入分布式锁需要引入新的系统和维护锁的代码,代价较大,为了简单,我们选择另一种思路:借助 Redis 单线程工作模式 +Lua 脚本完美的支持了上述操作的原子性。限于篇幅,不展开代码讨论,详细可以参看开源项目 ratelimiter4j.

解决方案

有两个
1.分布式锁
2.redis + lua //最佳实践

这两个解决方案,本质都是为了解决一个核心问题,就是校验限流的代码包含了几步操作,这几步操作要原子化。分布式是一种解决方案。lua是一个脚本,包含多个redis命令的集合,原子化多个命令。

这个才是本质,其他的只是细节。实现。

参考

mp.weixin.qq.com/s/k9tm-4lBw…