django 阅读笔记 - Cache


作者: dreampuf
日期: 2011-02-18 23:22:50

1   简介

记录了个人在需要时阅读django源码时的一些阅读笔记.所有笔记基于 django v1.0.4.

2   Cache

2.1   BaseCache

django中缓存是一个独立的组件,它定义了一个父类,文件在 django/core/cache/backend/base.py 这个模块包含了一个父类 BaseCache ,指定了一些基础的操作.
  • __init__ :初始化指定了缓存项的过期时间,但是根据具体实现的不同会有不同的解释. (比如在数据库实现中就是删除数据项)
  • add :添加缓存,参数分别为 过期时间 (默认是300秒).这个方法由子类实现.
  • get :获取缓存,参数为  , 默认值 (默认为None).
  • set :改变缓存,参数同 add 函数.
  • delete :删除缓存,参数为 .
  • get_many :获取多个缓存, 参数为 键列表.
  • has_key :是否存在键, 参数为 .
  • __contains__ :判断是否存在的函数, 参数为 .结果与 has_key 一致.

2.2   DataBaseCache

基于数据库的缓存.模块文件在 django/core/cache/backend/db.py 这个文件包含了一个继承BaseCache的数据库缓存实现. 他还指定了数据库最多存多少缓存项.

其中值得注意的几点是:

  • 使用pickle序列化对象.所以存储任何对象都是可以的,最后都会被转化为数据库支持的字符串.
  • 过期时间是以秒为单位.
  • 每次 set 都会处理序列化,哪怕本身存储的就是字符串.这显然不太合算.
  • 构造缓存管理对象的时候可以指定一个 cull_frequency 参数,作为超过最大项时删除的参考,默认是 3,也就是说每当超过容量限制时,删除1/3的缓存数据项.奇怪的是,这里是根据 cache_key 的大小删除,而不是根据过期时间,这样就可能导致 时效非常久的缓存被提早就给删除 了.
  • 每次获取时进行过期处理,也就是说可能有一些项永远都会存在数据库中.(过期后,自身cache_key非常大,极少有被删除的可能)

2.3   DummyCache

测试使用的缓存.模块文件在 django/core/cache/backend/dummy.py.这个缓存功能相当有限,仅仅只能被用于测试.而且本身无任何逻辑,只是返回一些默认值.

2.4   FileBaseCache

基于文件的缓存.模块文件在 django/core/cache/backend/filebase.py.这个文件系统缓存,实现了基于每个缓存对象一个文件的对应.只是在处理多文件管理时,使用了一些必要的方法.
  • 构造时传递的第一个为路径地址.
  • add 方法如果添加已存在的键时不会成功,这和我们寻常的逻辑有点不符,如果还需要调用 add 那么肯定是想指定值,所以如果添加一些已有键,势必会添加一次判断.
  • 每次 set 是都会进行一次目录遍历,搜索所有文件,看是否超过总数.
  • 文件名的生成是对 cache_key 进行一次md5,然后取加密后的字符两个前两位作为一个二级目录存放(比如: ab/cd/*****),这样是为了目录下的文件过多时索引文件非常慢而导致效率很低的问题.但是结合构造函数时接受的最大缓存项来看,默认的 300 根本无法构成对文件索引拖慢的威胁.而 FileBaseCache默认就使用二级目录预估的至少可以存储 1000*1000 项缓存数据(假设缓存文件平均分布).是否是因该有所优化的在构造时加上一个判断,只有在一定数量级之后才启用二级目录,或者增加一个一级目录管理,再或者默认不设目录.

2.5   LocamemCache

基于内存的缓存,模块文件在 django/core/cache/backend/locamem.py.实现了简单的内存缓存系统.

实现了带锁的内存缓存系统,不过有些瑕疵,好像是为了保证整体统一,不过这种统一难免让人诟病.

  • 构造时内部声明了两个字典,一个存放序列化之后的缓存值,一个存放设置好了的过期时间,并且额外声明了一个异步锁.不过据我所知 Python 的多线程简直就是在自慰, GIL 使然,你根本无法放开手脚,虽然值得解释器环境更加安全稳定,但是这种 伪多线程 很难让人提起兴趣.
  • 在添加缓存时,获取缓存时,依然不辞幸苦给缓存值进行了序列化.作为的 dict 可能唯一的感受就是嫉妒羡慕恨.
  • 在超出缓存最大值之后, LocamemCache 将会删除所有与 _cull_frequency 取模为0的值.仅仅是为了使用 生成器表达式?!如果 _cull_frequency 为0时,则清空缓存库.但是当 _cull_frequency 为1时,同样会有清空缓存库的效果.

2.6   MemcachedCache

基于memcached的缓存系统,模块文件在 django/core/cache/backend/memcached.py.简单的对cmemcache或者memcache的封装.

这下django终于机灵了,没有在这里序列化了,因为这些动作会在memcache库中操作.

  • 所有传入的 unicode字符 被转换为 utf-8,从缓存中获取的字符串则被转换为 unicode字符.
  • 如果在 set 或者 add 方法中指定过期时间为 0 不过期有可能是无效的,因为 MemcachedCache 在处理默认过期时间时采用了一个 逻辑或 处理,所以导致如果指定为 0 被逻辑操作为 传递默认值.
  • 他有一个额外的关闭连接方法(close),默认是不会自己调用的,需要在每次使用之后手动调用.
posted @ 2011-02-20 15:13  Dreampuf  阅读(2781)  评论(2编辑  收藏  举报