python3后台开发缓存实战

一、问题描述

后台项目中,经常会遇到复杂的业务查询(关联多张数据表),或者查询大量数据的分析统计结果,这样的请求都是耗时较长的,如果大量用户频繁出现这种操作,会给服务器很大压力,甚至出现崩溃的情况。

二、解决思路

  • 查询操作时,把结果缓存起来,下次调用同样参数时直接返回缓存结果,就会节省处理时间,查询时间越长,效果越明显。
  • 非查询操作时,清空缓存,重新查询数据生成新缓存数据。

三、项目实战

Flask+Vue搭建系统,在之前的一篇文章中,实现问题的解决思路。

缓存实现

python官方文档自带缓存功能lru_cache,它可供我们传入的参数有2个maxsize和typed,如果不传则maxsize的默认值为128,typed的默认值为False。其中maxsize参数表示是的被装饰的方法最大可缓存结果数量, 如果是默认值128则表示被装饰方法最多可缓存128个返回结果,如果maxsize传入为None则表示可以缓存无限个结果。

查询时添加缓存
from functools import lru_cache  # 设置缓存,减少第二次查询时间

@lru_cache()
@pysnooper.snoop('pysnooper.log')  # 输出到文件
def handle_requests(qrytype: str, qryfunc: str, argc: str, Id: int = None):
    dbClass = get_type_query().get(qrytype)
    if not dbClass:
        return jsonify(code=RET.PARAMERR, msg=u'查询类型错误')

    dbcls = dbClass()
    if isinstance(argc, str):
        try:
            argcjson = json.loads(argc)
        except Exception as e:
            logging.error('[handle_requests]Failed to json.load, {0}'.format(e))
            logging.error(traceback.format_exc())
            return jsonify(code=RET.PARAMERR, msg='Failed to json.load, {0}'.format(e))
    elif isinstance(argc, dict):
        argcjson = argc
    else:
        return jsonify(code=RET.PARAMERR, msg=u'argc查询类型错误')
    # print(dir(dbcls))

    if qryfunc in dir(dbcls):
        if Id:
            value = dbcls.__getattribute__(qryfunc)(argcjson, Id)
        else:
            value = dbcls.__getattribute__(qryfunc)(argcjson)
        return value
    else:
        return jsonify(code=RET.PARAMERR, msg=qryfunc + '方法不存在,请联系开发人员')

代码说明:

  • 导入lru_cache:from functools import lru_cache
  • 在查询处理接口handle_requests增加装饰器lru_cache就可以实现查询结果缓存
  • 相比之前没有写额外的代码,只增加的一个装饰器就实现了缓存功能
非查询时更新缓存

收到前端接口请求时,添加一个拦截函数clear_cache,判断非查询操作,就清除缓存,代码如下:

@client_page.before_request
def clear_cache():
    if request.method == 'GET':
        return
    for key, obj in globals().items():
        if not hasattr(obj, 'cache_clear'):  # 判断函数是否定义了缓存
            continue
        obj.__getattribute__('cache_clear')()

代码说明:

  • @client_page.before_request装饰器表示函数clear_cache()在进入路由之前先执行该函数
  • GET表查询请求,非查询请求时清除缓存
  • obj.getattribute(‘cache_clear’)()表示通过传入函数名称来执行该函数
查询效果

第一次查询耗时
在这里插入图片描述
第二次查询有了缓存后的耗时
在这里插入图片描述
第三次把"邮箱"由"1111"改成"2222"后的耗时,数据变化后,清除了缓存,重新查询了数据,耗时又增加
在这里插入图片描述

和redis比较

lru_cache和redis比较:

比较类型lru_cacheredis
缓存类型内存中内存中
分布式单个进程中分布式缓存
数据类型hash 参数作为key有多种数据类型
适用场景小型系统完整缓存解决方案
功能功能少但使用便捷功能齐全

python自带的缓存功能使用于稍微小型的单体应用,优点是可以很方便的根据传入不同的参数缓存对应的结果, 并且可以有效控制缓存的结果数量,在超过设置数量时根据LRU算法淘汰命中次数最少的缓存结果。缺点是没有办法对缓存过期时间进行设置。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值