杰瑞科技汇

Python memcache模块如何使用?

Python 官方或社区中并没有一个叫做 memcache 的标准库,通常大家所说的 memcache 模块,指的是由 evan 编写的第三方库 python-memcached,它是 Python 语言连接和操作 Memcached 服务最常用、最经典的库。

Python memcache模块如何使用?-图1
(图片来源网络,侵删)

下面我将围绕 python-memcached 这个库展开介绍。


什么是 Memcached?

在讲 Python 模块之前,先简单理解一下 Memcached 本身。

  • 定义:Memcached 是一个高性能的、分布式的内存对象缓存系统。
  • 目的:通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态网站、API 等应用的响应速度和性能。
  • 工作原理:它将数据存储在内存中,当需要访问数据时,先从 Memcached 中查找,如果找到(缓存命中),则直接返回;如果没找到(未命中),则从数据库等后端源获取数据,然后将数据存入 Memcached 供下次使用。
  • 特点
    • 简单:API 简单,使用基于文本的协议。
    • 快速:基于内存,速度极快。
    • 多线程:使用非阻塞的 I/O 处理,可以高效处理并发连接。
    • 分布式:可以轻松地水平扩展,通过添加更多节点来增加缓存容量。
    • 数据结构简单:只支持最简单的 key-value 存储,value 通常是字符串或字节串。

安装 python-memcached

使用 pip 命令进行安装:

pip install python-memcached

基本使用

1 连接到 Memcached 服务器

python-memcached 使用 Client 类来表示一个连接,你可以连接到单个 Memcached 服务器,也可以连接到一个服务器集群。

Python memcache模块如何使用?-图2
(图片来源网络,侵删)
import memcache
# 连接到单个 Memcached 服务器
# mc = memcache.Client(['127.0.0.1:11211'], debug=0)
# 连接到 Memcached 集群 (推荐)
# Client 会自动在多个服务器间进行数据分布和故障转移
mc = memcache.Client(['127.0.0.1:11211', '127.0.0.1:11212'], debug=0)
# debug=0 表示在生产环境中关闭调试信息,避免输出过多日志
# debug=1 会打印出详细的操作日志,方便调试

2 核心操作

Client 对象提供了与 key-value 存储相关的各种方法。

2.1 存储数据 (set, add, replace, append, prepend)

  • set(key, value, time=0, min_compress_len=0): 设置一个键值对,key 已存在,则覆盖其值。
  • add(key, value, time=0, min_compress_len=0): 添加一个键值对。仅当 key 不存在时才添加,key 已存在,则操作失败。
  • replace(key, value, time=0, min_compress_len=0): 替换一个键值对。仅当 key 存在时才替换,key 不存在,则操作失败。
  • append(key, value): 将 value 追加到指定 key 原有值的末尾。
  • prepend(key, value): 将 value 追加到指定 key 原有值的开头。

参数说明:

  • key: 键名,字符串类型。
  • value: 值,可以是任何可序列化的 Python 对象(如字符串、数字、列表、字典等)。python-memcached 会自动将其序列化为字符串存储。
  • time: 缓存过期时间,单位是,如果为 0,表示永不过期(但 Memcached 可能会在内存不足时将其淘汰),最大不能超过 30 天(2592000 秒)。
  • min_compress_len: 当 value 大于这个值时,会先进行压缩再存储。

示例:

# 使用 set 存储数据
mc.set('username', 'Alice', time=60)  # 存储用户名,60秒后过期
mc.set('user:1001', {'name': 'Bob', 'age': 30}) # 存储一个字典
# 使用 add 添加数据,'username' 已存在,此操作会失败
result_add = mc.add('username', 'Charlie')
print(f"Add result: {result_add}") # 输出: Add result: False
# 使用 replace 替换数据,'username' 不存在,此操作会失败
result_replace = mc.replace('non_existent_key', 'David')
print(f"Replace result: {result_replace}") # 输出: Replace result: False
# 使用 append 和 prepend
mc.set('greeting', 'Hello ')
mc.append('greeting', 'World')
mc.prepend('greeting', 'Say: ')
print(mc.get('greeting')) # 输出: Say: Hello World

2.2 获取数据 (get, gets)

  • get(key): 获取指定 key 的值,key 不存在,返回 None
  • get_multi(keys): 批量获取多个 key 的值,返回一个字典 {key: value, ...},效率比循环调用 get 高得多。

示例:

Python memcache模块如何使用?-图3
(图片来源网络,侵删)
# 获取单个值
username = mc.get('username')
print(f"Username: {username}") # 输出: Username: Alice
# 获取多个值
user_data = mc.get_multi(['username', 'user:1001'])
print(user_data)
# 可能的输出:
# {
#     'username': 'Alice',
#     'user:1001': {'name': 'Bob', 'age': 30}
# }

2.3 删除数据 (delete)

  • delete(key, time=0): 删除指定的 key。time 参数在这里表示一个“延迟删除”时间,通常设为 0。

示例:

# 删除 'greeting' 键
mc.delete('greeting')
print(mc.get('greeting')) # 输出: None

2.4 增减操作 (incr, decr)

  • incr(key, delta=1): 将 key 对应的值增加 delta,key 的值必须是数字字符串(如 "123")。
  • decr(key, delta=1): 将 key 对应的值减少 delta

这些操作是原子性的,非常适合用于计数器,如点赞数、商品库存等。

示例:

# 初始化一个计数器
mc.set('page_views', '100')
# 增加访问量
mc.incr('page_views', 5)
print(mc.get('page_views')) # 输出: 105
# 减少库存
mc.set('product_stock', '50')
mc.decr('product_stock', 2)
print(mc.get('product_stock')) # 输出: 48

2.5 其他操作

  • stats(): 获取 Memcached 服务器的统计信息。
  • flush_all(): 清空所有缓存,这是一个危险操作,慎用!它会立即清除所有节点上的所有数据。
  • disconnect_all(): 关闭所有连接。

高级特性与最佳实践

1 连接池

python-memcachedClient 对象内部已经实现了连接池,会复用与 Memcached 服务器的连接,所以你不需要自己手动管理连接池,直接创建一个 Client 实例并在整个应用中复用它即可。

2 处理服务器宕机

当一个 Memcached 节点宕机时,python-memcached 会自动将后续的请求重试到集群中的其他可用节点,这提供了基本的容错能力。

3 缓存穿透、击穿、雪崩

虽然这是通用的缓存问题,但在使用 Memcached 时需要特别注意:

  • 缓存穿透:查询一个根本不存在的数据,解决方案:如果查询的数据在缓存和数据库中都不存在,可以在缓存中存储一个空值或特殊标记(mc.set(key, None)),并设置一个较短的过期时间。
  • 缓存击穿:一个热点key在某一刻突然失效,大量并发请求直接打到数据库上,解决方案:对热点数据的缓存过期时间设置长一些,或者使用互斥锁(如 threading.Lock),只允许一个线程去查询数据库并重建缓存。
  • 缓存雪崩:大量key在同一时间集体失效,导致所有请求瞬间涌向数据库,解决方案:为不同的 key 设置随机的过期时间,避免集体失效。

4 与 Django 的集成

python-memcached 是 Django 框架缓存后端(django.core.cache.backends.memcached.MemcachedCache)的默认实现之一。

settings.py 中配置:

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': '127.0.0.1:11211', # 或者 ['127.0.0.1:11211', '127.0.0.1:11212']
    }
}

之后就可以在 Django 视图或模型中使用 cache API 了:

from django.core.cache import cache
def my_view(request):
    # 尝试从缓存获取数据
    data = cache.get('my_expensive_data')
    if data is None:
        # 缓存未命中,从数据库获取
        data = MyModel.objects.all()
        # 将数据存入缓存,有效期 5 分钟
        cache.set('my_expensive_data', data, 60 * 5)
    # ... 处理 data ...

替代方案

虽然 python-memcached 是经典选择,但现在也有一些更新的替代品,它们通常性能更好或功能更强大:

  • pymemcache: 由 Twitter 开发,被认为是 python-memcached 的一个现代化替代品,它性能更高,API 设计更现代,支持 Python 3,并且对协议的实现更严格。
  • aiomemcache: 如果你的应用是基于 asyncio 的异步框架(如 FastAPI、aiohttp),aiomemcache 是一个更合适的选择,它提供了原生的异步支持。

特性 描述
库名称 python-memcached (非标准库,需 pip install)
核心类 memcache.Client
连接方式 支持单节点和集群,客户端会自动处理数据分布
基本操作 set, get, delete, add, replace, incr, decr
高级操作 get_multi (批量获取), stats, flush_all
数据类型 key 是字符串,value 会被自动序列化为字符串
优点 简单易用,稳定可靠,是 Django 等框架的默认后端
适用场景 需要高性能缓存来减轻数据库压力的场景,如页面缓存、API 响应缓存、会话存储、计数器等。

对于大多数 Python python-memcached 是一个可靠且功能完备的选择,如果你追求极致性能或在异步环境中工作,可以考虑 pymemcacheaiomemcache

分享:
扫描分享到社交APP
上一篇
下一篇