漏斗限流

参考书籍:《redis深度历险:核心原理与应用实践》

 漏斗限流是最常用的限流方法之一。漏斗的容量代表着规定的行为可以持续的总数量,漏斗的剩余空间就代表着当前行为可以持续进行的数量,漏嘴的流速代表着系统允许该行为的最大频率。

import time

class Funnel(object):
    def __init__(self,capacity,leaking_rate):
        self.capacity=capacity#l漏斗容量
        self.leaking_rate=leaking_rate#漏斗流速
        self.left_quota=capacity#漏斗剩余空间
        self.leaking_ts=time.time()#上一次漏水时间

    def make_space(self):
        now_ts=time.time()
        delta_ts=now_ts-self.leaking_ts#距离上一次漏水过去了多久
        delta_quota=delta_ts*self.leaking_rate#又可以腾出的空间
        if delta_quota<1:#腾地空间太少就等下次
            return
        self.left_quota+=delta_quota#将腾地空间增加到剩余空间
        self.leaking_ts=now_ts#记录漏水时间
        if self.left_quota>self.capacity:#剩余空间不得高于容量
            self.left_quota=self.capacity
    
    def watering(self,quota):
        self.make_space()
        if self.left_quota>=quota:#判断剩余空间是否充足
            self.left_quota-=quota
            return True
        return False

funnels={}

def is_action_allowed(user_id,action_key,capacity,leaking_rate):
    key='%s:%s'%(user_id,action_key)
    funnel=funnels.get(key)
    if not funnel:
        funnel=Funnel(capacity,leaking_rate)
        funnels[key]=funnel
    return funnel.watering(1)

for i in range(20):
    print(is_action_allowed('hello','reply',15,0.5))
    time.sleep(1)#因为程序运行速度是很快的,所以运行后你会看到15个True,5个
                       #False,所以我们这里来sleep一秒来看运行效果。

Funnel对象的make_space方法是漏斗算法的核心,其在每次灌水之前都会被调用以触发漏水,给漏斗腾出空间来。能腾出多少空间取决于过去了多久以及流水的素瘤。Funnel对象占据的空间大小是固定的,是一个常量。

猜你喜欢

转载自www.cnblogs.com/fromzore/p/10084956.html