Redis简单应用
代码如下:
import random
import redis
import pickle
REDIS_HOST = '10.30.133.13'
REDIS_PASSWORD = 'MzhhMzU4NDQzNzU'
REDIS_PORT = 6379
class RedisClient(object):
def __init__(self):
redis_pool = redis.ConnectionPool(host=REDIS_HOST, password=REDIS_PASSWORD, port=REDIS_PORT)
self.client = redis.Redis(connection_pool=redis_pool)
def get(self, key):
try:
return pickle.loads(self.client.get(key))
except Exception as ex:
return None
def set(self, key, value, **kwargs):
"""
ex: 过期时间 秒s
px: 过期时间 毫秒ms
nx: 键不存在时生效
xx: 键存在时生效
"""
if not kwargs.get('ex') and not kwargs.get('px'):
# 不允许设置永久KEY,未设置失效时间的,则默认设置为 12-24 hour
kwargs['ex'] = random.randint(12 * 60 * 60, 24 * 60 * 60)
try:
self.client.set(key, pickle.dumps(value), **kwargs)
return self.get(key)
except Exception as ex:
return None
def ttl(self, key):
"""
键不存在时:return -2
未设置生命周期时:return -1
"""
return self.client.ttl(key)
def incr(self, key):
"""
自增+1,如果key不存在,则默认设置一个有失效时间的key(官方默认生命周期为-1,永久有效)
"""
if self.ttl(key) in [-1, -2]:
self.set(key, self.client.get(key) or 0, ex=random.randint(1, 3))
try:
return self.client.incr(key)
except:
return None
def scan(self, **kwargs):
"""
根据正则匹配对应keys
"""
_keys = self.client.scan(**kwargs)
keys = list()
for item in _keys[1]:
if isinstance(item, bytes):
keys.append(item.decode('utf-8'))
return keys
def keys(self):
"""
获取所有key
"""
return self.client.keys()
def destroy(self, key):
try:
return self.client.delete(key)
except Exception as ex:
pass
def match_destroy(self, pattern):
"""
根据正则匹配删除
"""
keys = self.scan(match=pattern)
for key in keys:
self.destroy(key)
return keys
def session(self, is_class=False):
"""
is_class: 是否为类方法
目的:提供redis实例供方法直接使用
"""
def wrapper(func):
def exec(*args, **kwargs):
if not is_class:
return func(self, *args, **kwargs)
_args = list(args)
func_instance = _args.pop(0)
# 处理位置参数传参错乱问题
return func(func_instance, self, *_args, **kwargs)
return exec
return wrapper
def session_method(self, key, expires=60):
"""
针对方法进行缓存,value为方法返回值
"""
def wrapper(func):
def exec(*args, **kwargs):
func_key = f'{str(func.__qualname__)}_{key}'
value = self.get(func_key)
if value is not None:
return value
value = func(*args, **kwargs)
self.set(func_key, value, ex=expires)
return value
return exec
return wrapper
if __name__ == '__main__':
redis_client = RedisClient()
# 写入key
redis_client.set(key='thisiskey', value='thisisvalue', ex=60)
# 读取key
print(f'value={redis_client.get("thisiskey")}')
# 获取失效时间
print(f'ttl={redis_client.ttl("thisiskey")}')
# 扫描keys
print(f'scan={redis_client.scan(match="thisiskey")}')
# 删除keys
print(f'delete_key={redis_client.match_destroy("this*")}')
print(f'value={redis_client.get("thisiskey")}')
result:
进阶应用(高级感)
实例1:使用装饰器注入redis实例(方法)
redis_client = RedisClient()
@redis_client.session()
def test1(session, *args, **kwargs):
session.set('thisiskey', 'thisisvalue')
return session.get('thisiskey')
print(test1())
result:
实例2:使用装饰器注入redis实例(类方法)
redis_client = RedisClient()
class Test(object):
@redis_client.session(is_class=True)
def test2(self, session):
session.set('thisiskey', 'thisisvalue')
return session.get('thisiskey')
print(Test().test2())
实例3:使用装饰器对方法返回值进行缓存,针对被频繁调用的方法
redis_client = RedisClient()
class Test(object):
@redis_client.session_method('thisiskey_test3', 60)
def test3(self, **kwargs):
print('i am here')
return 'thisisvalue_test3'
print(Test().test3())
print(Test().test3())
result:
实例4:使用redis进行接口限流
推荐使用
https://editor.youkuaiyun.com/md/?articleId=131138755
例如上传文件接口,同一用户仅允许10s内上传一次
redis_client = RedisClient()
@redis_client.session()
def import_file_limit(session, request):
key = f'{request.method}_{request.path}_{request.user_id}_import_file'
session.set(key, 0, ex=10, nx=True)
num = session.incr(key)
if num <= 1:
return
ttl = session.ttl(key)
print(f'{request.user_id}提交过于频繁,请在 {ttl} 秒后重试')