dogpile是一种控制结构,它允许选择单个执行线程作为某些资源的“创建者”,同时允许其他执行线程在创建过程中引用此资源的先前版本。

dogpile.cache是​​一个缓存API,它提供了一个通用接口来缓存任何种类的后端。

首先安装dogpile:pip install dogpile.cache
现在有很多有名的key/value服务比如说redis Memcached,他们都很适合用于缓存,特别是Memcached。考虑到缓存系统,dogpile.cache提供了针对该系统的特定Python API的接口。

dogpile.cache配置包含以下组件:

  1. region: 是一个CacheRegion的实例,可以被看做是front end
  2. backend: 是一个CacheBackend的实例,描述了数据是怎么被储存的。这个接口只提供了get(),set(),delete()。用于特定CacheRegion的实际CacheBackend类型由用于与缓存通信的底层API,比如pylibmc(Memcached的python客户端)确定。
  3. Value generation functions: 这些是用户定义的函数,用于生成要放入缓存的数据。虽然godpile.cache提供了将数据放入缓存的常用set方法,但是通常使用方法是get。传递一个创建函数,当且仅当需要时,它将用于生成新值,这种“get-or-create”模式是“Dogpile”系统的全部关键。

初步使用:
dogpile.cache包含一个Pylibmc后端

from dogpile.cache import make_region# 这里创建了一个CacheRegion实例对象
Region = make_region()
# 对CacheRegion对象配置了backend
region = Region.configure('dogpile.cache.pylibmc',  # 这是name of backend,是需要的唯一arguementexpiration_time = 3600,arguments = {'url': ["127.0.0.1"],  # 这里是传递Memcached server的URL}
)@region.cache_on_arguments()
def load_user_info(user_id):return some_database.lookup_user_by_id(user_id)

所以最后都是使用region作为装饰器


make_region()

make_region()函数会直接调用CacheRegion的结构
该函数有以下参数:

  • name: 可选,region的名字,可以用.name获取,在config file中配置region时会有用
  • function_key_generator: 可选,用于使用CacheRegion.cache_on_arguments() 方法,这个函数需要有两个level。 一个是给出data creation function,然后需要返回一个新function用于基于给定的arguement生成key。
    def my_key_generator(namespace, fn, **kw):fname = fn.__name__def generate_key(*arg):return namespace + "_" + fname + "_".join(str(s) for s in arg)return generate_keyregion = make_region(function_key_generator = my_key_generator
    ).configure("dogpile.cache.dbm", # python的database manager,python本身有很多dbm库,但是dbm是一个方便选择,不用选择特定的dbm模块,它可以自己选择最适合的expiration_time=300,arguments={"filename":"file.dbm"}
    )
    

    使用装饰器:

    @my_region.cache_on_arguments(namespace=('x', 'y'))
    def my_function(a, b, **kw):return my_data()
    
  • function_multi_key_generator:可选,用于使用CacheRegion.cache_multi_on_arguments()方法,Generated function会返回一个key列表。
    def my_multi_key_generator(namespace, fn, **kw):
    namespace = fn.__name__ + (namespace or '')def generate_keys(*args):return [namespace + ':' + str(a) for a in args]return generate_keys
    
  • key_mangler: 可选,比较典型的是SHA1,sha1_mangle_key() 方法会对所有的key做hash
  • async_creation_runner: 它将通过互斥锁并在完成时负责释放该互斥锁
    import threading
    def async_creation_runner(cache, somekey, creator, mutex):def runner():try:value = creator()cache.set(somekey, value)finally:mutex.release()thread = threading.Thread(target=runner)thread.start()region = make_region(async_creation_runner=async_creation_runner,
    ).configure('dogpile.cache.memcached',expiration_time=5,arguments={'url': '127.0.0.1:11211','distributed_lock': True,}
    )
    

CacheRegion.configure()

根据上面一步,当我们有了CacheRegion的时候,CacheRegion.cache_on_arguments() 方法就可以用来当做装饰器了,但是这个缓存现在还不能用,必须经过CacheRegion.configure()配置了backend等信息才能使用

CacheRegion.configure() 有以下几个参数:

  • backend: CacheBackend的名字,必须项
  • expiration_time: 在上次value creation function调用之后,经过这段时间,才会调用下一次value creation function
  • arguments: 指定backend的地址
  • wrap: ProxyBackend类和/或实例的列表,每个类和/或实例用于包装原始backend,以便可以应用自定义功能扩充。
  • replace_existing_backend: 设置为True的话,已经存在的cache backend会被替换,如果不设置,对存在的backend进行配置会报错。
  • region_invalidator: 重写默认的无效策略
  • CacheRegion.configure_from_config():使用configuration dictionary和里面的前缀批量配置backend:
    local_region = make_region()
    memcached_region = make_region()
    # 上面CacheRegion已经创建好,但是还没有配置
    myconfig = {"cache.local.backend":"dogpile.cache.dbm","cache.local.arguments.filename":"/path/to/dbmfile.dbm","cache.memcached.backend":"dogpile.cache.pylibmc","cache.memcached.arguments.url":"127.0.0.1, 10.0.0.1",
    }
    local_region.configure_from_config(myconfig, "cache.local.")
    memcached_region.configure_from_config(myconfig,"cache.memcached.")
    

如何使用Region

上面对CacheRegion该配置的已经配置好了,这玩意儿相当于我们访问cache的前端接口,它包含下面的方法:

首先介绍invalidate()方法:
默认的invalidation system就是为value设置当前时间为最小的创建时间,任何检索值的创建时间早于这个timestamp就会被判定为过期,它不会对缓存中的值产生影响。这个timestamp被进程储存在本地内存,所以不会影响其他进程。但是如果这个timestamp被储存在缓存中,各进程都会被同一个timestamp影响,那么就需要制定一个custom RegionInvalidationStrategy.

这个方法可以有hard和soft两个选项,如果是hard,那么CacheRegion.get_or_create()会让所有的getters都等待value重新生成,如果是soft,那么随后的getters会获取old value直到新的value生成。

CacheRegion.get(key, expiration_time=None, ignore_expiration=False)

key: 根据key从Cache里面获取value,如果获取不到,该方法就会返回一个token:NO_VALUE。

expiration_time: 这个过期时间,要么是在region配置的时候设定好了,要么是现在调用的时候传递的参数,它会比较检索值的创建时间和现在时间(time.time()),如果过期了,这个缓存值会被忽略并且返回NO_VALUE。

ignore_expiration: 如果我们这样设置参数ignore_expiration=True, 那么会绕过这个过期时间检测

CacheRegion.get_or_create(key, creator, expiration_time=None, should_cache_fn=None, creator_args=None)

根据给定的key在缓存中获取对应的value,如果这个值不存在或者过期了,那么给定的creation function可能会创建新的值并且保存。

并发锁:
是否能使用这个creation function取决于是否能获取这个dogpile lock,如果不能,证明此时正有另一个线程或者进程在使用creation function为这个key创建值。
当这个dogpile不能获取的时候:
如果previous value不存在,那么这个方法就会block并且等待直到这个锁被释放,并且有一个新的值available。
如果previous value存在,那么会直接被返回。

如果invalidate()方法被called,如果检索值的timestamp比invalidation timestamp老,那么该值不管如何都不会被返回,该方法会尝试获取dogpile lock去生成新的值,或者等待lock释放然后返回新的值

key:检索的key
creator:用于创建新的值的函数
creator_args: 向创建函数传递参数 tuple
expiration_time: 会重写配置region时设置的过期时间,如果不需要过期时间,设置为-1
should_cache_fn:这个方法会接受creation function的返回值,然后根据返回True或者False判断新生成的值是否需要被保存到cache中:

def dont_cache_none(value):return value is not None# 如果这里返回False,那么该值不会被缓存value = region.get_or_create("some key",create_value,  # 这是creation functionshould_cache_fn=dont_cache_none)

CacheRegion.set(key, value)

在缓存中为特定的key设置value

CacheRegion.delete(key)

缓存中删除特定的键值对,该操作幂等

CacheRegion.cache_on_arguments(namespace=None, expiration_time=None, should_cache_fn=None, to_str=<class ‘str’>, function_key_generator=None)

这是一个装饰器函数将creation function创建的键值对储存到缓存中,这个装饰器会内在的调用CacheRegion.get_or_create()方法去获取缓存然后看是否需要调用该函数。

@someregion.cache_on_arguments()
def generate_something(x, y):return somedatabase.query(x, y)

这个被装饰的方法可以现在被调用了,数据会从cache里面获取,直到新的value被需要
result = generate_something(5, 6)

这个方法有一个属性为invalidate(),可以验证value的timestamp:
generate_something.invalidate(5, 6)

这个方法还可以直接使用set(),这样会直接储存这个给定的value,而不需要调用这个被装饰的函数:
generate_something.set(3, 5, 6)

这个方法有属性refresh(),该方法会调用被装饰函数去产生新的value放入缓存:
newvalue = generate_something.refresh(5, 6)

这个方法有属性original(),它会调用被装饰函数而不是获取缓存中的数据:
newvalue = generate_something.original(5, 6)

这个方法有属性get(),它会返回缓存中的值,或者返回NO_VALUE:
value = generate_something.get(5, 6)

SqlAlchemy做数据库缓存 -- dogpile.cache相关推荐

  1. memcached mysql缓存_memcached做数据库缓存

    最近研究memcache小有成果,把经验分享出来. 白话:很早就听说memcache了,一直没搞懂,后来又看到redis很火,可以用来做缓存,研究了半天也没搞懂咋个做缓存,后来也不纠结了,继续学习py ...

  2. redis做数据库缓存

    只读缓存 使用只读缓存时,是先把修改写到后端数据库中,再把缓存中的数据删除.当下次访问这个数据时,会以后端数据库中的值为准,重新加载到缓存中. 这样做的优点是,数据库和缓存可以保证完全一致,并且缓存中 ...

  3. 使用烧杯进行缓存? 为什么要切换到dogpile.cache

    Continuing on where I left off regarding Beaker in October (see Thoughts on Beaker), my new replacem ...

  4. mysql数据库如何做缓存_MySql数据库缓存

    对MySql查询缓存及SQL Server过程缓存的理解及总结 一.MySql的Query Cache 1.Query Cache   MySQL Query Cache是用来缓存我们所执行的SELE ...

  5. java+cache使用方法_java相关:springboot使用GuavaCache做简单缓存处理的方法

    java相关:springboot使用GuavaCache做简单缓存处理的方法 发布于 2020-3-29| 复制链接 摘记: 问题背景 实际项目碰到一个上游服务商接口有10秒的查询限制(同个账号). ...

  6. redis做mysql缓存的优点_面试官:如何保障数据库和redis缓存的一致性

    随着互联网的高速发展,使用互联网产品的人也越来越多,团队不可避免得也会面对越来越复杂的高并发业务场景(如下图),比如热点视频/文章的观看(读场景),热点视频/文章的评论,点赞等(写场景). 众所周知, ...

  7. 缓存的Cache Aside模式

    为什么80%的码农都做不了架构师?>>>    序 本文主要讲述下缓存的Cache Aside模式. Cache Aside 有两个要点: 应用程序先从cache取数据,没有得到,则 ...

  8. 从Java视角理解CPU缓存(CPU Cache)

    http://coderplay.iteye.com/blog/1485760 众所周知, CPU是计算机的大脑, 它负责执行程序的指令; 内存负责存数据, 包括程序自身数据. 同样大家都知道, 内存 ...

  9. Spring整合Redis做数据缓存(Windows环境)

    当我们一个项目的数据量很大的时候,就需要做一些缓存机制来减轻数据库的压力,提升应用程序的性能,对于java项目来说,最常用的缓存组件有Redis.Ehcache和Memcached. Ehcache是 ...

最新文章

  1. 不同真菌物种注释数据库对群落组成的影响
  2. BZOJ 3144 [HNOI2013]切糕 (最大流+巧妙的建图)
  3. Java NIO学习系列七:Path、Files、AsynchronousFileChannel
  4. python线程池模块_python并发编程之进程池,线程池,协程(Python标准模块--concurrent.futures(并发未来))...
  5. docker容器内安装ifconfig netstat ping vim 等测试工具的方法
  6. 面试题29. 顺时针打印矩阵/54. 螺旋矩阵
  7. Visual Studio 2005 提示“试图运行项目时出错:无法启动调试。绑定句柄无效”~[解决方案]...
  8. 【软考】系统集成项目管理工程师(一)信息化知识
  9. Qt 之 QPainter
  10. JAVA NIO介绍及使用
  11. 优启通制作系统u盘_EasyU优启通U盘启动盘制作工具BIOS+UEFI双启无捆绑
  12. (附源码)spring boot基于Java的电影院售票与管理系统毕业设计 011449
  13. frp与fail2ban结合禁用ip
  14. Tomcat - 解决which must be escaped when used within the value错误
  15. 博文推荐|深入解析 BookKeeper 多副本协议(一)
  16. xilinx ip video
  17. MySQL参数优化:back_log
  18. 关于小数四舍五入的方式
  19. JavaScriptJQuery_jQuery简介
  20. 绪论(p1-p2) author:run

热门文章

  1. [基础]qml基础控件(Text)
  2. 【并行计算-CUDA开发】CUDA线程、线程块、线程束、流多处理器、流处理器、网格概念的深入理解
  3. Vue中v-model的使用及案例
  4. Qt实现动态时钟表盘的设计
  5. maven-replacer-plugin 静态资源版本号解决方案(css/js等)
  6. 互联网行业中产品经理常用的专业术语有哪些?
  7. 目录文件DNSVHost暴力破解工具:Gobuster
  8. Linux下面查找数据的grep
  9. Window应急响应(六 ARP病毒)
  10. 【AI人工智能写作】使用 AI 智能写作实现每天产生被动收入的终极指南!!!...