python使用redis计数器
普通计数
def redis_count(conn, key, amount=1):
"""redis 计数器"""
try:
count = conn.incr(key, amount)
except Exception as e:
raise e
finally:
conn.close()
return count
redis_count(cache,"c1")
固定窗口法
def can_pass_fixed_window(user, action, redis_conn,time_period=60, times=30):
"""
固定窗口法
:param user: 用户唯一标识
:param action: 用户访问的接口标识(即用户在客户端进行的动作)
:param time_zone: 接口限制的时间段
:param times: 限制的时间段内允许多少请求通过
"""
key = '{}:{}'.format(user, action)
# redis_conn 表示redis连接对象
count = redis_conn.get(key)
print("count>>>",count)
if not count:
count = 1
redis_conn.setex(key,value = count,time = time_period) #为指定的键(key)设置过期以秒(second)计的过期时间
if int(count) < times:
redis_conn.incr(key)
return True
return False
滑动窗口法
def can_pass_slide_window(user, action,redis_conn, time_period=60, times=30):
"""
滑动窗口法
:param user: 用户唯一标识
:param action: 用户访问的接口标识(即用户在客户端进行的动作)
:param time_zone: 接口限制的时间段
:param time_zone: 限制的时间段内允许多少请求通过
"""
key = '{}:{}'.format(user, action)
now_ts = int(time.time() * 1000)
# value是什么在这里并不重要,只要保证value的唯一性即可,这里使用毫秒时间戳作为唯一值
value = now_ts
# 时间窗口左边界
time_period=time_period
old_ts = now_ts - int(time_period * 1000)
# 记录行为
mapping={
value:now_ts
}
#redis_conn.zadd(key, value, now_ts)
redis_conn.zadd(key,mapping)
#print(redis_conn.zrange(key, 0, -1, withscores=True))
# 删除时间窗口之前的数据
redis_conn.zremrangebyscore(key, 0, old_ts)
# 获取窗口内的行为数量
count = redis_conn.zcard(key)
# 设置一个过期时间免得占空间
redis_conn.expire(key, time_period + 1)
print("count>>>",count)
if not count or count < times:
return True
return False
#can_pass_slide_window(user, action, cache)
测试
user="stock_code1"
action="warning"
for i in range(60):
can_bool = can_pass_slide_window(user, action, cache)
print("can_bool",can_bool)