基本用法
from zdppy_cache import Cache
# 创建缓存对象
cache = Cache()
# 关闭缓存对象
cache.close()
# 通过上下文自动关闭缓存对象
with Cache(cache.directory) as reference:
reference.set('key', 'value')
# 通过缓存对象获取值
print(cache.get('key'))
指定缓存目录
from zdppy_cache import Cache
# 实例化缓存对象,指定缓存目录
cache = Cache('tmp/mycache')
# 设置缓存项
cache.set('key1', 'value1')
# 获取缓存项
value = cache.get('key1')
print('Cached value:', value) # 输出: Cached value: value1
# 关闭缓存对象
cache.close()
删除缓存项
from zdppy_cache import Cache
# 实例化缓存对象,指定缓存目录
cache = Cache('tmp/mycache')
# 设置缓存项
cache.set('key1', 'value1')
# 删除指定的缓存项
cache.delete('key1')
# 验证缓存项是否已被删除
value = cache.get('key1')
print('Cached value:', value) # 输出: Cached value: None
# 关闭缓存对象
cache.close()
判断键是否存在
from zdppy_cache import Cache
# 实例化缓存对象,指定缓存目录
cache = Cache('tmp/mycache')
# 设置缓存项
cache.set('key1', 'value1')
# 检查键是否存在
if 'key2' in cache:
print("Key2 exists in cache")
else:
print("Key2 does not exist in cache")
# 关闭缓存对象
cache.close()
设置过期时间
from zdppy_cache import Cache
# 实例化缓存对象,指定缓存目录
# cache = Cache('tmp/mycache')
cache = Cache()
# 设置缓存项,其中expire参数指定过期时间(单位:秒)
cache.set('key3', 'value3', expire=3)
print("没过期:", cache.get('key3'))
# 等待一段时间后尝试获取
import time
time.sleep(3)
value = cache.get('key3')
print('已经过期了:', value) # 输出: Cached value after expiration: None
# 关闭缓存对象
cache.close()
手动清理缓存
from zdppy_cache import Cache
# 实例化缓存对象,指定缓存目录
# cache = Cache('tmp/mycache')
cache = Cache()
# 手动清理过期缓存
cache.expire()
# 定期清理可以结合定时任务或后台进程来实现
# 关闭缓存对象
cache.close()
自动清理缓存
from zdppy_cache import Cache
# DiskCache支持自动清理策略,如最少使用(LRU)清理,确保缓存的大小在控制范围内。
# 实例化缓存,指定大小限制为100MB
# DiskCache将自动管理缓存大小,根据LRU算法清理最少使用的缓存项
cache = Cache('tmp/mycache', size_limit=100 * 1024 * 1024)
# 关闭缓存对象
cache.close()
缓存函数
from zdppy_cache import Cache
# DiskCache支持自动清理策略,如最少使用(LRU)清理,确保缓存的大小在控制范围内。
# 实例化缓存,指定大小限制为100MB
# DiskCache将自动管理缓存大小,根据LRU算法清理最少使用的缓存项
cache = Cache('tmp/mycache', size_limit=100 * 1024 * 1024)
# DiskCache提供了装饰器,可以非常方便地缓存特定函数的返回结果,减少重复计算。
# 使用lru_cache装饰器自动缓存函数结果
@cache.memoize()
def compute_expensive_operation(x):
# 模拟耗时计算
return x * x * x
# 第一次调用,计算结果并缓存
result = compute_expensive_operation(3)
print(result) # 输出: 27
# 第二次调用,直接从缓存获取结果
result = compute_expensive_operation(3)
print(result) # 输出: 27
# 关闭缓存对象
cache.close()
并发安全
import threading
from zdppy_cache import Cache
# DiskCache支持自动清理策略,如最少使用(LRU)清理,确保缓存的大小在控制范围内。
# 实例化缓存,指定大小限制为100MB
# DiskCache将自动管理缓存大小,根据LRU算法清理最少使用的缓存项
cache = Cache('tmp/mycache', size_limit=100 * 1024 * 1024)
def cache_operations():
cache.set('key', 'value')
print('Cached:', cache.get('key'))
# DiskCache是线程安全和进程安全的,可以在多线程和多进程环境中安全使用。
# 在多线程环境下使用缓存
thread1 = threading.Thread(target=cache_operations)
thread2 = threading.Thread(target=cache_operations)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
# 关闭缓存对象
cache.close()
缓存到底是怎么实现的
执行缓存的函数如下:
with Cache(cache.directory) as reference:
reference.set('key', 'value')
所以,缓存的逻辑都在这个set方法里面。
set方法的完整代码如下:
def set(
self,
key,
value,
expire=None,
read=False,
tag=None,
retry=False,
):
"""
设置key的缓存为value,类似于存储了一个字典的键值对
当read为True时,value应该是一个类似文件的对象,以二进制模式打开以供读取。
当数据库超时并且retry为False(默认)时引发Timeout错误。
:param key: 键
:param value: 值
:param float expire: 超时时间,默认不超时。浮点数类型,单位是秒。
:param bool read: 是否读取二进制文件,默认False
:param str tag: 类似于给key进行分组,打标签
:param bool retry: 是否重试,默认False
:return: 成功返回True
:raises Timeout: 超时抛出异常
"""
# 记录开始时间
now = time.time()
# 存储key
db_key, raw = self._disk.put(key)
# 计算超时时间
expire_time = None if expire is None else now + expire
# 进行存储
size, mode, filename, db_value = self._disk.store(value, read, key=key)
# 对存储的结果,进行封装,是一个元组
columns = (expire_time, tag, size, mode, filename, db_value)
# The order of SELECT, UPDATE, and INSERT is important below.
# 使用示例:
# value = cache.get(key)
# if value is None:
# value = expensive_calculation()
# cache.set(key, value)
#
# Cache.get 不清理过期的键以避免查找期间的写操作。
# 因此,常用/过期(used/expired)的键将保留在缓存中,使UPDATE成为首选路径。
# 另一种方法是假设键不存在,首先尝试INSERT,然后处理由于违反UNIQUE约束而发生的IntegrityError。
# 基于常见的缓存使用模式,这种乐观的方法被拒绝了。
# INSERT OR REPLACE也就是UPSERT没有被使用,因为旧的文件名可能需要清理。
with self._transact(retry, filename) as (sql, cleanup):
# 执行SQL,获取结果
rows = sql(
'SELECT rowid, filename FROM Cache'
' WHERE key = ? AND raw = ?',
(db_key, raw),
).fetchall()
if rows:
# 如果找到了,清理旧的数据,再执行更新
((rowid, old_filename),) = rows
cleanup(old_filename)
self._row_update(rowid, now, columns)
else:
# 如果没有找到,直接写入
self._row_insert(db_key, raw, now, columns)
# 计算是否超过缓存限制
self._cull(now, sql, cleanup)
# 成功了
return True
下节课计划
封装一些简单的方法,比如:
- set:设置缓存,带默认超时时间
- get:获取缓存
- delete:删除缓存
- delete_all:清空缓存