python缓存入门
python缓存入门
1 简介
- 什么是缓存呢?
缓存就是利用编程技术把数据存储在临时位置,不用再去通过数据源获取数据。
- 缓存的规则是什么?
- 频繁调用的函数,输出不经常改变,执行需要很长时间
- 缓存应该比从当前数据源获取数据快
- 缓存影响内存占用,选择适当的数据结构进行缓存
2 缓存操作
缓存,如浏览器缓存,服务器缓存,代理缓存,硬件缓存。
无论哪种缓存,操作有两种主要类型:read
和 write
- 读缓存
应用程序先去cache中读取数据,如果可以命中,则直接返回;如果没有命中,则去数据库中查询,成功后存入缓存
-
写缓存
应用程序先去更新数据库,成功后再删除缓存
3 缓存回收策略
缓存会使读写速度更快。速度的提高是因为缓存的数据很小,随着缓存的数据量增加,搜索所需要的时间也会增加。
因此空间优化就比较重要了,一旦缓存满了,我们需要通过一些手段删除缓存中的历史数据来为新数据腾出空间。
缓存回收策略主要用于决定要删除缓存中的哪些数据:
序号 | 方式 | 说明 |
---|---|---|
1 | LRU | 当缓存耗尽空间时,删除最久未使用的缓存数据 |
2 | LFU | 淘汰最不常用的缓存数据 |
3 | MRU | 淘汰最近使用的缓存的数据 |
4 | FIFO | 缓存像队列一样工作,先进先出 |
4 缓存存放
缓存与web服务放在一起,会出现以下几点问题:
- 当服务器宕机时,会丢失所有与服务器相关的缓存数据。
- 当增加缓存内存时,会入侵服务器内存
最可靠的方案就是 在服务器外独立维护一个缓存服务
5 缓存的实现
5.1 python内置缓存
使用 functools
模块的 lur_cache
装饰器,可以缓存最多 maxsize
个此函数的调用结果,从而提高程序执行的效率,特别适合于耗时的函数。
参数:
-
maxsize
: 如果为 None,则无限制,设置为 2 的幂 时,性能最佳 -
typed
: 如果 typed=True,则不同参数类型的调用将分别缓存,例如 f(3) 和 f(3.0)
from functools import lru_cache
# 这种缓存适合服务端
@lru_cache(maxsize=20)
def fib(n):
print("此函数执行了")
if n < 2:
return n
return fib(n - 1) + fib(n - 2)
# 执行了函数,返回了结果 2
print(fib(3))
# 没有执行 fib函数,读取了缓存中的结果
print(fib(3))
"""
此函数执行了
此函数执行了
此函数执行了
此函数执行了
2
2
"""
5.2 磁盘缓存-diskcache库
diskcache
缓存对象管理是基于SQLite
数据库,它是一个轻量级的基于磁盘的数据库,该数据库不需要单独的服务器进程,并允许使用SQL
查询。
DiskCache
是Apache2
许可的磁盘和文件支持的缓存库,用纯Python编写。
当进程使用内存]时,磁盘上会留下千兆字节的空余空间。这些进程中有用Memcached
(有时是Redis
)作缓存。DiskCache
有效地将空余的磁盘空间用于缓存。
使用pip安装:pip install diskcache
5.2.1 Cache缓存
DiskCache
的核心是diskcache.Cache
,代表磁盘和文件支持的缓存。
from diskcache import Cache
# 实例一个缓存对象
# 需要传入目录路径。如果目录路径不存在,将创建该路径,并且会在指定位置创建一个cache.db的文件。
# 如果未指定,则会自动创建一个临时目录,并且会在指定位置创建一个cache.db的文件。
cache = Cache('./cache01')
5.2.1.1 保存和获取缓存
from diskcache import Cache
# 1. 实例一个缓存对象
# 需要传入目录路径。如果目录路径不存在,将创建该路径,并且会在指定位置创建一个cache.db的文件。
# 如果未指定,则会自动创建一个临时目录,并且会在指定位置创建一个cache.db的文件。
cache = Cache('./cache01')
# 2. 保存缓存
cache.set('name', '张三', expire=5, read=True, tag='姓名', retry=True)
# 3. 获取缓存 expire_time为真,返回有效期时间;tag为真,返回缓存设置的tag值;
name = cache.get('name', default=False, expire_time=True, tag=True, retry=True)
print(name) # ('张三', 1659593995.7302778, '姓名')
set(key, value, expire=None, read=False, tag=None, retry=False)
key
和value
分别代表缓存的key与缓存的值;expire
表示过期时间,单位秒;read
表示以二进制模式读取内容;tag
表示与key值相关的文本;retry
表示连接超时是否重试;
get(key, default=None, read=False, expire_time=False, tag=False, retry=False)
key
表示缓存的键值;default
表示如果对应的键值没有,则返回这个default设置的默认值;expire_time
表示返回缓存的过期时间(从纪元开始的秒数);tag
表示返回与key
值相关的文本;
5.2.1.2 更新缓存的时间
# 4. 更新缓存过期时间
result = cache.touch('name', expire=10, retry=True)
print(result)
# 5. 获取缓存信息
name = cache.get('name', default=False, expire_time=True, tag=True, retry=True)
print(name)
touch(key, expire=None, retry=False)
- key表示缓存的键值;
- expire表示设置的过期时间;
- retry表示是否超时重试;
5.2.1.3 add添加新的缓存
类似set
方法,当且仅当key
值不存在时,才会添加成功
# 6. add添加缓存
cache.add('name', '李四', expire=10, retry=True)
print(cache.get('name')) # 张三 添加失败
# 7. set添加缓存
cache.set('name', '李四', expire=10, retry=True)
print(cache.get('name')) # 李四 添加成功
5.2.1.4 删除缓存
delete删除返回True或False,而pop删除返回缓存的值
# 8. delete 删除缓存
cache.set('subject', 'python', expire=10, tag='编程语言', retry=True)
print(cache.delete('subject', retry=True)) # 返回 True, 删除成功
# 9. pop 删除缓存
cache.set('subject', 'python', expire=10, tag='编程语言', retry=True)
print(cache.pop('subject', retry=True)) # python 返回删除的缓存数据
5.2.1.5 删除所有过期的缓存
程序会自动删除过期的缓存数据, 也可以手动执行。
cache.expire()