zoukankan      html  css  js  c++  java
  • 利用memoize缓存到Redis出现多个参数同一个结果

    在为后端输出加入Redis缓存的过程中出现的问题。

    在我利用Flask-restful架构的后端中,理所当然的利用装饰器marshal_with对我的返回数据进行格式化输出。

    举个最简单的例子:

    from flask_restful import Resource,  fields,  marshal_with
    
    fields = {
        'id': fields.Integer,
        'name': fields.String,
        'bio': fields.String,
    }
    
    class Users(Resource):
        @marshal_with(fields)
        def get(self, user_id):
            return session.query(User).filter(User.id=user_id).first()

    这样子通过GET请求则会从数据库拿到的query对象会被marshal_with装饰城json数组返回(此处省略了主app添加资源然后运行,以及models的创建过程)。

    在我想对这样一个资源请求添加缓存的时候,自然准备利用flask_cache.

    而flask_cache的对象cache,主要两个装饰器(详细可参考:https://pythonhosted.org/Flask-Cache/):

    1.cache.cached

    2.cache.memoize

    区别主要在于第二个在制作key的时候会考虑参数,那么因为我们这个有user_id,不同的用户请求在缓存当中不同,自然选择memoize,所以我一开始就这样写。

    from flask_restful import Resource,  fields,  marshal_with
    from flask_cache import  Cache
    
    cache=Cache(......) #initial with app
    
    fields = {
        'id': fields.Integer,
        'name': fields.String,
        'bio': fields.String,
    }
    
    class Users(Resource):
        @cache.memoize()
        @marshal_with(fields)
        def get(self, beacon_id):
            return session.query(User).filter(User.id=user_id).first()

    可是在测试过程中发现,对于不同的user_id,返回的都是同一个缓存结果。

    几经波折,打印出来才发现是装饰器顺序导致memoize了marshal_with的装饰导致key一样。

    那么如果我把这两个顺序交换,也就是说memoize放在marshal_with下面,可是这样子会造成一个新的问题,

    缓存的数据是SQLAlchemy的查询结果,当你试图从缓存中恢复的时候则会造成:

    “Parent instance <SomeClass> is not bound to a Session; lazy load operation…”

    这个错误,最终,我选择了取消marshal_with装饰器:

    from flask_restful import Resource,  fields,  marshal_with,marshal
    from flask_cache import  Cache
    
    cache=Cache(......) #initial with app
    
    fields = {
        'id': fields.Integer,
        'name': fields.String,
        'bio': fields.String,
    }
    
    class Users(Resource):
        @cache.memoize()
        def get(self, beacon_id):
            return marshal(session.query(User).filter(User.id=user_id).first(),fields)

    也就是说直接缓存marshal装饰后的结果。

    在put post等修改数据库的操作后,利用cache.delete_memoized删掉缓存保证数据同步。

  • 相关阅读:
    EggJs+Vue服务端渲染实践
    使用Charles代理功能将网络请求定向至本地文件
    iOS内存管理(一)
    RumTime实践之--UITableView和UICollectionView缺省页的实现
    CollectionView水平和竖直瀑布流的实现
    解决在HTTPS页面里嵌套HTTP页面浏览器block的问题
    利用servlet做转发,实现js跨域解决同源问题
    js将数字转换成大写的人民币表达式
    《将博客搬至CSDN》 分类: 勉励自己 2014-09-05 14:29 43人阅读 评论(0) 收藏
    jquery插件,美化select标签
  • 原文地址:https://www.cnblogs.com/lesliexong/p/8427789.html
Copyright © 2011-2022 走看看