令牌桶算法的python实现,人人都可以玩算法

from redis  import Redis
import time
import math
import random

redis_conn =  Redis(host='localhost',port=6689,password="redis_user",db=0)

hasinit = False
def init_redis_key(key,times):
    redis_conn.hset(key, 'tokens', times)
    last_time = int(time.time())  # 记录令牌生成时间
    redis_conn.hset(key, 'last_time', last_time)

def can_pass_token_bucket(user, action, time_zone=60, times=30):
    """
    :param user: 用户唯一标识
    :param action: 用户访问的接口标识(即用户在客户端进行的动作)
    :param time_zone: 接口限制的时间段
    :param time_zone: 限制的时间段内允许多少请求通过
    """
    # 请求来了就倒水,倒水速率有限制
    key = '{}:{}'.format(user, action)
    global hasinit
    if not hasinit:
        init_redis_key(key,times)
        hasinit = True
    rate = times / time_zone # 令牌生成速度
    capacity = times # 桶容量
    tokens = redis_conn.hget(key, 'tokens') # 看桶中有多少令牌
    last_time = redis_conn.hget(key, 'last_time') # 上次令牌生成时间
    now = int(time.time())
    if tokens:
        tokens = int(tokens)
    else:
        tokens = capacity
    if last_time:
        last_time = int(last_time)
    else:
        last_time = now
    print("tokens:",tokens)

    delta_tokens = (now - last_time) * rate # 经过一段时间后生成的令牌
    if delta_tokens >= 1:
        tokens = tokens + math.ceil(delta_tokens) # 增加令牌
        if tokens > capacity:
            tokens = capacity
        last_time = int(time.time()) # 记录令牌生成时间
        # print("hset last_time2:",last_time)
        redis_conn.hset(key, 'last_time', last_time)

    if tokens >= 1:
        tokens = tokens - 1 # 请求进来了,令牌就减少1
        print("hset tokens2:",tokens)
        redis_conn.hset(key, 'tokens', tokens)
        return True
    return False


if __name__ == "__main__":
    i = 0
    while i < 120:
        i = i + 1
        if can_pass_token_bucket("77-88-99","get"):
            print(f"第{i}次成功")
        else:
            print(f"第{i}次失败")
        print("\n")
        # 通过sleep模拟不同时间段请求速率的不同,当请求过快,token充足,请求能通过,token不足以后,返回失败
        # 当请求速率降下来之后,token的数量能上去,可以应对突发请求  token的数值大,突发请求成功数量就多
        if  i > 1 and i < 30:
            time.sleep(0.1)
        if i > 30 and i < 60:
            t = random.randint(2,6)/10
            time.sleep(t)
        if i > 60 and i < 90:
            t = random.randint(30,41)/10
            time.sleep(t)
        if i > 90 and i < 120:
            t = random.randint(2,6)/10
            time.sleep(t)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
令牌桶算法和漏桶算法都是常用的限速算法,它们可以用来限制系统的请求速率,避免系统过载或崩溃。下面是用 Python 实现令牌桶算法和漏桶算法的示例代码。 令牌桶算法示例代码: ```python import time class TokenBucket(object): def __init__(self, rate, capacity): self.rate = rate self.capacity = capacity self.tokens = 0 self.last_time = time.time() def get_tokens(self): now = time.time() elapsed_time = now - self.last_time self.tokens += elapsed_time * self.rate if self.tokens > self.capacity: self.tokens = self.capacity self.last_time = now return self.tokens def consume(self, tokens): if tokens <= self.get_tokens(): self.tokens -= tokens return True else: return False ``` 使用示例: ```python tb = TokenBucket(rate=1, capacity=5) for i in range(10): if tb.consume(1): print('request %d success' % i) else: print('request %d failed' % i) time.sleep(0.5) ``` 输出结果: ``` request 0 success request 1 failed request 2 success request 3 failed request 4 success request 5 failed request 6 success request 7 failed request 8 success request 9 failed ``` 漏桶算法示例代码: ```python import time class LeakyBucket(object): def __init__(self, rate, capacity): self.rate = rate self.capacity = capacity self.water = 0 self.last_time = time.time() def get_water(self): now = time.time() elapsed_time = now - self.last_time self.water = max(0, self.water - elapsed_time * self.rate) self.last_time = now return self.water def add_water(self, amount): if self.get_water() + amount <= self.capacity: self.water += amount return True else: return False ``` 使用示例: ```python lb = LeakyBucket(rate=1, capacity=5) for i in range(10): if lb.add_water(1): print('request %d success' % i) else: print('request %d failed' % i) time.sleep(0.5) ``` 输出结果: ``` request 0 success request 1 failed request 2 success request 3 failed request 4 success request 5 failed request 6 success request 7 failed request 8 success request 9 failed ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_36013896

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值