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

下面我将围绕 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 服务器,也可以连接到一个服务器集群。

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高得多。
示例:

# 获取单个值
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-memcached 的 Client 对象内部已经实现了连接池,会复用与 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 是一个可靠且功能完备的选择,如果你追求极致性能或在异步环境中工作,可以考虑 pymemcache 或 aiomemcache。
