python缓存入门

1 简介

  • 什么是缓存呢?

​ 缓存就是利用编程技术把数据存储在临时位置,不用再去通过数据源获取数据。

  • 缓存的规则是什么?
    • 频繁调用的函数,输出不经常改变,执行需要很长时间
    • 缓存应该比从当前数据源获取数据快
    • 缓存影响内存占用,选择适当的数据结构进行缓存

2 缓存操作

缓存,如浏览器缓存,服务器缓存,代理缓存,硬件缓存。

无论哪种缓存,操作有两种主要类型:readwrite

  • 读缓存

​ 应用程序先去cache中读取数据,如果可以命中,则直接返回;如果没有命中,则去数据库中查询,成功后存入缓存

  • 写缓存

    应用程序先去更新数据库,成功后再删除缓存

3 缓存回收策略

缓存会使读写速度更快。速度的提高是因为缓存的数据很小,随着缓存的数据量增加,搜索所需要的时间也会增加。

因此空间优化就比较重要了,一旦缓存满了,我们需要通过一些手段删除缓存中的历史数据来为新数据腾出空间。

缓存回收策略主要用于决定要删除缓存中的哪些数据:

序号 方式 说明
1 LRU 当缓存耗尽空间时,删除最久未使用的缓存数据
2 LFU 淘汰最不常用的缓存数据
3 MRU 淘汰最近使用的缓存的数据
4 FIFO 缓存像队列一样工作,先进先出

4 缓存存放

缓存与web服务放在一起,会出现以下几点问题:

  1. 当服务器宕机时,会丢失所有与服务器相关的缓存数据。
  2. 当增加缓存内存时,会入侵服务器内存

最可靠的方案就是 在服务器外独立维护一个缓存服务

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查询。

DiskCacheApache2许可的磁盘和文件支持的缓存库,用纯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)
    • keyvalue分别代表缓存的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()

版权声明:本文为三叶草body原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/itelephant/p/16570945.html