高并发系统为了服务的可用性面对高流量及qps高峰时通常有三种常见的应对措施:缓存、降级和限流。这一篇我们来看一下限流及go相应的实现。 限流算法通常有这么几种:计数器、令牌痛、漏桶,这几个算法的优缺点在这里就不多说了,网上有大量的文章介绍这几个算法,大家也可以借鉴我限流算法的那篇文章。 这里就这几种算法的思想借助go的API来实现一下:
这里用到的并发相关的API 主要是sync.Mutex
我们通过设定一个计数器ReqCount,当ReqCount大于MaxCount(计数器最大值)时不发放令牌(token),过来的请求因拿不到令牌直接返回或者触发其他的拒绝策略。
因为计数器的操作是一个典型的先判断再操作的竞态条件,并且存在另外一个专门置0的go协程,如果不加锁,在并发场景下发生问题的概率是非常大的,所以使用sync.Mutex,保证了操作的原子性。
计数器比较简单,下面来看一下实现的代码:
这里涉及的API 主要是channel
,利用的就是channel的阻塞操作。
我们把一个指定尺寸channel,相当于一个指定容量的令牌桶,每一个空闲位置就是一个令牌。由于channel满时就无法向其中加元素,所以我们就可以以固定的速率消费channel中的消息(释放空间相当于添加令牌),取令牌就是添加一条消息,当令牌桶满时就无法正常添加消息(取令牌)了,这样就利用channel来构造了一个限流器。
下面来看一下代码:
在常用限流算法go的实现中,关于sync、chan的使用大致就是以上,这两个demo挺简单的,可以由浅入深帮助大家理解一下go并发编程及Mutex、chan 的API使用。 关于限流算法暂时就说这么多。