django-redis使用


django-redis使用

1. 安装

安装:

pip install django-redis

2. 配置

在 Django 项目的 settings.py 中配置缓存后端为 Redis,主要修改 CACHES 配置项。

# settings.py
CACHES = {
    "default": {
        # 指定缓存后端为 django_redis
        "BACKEND": "django_redis.cache.RedisCache",
        # Redis 连接地址(格式:redis://[:密码]@主机:端口/数据库编号)
        "LOCATION": "redis://127.0.0.1:6379/1",  # 数据库 1(默认 0)
        "OPTIONS": {
            # 指定 Redis 客户端(基于 redis-py)
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
            # 可选:连接池配置(优化性能)
            "CONNECTION_POOL_KWARGS": {
                "max_connections": 100,  # 最大连接数
            },
            # 可选:密码(如果 Redis 配置了密码)
            # "PASSWORD": "your_redis_password",
        }
    }
}

若需用 Redis 存储 Django 会话(替代默认的数据库存储),添加以下配置:

# settings.py
# 会话存储引擎改为 Redis
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
# 使用上面配置的 "default" 缓存
SESSION_CACHE_ALIAS = "default"

3. 使用

1. 获取客户端

获取原始Redis客户端

from django_redis import get_redis_connection

# 获取连接(默认使用 "default" 缓存配置)
conn = get_redis_connection("default")  # "default" 对应 CACHES 中的键

2. 操作命令

1. 字符串(String)

字符串是 Redis 最基本的数据类型,可存储文本、数字等,适合缓存简单数据(如用户信息、计数器)。

常用命令示例:

命令 作用 示例 返回值(及解码)
set(key, value) 设置键值对(覆盖已有键) conn.set("name", "zhangsan") True(成功)
get(key) 获取键对应的值 conn.get("name") b'zhangsan' → 解码:conn.get("name").decode("utf-8")'zhangsan'
setex(key, seconds, value) 设置带过期时间的键值对(原子操作) conn.setex("code", 60, "123456") # 60 秒后过期 True(成功)
incr(key) 对键的数值自增 1(键不存在则初始化为 0 后 + 1) conn.incr("count") # 初始 count 为 0 → 自增后为 1 自增后的值(1
incrby(key, n) 对键的数值自增 n(n 为整数) conn.incrby("count", 5) # count 从 1 → 6 自增后的值(6
decr(key) 对键的数值自减 1 conn.decr("count") # count 从 6 → 5 自减后的值(5
append(key, value) 向已有字符串末尾追加内容 conn.append("name", "_male") # name 原为 "zhangsan" → 变为 "zhangsan_male" 追加后字符串的长度(13
strlen(key) 获取字符串长度 conn.strlen("name") 长度(13

2. 列表(List)

列表是有序的字符串集合(可重复),底层是双向链表,适合实现消息队列、最新列表等场景(如朋友圈动态、任务队列)。

常用命令示例:

命令 作用 示例 返回值(及说明)
lpush(key, *values) 向列表左侧(头部)插入一个 / 多个元素 conn.lpush("mylist", "a", "b", "c") 插入后列表的长度(3
rpush(key, *values) 向列表右侧(尾部)插入一个 / 多个元素 conn.rpush("mylist", "d") # 列表变为 [c, b, a, d](左侧为头,右侧为尾) 插入后列表的长度(4
lpop(key) 移除并返回列表左侧(头部)第一个元素 conn.lpop("mylist") # 移除 "c" 被移除的元素(b'c'
rpop(key) 移除并返回列表右侧(尾部)第一个元素 conn.rpop("mylist") # 移除 "d" 被移除的元素(b'd'
lrange(key, start, end) 获取列表中 [start, end] 区间的元素(start=0 表示第一个,end=-1 表示最后一个) conn.lrange("mylist", 0, -1) # 列表当前为 [b, a] 元素列表([b'b', b'a']
llen(key) 获取列表长度 conn.llen("mylist") 长度(2
lrem(key, count, value) 从列表中删除 count 个值为 value 的元素(count>0 从左删;count<0 从右删;count=0 删所有) conn.lrem("mylist", 1, "b") # 从左删 1 个 "b" 被删除的元素数量(1
lset(key, index, value) 将列表指定索引的元素替换为 value(索引越界会报错) conn.lset("mylist", 0, "x") # 列表原为 [a] → 变为 [x] True(成功)

3. 哈希(Hash)

哈希适合存储对象类数据(如用户信息、商品属性),每个哈希可包含多个字段(field)和对应的值(value)。

常用命令示例:

命令 作用 示例 返回值(及说明)
hset(key, field, value) 给哈希表设置一个字段和值 conn.hset("user:1", "name", "zhangsan") 1(新增字段);0(字段已存在,仅更新值)
hset(key, mapping={}) 批量设置哈希表的字段和值(mapping 为字典) conn.hset("user:1", mapping={"age": 20, "gender": "male"}) 成功设置的字段数量(2
hget(key, field) 获取哈希表中指定字段的值 conn.hget("user:1", "name") 字段值(b'zhangsan'
hgetall(key) 获取哈希表中所有字段和值 conn.hgetall("user:1") 字典形式({b'name': b'zhangsan', b'age': b'20', b'gender': b'male'}
hkeys(key) 获取哈希表中所有字段名 conn.hkeys("user:1") 字段名列表([b'name', b'age', b'gender']
hvals(key) 获取哈希表中所有字段值 conn.hvals("user:1") 字段值列表([b'zhangsan', b'20', b'male']
hexists(key, field) 判断哈希表中是否存在指定字段 conn.hexists("user:1", "name") True(存在);False(不存在)
hdel(key, *fields) 删除哈希表中一个 / 多个字段 conn.hdel("user:1", "gender") 被删除的字段数量(1
hincrby(key, field, amount) 对哈希表中指定字段的数值增减(amount 为整数) conn.hincrby("user:1", "age", 1) # age 从 20 → 21 增减后的值(21

4. 集合(Set)

集合是无序的字符串集合(元素唯一),适合存储去重数据(如标签、粉丝列表),支持交集、并集等集合运算。

常用命令示例:

命令 作用 示例 返回值(及说明)
sadd(key, *members) 向集合添加一个 / 多个元素(重复元素会被忽略) conn.sadd("tags", "python", "django", "redis") 成功添加的元素数量(3
smembers(key) 获取集合中所有元素 conn.smembers("tags") 元素集合({b'python', b'django', b'redis'}
sismember(key, member) 判断元素是否在集合中 conn.sismember("tags", "python") True(存在);False(不存在)
scard(key) 获取集合中元素的数量 conn.scard("tags") 数量(3
srem(key, *members) 从集合中删除一个 / 多个元素 conn.srem("tags", "redis") 被删除的元素数量(1
spop(key, count=1) 随机删除并返回集合中 count 个元素 conn.spop("tags", 1) # 随机删除 1 个元素 被删除的元素(如 [b'django']
sinter(key1, key2) 求两个集合的交集(同时存在于两个集合的元素) conn.sadd("tags2", "django", "flask"); conn.sinter("tags", "tags2") 交集元素({b'django'}
sunion(key1, key2) 求两个集合的并集(所有元素去重) conn.sunion("tags", "tags2") 并集元素({b'python', b'django', b'flask'}

5. 有序集合(Sorted Set)

有序集合类似集合,但每个元素关联一个 分数(score),Redis 按分数对元素排序,适合实现排行榜、带权重的任务队列等。

常用命令示例:

命令 作用 示例 返回值(及说明)
zadd(key, mapping={}, nx=False) 向有序集合添加元素(mapping 为 {元素:分数};nx=True 表示仅添加不存在的元素) conn.zadd("ranking", {"user1": 80, "user2": 90, "user3": 70}) 成功添加的元素数量(3
zrange(key, start, end, withscores=False) 按分数升序获取 [start, end] 区间的元素(withscores=True 同时返回分数) conn.zrange("ranking", 0, -1, withscores=True) 元素列表([(b'user3', 70.0), (b'user1', 80.0), (b'user2', 90.0)]
zrevrange(key, start, end, withscores=False) 按分数降序获取元素(与 zrange 相反) conn.zrevrange("ranking", 0, -1) 降序元素([b'user2', b'user1', b'user3']
zscore(key, member) 获取元素的分数 conn.zscore("ranking", "user2") 分数(90.0
zincrby(key, amount, member) 增加元素的分数(amount 可为负数) conn.zincrby("ranking", 5, "user1") # user1 分数从 80 → 85 增减后的分数(85.0
zrank(key, member) 获取元素按分数升序的排名(从 0 开始) conn.zrank("ranking", "user1") # 此时 user1 分数 85,排名第 1 排名(1
zrem(key, *members) 从有序集合中删除元素 conn.zrem("ranking", "user3") 被删除的元素数量(1

6. 通用命令

以下命令可操作任意类型的键:

命令 作用 示例 返回值(及说明)
exists(key) 判断键是否存在 conn.exists("name") 1(存在);0(不存在)
delete(*keys) 删除一个 / 多个键(无论类型) conn.delete("name", "mylist") 被删除的键数量(2
expire(key, seconds) 给键设置过期时间(秒) conn.expire("user:1", 3600) # 1 小时后过期 True(成功);False(键不存在)
ttl(key) 查看键的剩余过期时间(秒) conn.ttl("user:1") 剩余秒数(如 3500);-1(永久有效);-2(已过期)
type(key) 查看键的类型(string/list/hash/set/zset 等) conn.type("user:1") 类型(b'hash'
keys(pattern) 查找匹配 pattern 的所有键(生产环境慎用,可能阻塞 Redis) conn.keys("user:*") # 匹配所有以 user: 开头的键 键列表([b'user:1']

7. 注意事项

  1. 字节类型解码:所有返回值默认是 bytes 类型,需用 decode("utf-8") 转为字符串(如 conn.get("name").decode("utf-8"))。
  2. 命令大小写:Redis 原生命令通常大写(如 SET),但 redis-py 中支持小写(如 conn.set()),效果一致。
  3. 批量操作效率:对大量数据操作时,建议用 管道(Pipeline) 减少网络往返(见下方示例)。
  4. 生产环境慎用 keys()keys(*) 会遍历所有键,数据量大时会阻塞 Redis,建议用 scan() 替代。

4. 高级设置

1. 设置全局过期时间

CACHES = {
    "default": {
        # ... 其他配置 ...
        "TIMEOUT": 300,  # 全局默认 5 分钟过期(None 表示永久)
    }
}

2. 批量删除键

from django_redis import get_redis_connection

conn = get_redis_connection("default")
# 删除所有以 "user:" 开头的键
conn.delete_pattern("user:*")

4. 管道操作

批量执行命令,减少网络返(提升性能)

conn = get_redis_connection("default")
pipe = conn.pipeline()  # 创建管道

# 批量添加命令
pipe.set("a", 1).set("b", 2).incr("a")
# 执行所有命令
pipe.execute()  # 返回 [True, True, 2]

0 条评论

发表评论

暂无评论,欢迎发表您的观点!