DiskCache: 基于磁盘的缓存
DiskCache 是一个基于 Apache2 许可的磁盘和文件缓存库,使用纯 Python 编写,并与 Django 兼容。
2023 年基于云的计算对内存提出了更高要求。磁盘上留有大量空闲空间,而进程却在争夺内存。在这些进程中,Memcached(有时是 Redis)被用作缓存。如果能利用空闲的磁盘空间进行缓存岂不是很好?
Django 是 Python 最流行的 Web 框架,自带多个缓存后端。但不幸的是,Django 中基于文件的缓存本质上是有问题的。剔除方法是随机的,大型缓存会反复扫描缓存目录,随着增长速度线性下降。你真的能容忍在一个有一千个项目的缓存中存储一个键需要六十毫秒吗?
在 Python 中,我们可以做得更好。而且我们可以用纯 Python 来实现!
::
In [1]: import pylibmc In [2]: client = pylibmc.Client(['127.0.0.1'], binary=True) In [3]: client[b'key'] = b'value' In [4]: %timeit client[b'key']
10000 次循环,3 次中最佳用时: 25.4 µs
In [5]: import diskcache as dc In [6]: cache = dc.Cache('tmp') In [7]: cache[b'key'] = b'value' In [8]: %timeit cache[b'key']
100000 次循环,3 次中最佳用时: 11.8 µs
注意: 微基准测试有其用处,但不能替代真实测量。DiskCache 提供缓存基准测试来证明其性能主张。虽然避免了微优化,但你的实际体验可能有所不同。
DiskCache 高效地将GB级存储空间用于缓存。通过利用坚如磐石的数据库库和内存映射文件,缓存性能可以匹配甚至超越行业标准解决方案。无需 C 编译器或运行其他进程。性能是一项特性,测试覆盖率达到 100%,包括单元测试和数小时的压力测试。
推荐语
Daren Hasenkamp, 创始人 --
"这是一个有用的、简单的 API,就像我喜欢 Redis 那样。它为一个每天有超过百万用户(每秒 100 多次点击)的网站减少了超过 25% 击中 Elasticsearch 集群的查询。"
Mathias Petermann, 高级 Linux 系统工程师 --
"我将它实现到我们的 Ansible 查找模块的包装器中,我们能够将一些 Ansible 运行的速度提高近 3 倍。DiskCache 为我们节省了大量时间。"
你的公司或网站是否使用 DiskCache?给我们发送消息让我们知道。
特性
- 纯 Python 实现
- 文档完备
- 基准比较(替代方案、Django 缓存后端)
- 100% 测试覆盖率
- 数小时的压力测试
- 注重性能
- 兼容 Django API
- 线程安全和进程安全
- 支持多种淘汰策略(包括 LRU 和 LFU)
- 键支持"标签"元数据和淘汰
- 在 Python 3.10 上开发
- 在 CPython 3.6、3.7、3.8、3.9、3.10 上测试
- 在 Linux、Mac OS X 和 Windows 上测试
- 使用 GitHub Actions 测试
快速入门
使用 pip 安装 DiskCache 很简单::
$ pip install diskcache
你可以在解释器中使用 Python 的内置帮助函数访问文档::
import diskcache help(diskcache) # doctest: +SKIP
DiskCache 的核心是三种用于缓存的数据类型。Cache 对象管理 SQLite 数据库和文件系统目录以存储键值对。FanoutCache 提供一个分片层以利用多个缓存,而 DjangoCache 将其与 Django 集成::
from diskcache import Cache, FanoutCache, DjangoCache help(Cache) # doctest: +SKIP help(FanoutCache) # doctest: +SKIP help(DjangoCache) # doctest: +SKIP
在缓存数据类型之上构建的是 Deque 和 Index,它们作为 Python 的 collections.deque 和 dict 的跨进程、持久化替代品。这些实现了序列和映射容器的基类::
from diskcache import Deque, Index help(Deque) # doctest: +SKIP help(Index) # doctest: +SKIP
最后,提供了一些使用底层缓存的跨进程同步方法。可用的功能包括带缓存雪崩防护的记忆化、跨进程锁定和跨进程限流::
from diskcache import memoize_stampede, Lock, throttle help(memoize_stampede) # doctest: +SKIP help(Lock) # doctest: +SKIP help(throttle) # doctest: +SKIP
Python 的文档字符串是快速入门的好方法,但并不能取代 DiskCache 教程和 DiskCache API 参考。
用户指南
对于想要更多细节的人,文档的这一部分描述了教程、基准测试、API 和开发。
- DiskCache 教程
- DiskCache 缓存基准测试
- DiskCache DjangoCache 基准测试
- 案例研究:网络爬虫
- 案例研究:落地页缓存
- 演讲:缓存的方方面面 - SF Python 2017 聚会
- DiskCache API 参考
- DiskCache 开发
.. _
DiskCache 教程
: http://www.grantjenks.com/docs/diskcache/tutorial.html .. _DiskCache 缓存基准测试
: http://www.grantjenks.com/docs/diskcache/cache-benchmarks.html .. _DiskCache DjangoCache 基准测试
: http://www.grantjenks.com/docs/diskcache/djangocache-benchmarks.html .. _演讲:缓存的方方面面 - 2017年旧金山Python开发者聚会
: http://www.grantjenks.com/docs/diskcache/sf-python-2017-meetup-talk.html .. _案例研究:网络爬虫
: http://www.grantjenks.com/docs/diskcache/case-study-web-crawler.html .. _案例研究:落地页缓存
: http://www.grantjenks.com/docs/diskcache/case-study-landing-page-caching.html .. _DiskCache API 参考
: http://www.grantjenks.com/docs/diskcache/api.html .. _DiskCache 开发
: http://www.grantjenks.com/docs/diskcache/development.html
比较
与DiskCache
_相关的流行项目的比较。
键值存储 ................
DiskCache
_主要是一个简单的键值存储。下表展示了与其他四个项目的功能比较。
dbm
_是Python标准库的一部分,它实现了一个通用接口,用于访问DBM数据库的变体 — dbm.gnu或dbm.ndbm。如果这些模块都没有安装,则会使用速度较慢但简单的dbm.dumb。shelve
_是Python标准库的一部分,它将"架子"实现为一个持久的、类似字典的对象。与"dbm"数据库的区别在于,其值可以是pickle模块能处理的任何对象。sqlitedict
_是Python的sqlite3数据库的一个轻量级封装,具有简单、Pythonic的类字典接口,并支持多线程访问。键是任意字符串,值是任意可pickle的对象。pickleDB
_是一个轻量级简单的键值存储。它基于Python的simplejson模块构建,并受Redis启发。它使用BSD三条款许可证。
.. _dbm
: https://docs.python.org/3/library/dbm.html
.. _shelve
: https://docs.python.org/3/library/shelve.html
.. _sqlitedict
: https://github.com/RaRe-Technologies/sqlitedict
.. _pickleDB
: https://pythonhosted.org/pickleDB/
功能
================ ============= ========= ========= ============ ============ 功能 diskcache dbm shelve sqlitedict pickleDB ================ ============= ========= ========= ============ ============ 原子性? 始终 可能 可能 可能 否 持久性? 是 是 是 是 是 线程安全? 是 否 否 是 否 进程安全? 是 否 否 可能 否 后端? SQLite DBM DBM SQLite 文件 序列化? 可定制 无 Pickle 可定制 JSON 数据类型? 映射/双端队列 映射 映射 映射 映射 排序? 插入/排序 无 无 无 无 淘汰策略? LRU/LFU/更多 无 无 无 无 空间回收? 自动 可能 可能 手动 自动 事务? 是 否 否 可能 否 多进程? 是 否 否 否 否 可分叉? 是 否 否 否 否 元数据? 是 否 否 否 否 ================ ============= ========= ========= ============ ============
质量
================ ============= ========= ========= ============ ============ 项目 diskcache dbm shelve sqlitedict pickleDB ================ ============= ========= ========= ============ ============ 测试? 是 是 是 是 是 覆盖率? 是 是 是 是 否 压力测试? 是 否 否 否 否 CI测试? Linux/Windows 是 是 Linux 否 Python版本? 2/3/PyPy 全部 全部 2/3 2/3 许可证? Apache2 Python Python Apache2 3条款BSD 文档? 详尽 摘要 摘要 Readme 摘要 基准测试? 是 否 否 否 否 源码? GitHub GitHub GitHub GitHub GitHub 纯Python? 是 是 是 是 是 服务器? 否 否 否 否 否 集成? Django 无 无 无 无 ================ ============= ========= ========= ============ ============
时间
这些是粗略的测量结果。更严格的数据请参见DiskCache 缓存基准测试
_。
================ ============= ========= ========= ============ ============ 项目 diskcache dbm shelve sqlitedict pickleDB ================ ============= ========= ========= ============ ============ get 25 µs 36 µs 41 µs 513 µs 92 µs set 198 µs 900 µs 928 µs 697 µs 1,020 µs delete 248 µs 740 µs 702 µs 1,717 µs 1,020 µs ================ ============= ========= ========= ============ ============
缓存库 .................
joblib.Memory
_提供缓存函数,通过显式保存输入和输出到文件来工作。它设计用于处理不可哈希且可能大型的输入和输出数据类型,如numpy数组。klepto
_扩展了Python的lru_cache
,可使用不同的键映射和替代缓存算法,如lfu_cache
和mru_cache
。Klepto为所有缓存和存档使用简单的字典式接口。
.. _klepto
: https://pypi.org/project/klepto/
.. _joblib.Memory
: https://joblib.readthedocs.io/en/latest/memory.html
数据结构 ...............
dict
_是一个映射对象,将可哈希的键映射到任意值。映射是可变对象。目前Python只有一种标准映射类型,即字典。pandas
_是一个Python包,提供快速、灵活和富有表现力的数据结构,旨在使处理"关系型"或"标记性"数据变得简单直观。Sorted Containers
_是一个Apache2许可的排序集合库,用纯Python编写,速度与C扩展相当。Sorted Containers实现了排序列表、排序字典和排序集合数据类型。
.. _dict
: https://docs.python.org/3/library/stdtypes.html#typesmapping
.. _pandas
: https://pandas.pydata.org/
.. _Sorted Containers
: http://www.grantjenks.com/docs/sortedcontainers/
纯Python数据库 .....................
ZODB
_支持数据库操作的同构接口,这意味着使对象持久化对你的代码影响很小,并且没有部分隐藏数据库的数据库映射器。CodernityDB
_是一个开源的、纯Python的、多平台、无模式的NoSQL数据库,包括HTTP服务器版本和一个Python客户端库,旨在与嵌入式版本100%兼容。TinyDB
_是一个微型的、面向文档的数据库,为你的便利而优化。如果你需要一个具有简洁API的简单数据库,无需大量配置就能正常工作,TinyDB可能是你的正确选择。 .. _ZODB
: http://www.zodb.org/ .. _CodernityDB
: https://pypi.org/project/CodernityDB/ .. _TinyDB
: https://tinydb.readthedocs.io/
对象关系映射(ORM) ................................
Django ORM
_ 提供的模型是关于数据的单一、权威信息源,包含存储数据的基本字段和行为。通常,每个模型对应一个单独的SQL数据库表。SQLAlchemy
_ 是Python的SQL工具包和对象关系映射器,为应用程序开发者提供SQL的全部功能和灵活性。它提供了一套完整的知名企业级持久化模式。Peewee
_ 是一个简单而小巧的ORM。它有少量但富有表现力的概念,使其易于学习和直观使用。Peewee支持Sqlite、MySQL和PostgreSQL,并有大量扩展。SQLObject
_ 是一个流行的对象关系管理器,为数据库提供对象接口,将表作为类,行作为实例,列作为属性。Pony ORM
_ 是一个具有优美查询语法的Python ORM。使用Python语法与数据库交互。Pony将这些查询转换为SQL,并以最高效的方式在数据库中执行它们。
.. _Django ORM
: https://docs.djangoproject.com/en/dev/topics/db/
.. _SQLAlchemy
: https://www.sqlalchemy.org/
.. _Peewee
: http://docs.peewee-orm.com/
.. _SQLObject
: http://sqlobject.org/
.. _Pony ORM
: https://ponyorm.com/
SQL数据库 .............
SQLite
_ 是Python标准库的一部分,提供了一个轻量级的基于磁盘的数据库,不需要单独的服务器进程,并允许使用SQL查询语言的非标准变体访问数据库。MySQL
_ 是世界上最流行的开源数据库之一,已成为基于Web的应用程序的首选数据库。MySQL为Python平台和开发提供了标准化的数据库驱动程序。PostgreSQL
_ 是一个强大的开源对象关系数据库系统,拥有超过30年的活跃开发历史。Psycopg是Python编程语言最受欢迎的PostgreSQL适配器。Oracle DB
_ 是Oracle公司的关系数据库管理系统(RDBMS)。最初开发于1977年,Oracle DB是最受信赖和广泛使用的企业关系数据库引擎之一。Microsoft SQL Server
_ 是由Microsoft开发的关系数据库管理系统。作为数据库服务器,它根据其他软件应用程序的请求存储和检索数据。
.. _SQLite
: https://docs.python.org/3/library/sqlite3.html
.. _MySQL
: https://dev.mysql.com/downloads/connector/python/
.. _PostgreSQL
: http://initd.org/psycopg/
.. _Oracle DB
: https://pypi.org/project/cx_Oracle/
.. _Microsoft SQL Server
: https://pypi.org/project/pyodbc/
其他数据库 ...............
Memcached
_ 是免费开源的、高性能、分布式内存对象缓存系统,本质上是通用的,但旨在通过减轻数据库负载来加速动态Web应用程序。Redis
_ 是一个开源的、内存数据结构存储,用作数据库、缓存和消息代理。它支持字符串、哈希、列表、集合、带范围查询的有序集合等数据结构。MongoDB
_ 是一个跨平台的面向文档的数据库程序。作为一个NoSQL数据库程序,MongoDB使用类似JSON的带模式的文档。PyMongo是在Python中使用MongoDB的推荐方式。LMDB
_ 是一个闪电般快速的内存映射数据库。通过内存映射文件,它具有纯内存数据库的读取性能,同时保留了标准磁盘数据库的持久性。BerkeleyDB
_ 是一个旨在为键/值数据提供高性能嵌入式数据库的软件库。Berkeley DB是一个程序化工具包,为桌面和服务器应用程序提供内置数据库支持。LevelDB
_ 是Google编写的快速键值存储库,提供了从字符串键到字符串值的有序映射。数据按键排序存储,用户可以提供自定义比较函数。
.. _Memcached
: https://pypi.org/project/python-memcached/
.. _MongoDB
: https://api.mongodb.com/python/current/
.. _Redis
: https://redis.io/clients#python
.. _LMDB
: https://lmdb.readthedocs.io/
.. _BerkeleyDB
: https://pypi.org/project/bsddb3/
.. _LevelDB
: https://plyvel.readthedocs.io/
参考
DiskCache文档
_PyPI上的DiskCache
_GitHub上的DiskCache
_DiskCache问题追踪器
_
.. _DiskCache文档
: http://www.grantjenks.com/docs/diskcache/
.. _PyPI上的DiskCache
: https://pypi.python.org/pypi/diskcache/
.. _GitHub上的DiskCache
: https://github.com/grantjenks/python-diskcache/
.. _DiskCache问题追踪器
: https://github.com/grantjenks/python-diskcache/issues/
许可证
版权所有 2016-2023 Grant Jenks
根据Apache许可证2.0版("许可证")授权;除非遵守许可证,否则不得使用此文件。你可以在以下位置获得许可证的副本:
http://www.apache.org/licenses/LICENSE-2.0
除非适用法律要求或书面同意,根据许可证分发的软件是基于"按原样"分发的,不附带任何明示或暗示的担保或条件。请参阅许可证以了解特定语言下的权限和限制。
.. _DiskCache
: http://www.grantjenks.com/docs/diskcache/