关于Redis的安装配置,可以参考前面的一篇:
https://blog.csdn.net/weixin_46307478/article/details/122204294
二、使用python操作Redis
python中我们使用redis-py库来操作Redis数据库,下面将着重介绍。
(base) [mca@clu01 ~]$ conda activate odc
(odc) [mca@clu01 ~]$ pip install redis
1.连接
第一种方式:普通
import redis # 导入redis模块,通过python操作redis 也可以直接在redis主机的服务端操作缓存数据库
r = redis.Redis(host='localhost', port=6379, decode_responses=True) # host是redis主机,需要redis服务端和客户端都启动 redis默认端口是6379
r.set('name', 'junxi') # key是"name" value是"junxi" 将键值对存入redis缓存
print(r['name'])
print(r.get('name')) # 取出键name对应的值
print(type(r.get('name')))
# 指定密码,数据库
redis_conn = redis.Redis(host='127.0.0.1', port= 6379, password= 'your pw', db= 0)
第二种方式:连接池
redis-py使用connection pool来管理对一个redis server的所有连接,避免每次建立、释放连接的开销。默认,每个Redis实例都会维护一个自己的连接池。
可以直接建立一个连接池,然后作为参数Redis,这样就可以实现多个Redis实例共享一个连接池。
import redis # 导入redis模块,通过python操作redis 也可以直接在redis主机的服务端操作缓存数据库
pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=True) # host是redis主机,需要redis服务端和客户端都起着 redis默认端口是6379
r = redis.Redis(connection_pool=pool)
r.set('gender', 'male') # key是"gender" value是"male" 将键值对存入redis缓存
print(r.get('gender')) # gender 取出键male对应的值
# redis_pool = redis.ConnectionPool(host='127.0.0.1', port= 6379, password= 'your pw', db= 0)
管道
redis-py默认在执行每次请求都会创建(连接池申请连接)和断开(归还连接池)一次连接操作,如果想要在一次请求中指定多个命令,则可以使用pipline实现一次请求指定多个命令,并且默认情况下一次pipline 是原子性操作。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import redis
pool = redis.ConnectionPool(host='192.168.22.132', port=6379)
r = redis.Redis(connection_pool=pool)
# pipe = r.pipeline(transaction=False)
pipe = r.pipeline(transaction=True)
pipe.set('name', 'root')
pipe.set('role', 'root')
pipe.execute()
2.常用数据结构
- String-字符串
- List-列表
- Hash-哈希
- Set-集合
- ZSet-有序集合
- Bitmap-位图
各个数据类型应用场景:
类型 | 简介 | 特性 | 场景 |
---|---|---|---|
String(字符串) | 二进制安全 | 可以包含任何数据,比如jpg图片或者序列化的对象,一个键最大能存储512M | — |
Hash(字典) | 键值对集合,即编程语言中的Map类型 | 适合存储对象,并且可以像数据库中update一个属性一样只修改某一项属性值(Memcached中需要取出整个字符串反序列化成对象修改完再序列化存回去) | 存储、读取、修改用户属性 |
List(列表) | 链表(双向链表) | 增删快,提供了操作某一段元素的API | 1,最新消息排行等功能(比如朋友圈的时间线) 2,消息队列 |
Set(集合) | 哈希表实现,元素不重复 | 1、添加、删除,查找的复杂度都是O(1) 2、为集合提供了求交集、并集、差集等操作 | 1、共同好友 2、利用唯一性,统计访问网站的所有独立ip 3、好友推荐时,根据tag求交集,大于某个阈值就可以推荐 |
Sorted Set(有序集合) | 将Set中的元素增加一个权重参数score,元素按score有序排列 | 数据插入集合时,已经进行天然排序 | 1、排行榜 2、带权重的消息队列 |
由于作者主要使用的是zset数据结构,以下仅总结Zset结构的使用:
3.zset集合操作
redis有序集合:
Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
zset的成员是唯一的,但分数(score)却可以重复。
python redis提供的方法与命令行基本一致, 具体的函数及含义可以参考给定的命令行来使用, 对应的函数名称与命令名称基本一致
常规的ZSET官方操作命令:
1 ZADD key score1 member1 [score2 member2] 向有序集合添加一个或多个成员,或者更新已存在成员的分数
2 ZCARD key 获取有序集合的成员数
3 ZCOUNT key min max 计算在有序集合中指定区间分数的成员数
4 ZINCRBY key increment member 有序集合中对指定成员的分数加上增量 increment
5 ZINTERSTORE destination numkeys key [key ...] 计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中
6 ZLEXCOUNT key min max 在有序集合中计算指定字典区间内成员数量
7 ZRANGE key start stop [WITHSCORES] 通过索引区间返回有序集合成指定区间内的成员
8 ZRANGEBYLEX key min max [LIMIT offset count] 通过字典区间返回有序集合的成员
9 ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT] 通过分数返回有序集合指定区间内的成员
10 ZRANK key member 返回有序集合中指定成员的索引
11 ZREM key member [member ...] 移除有序集合中的一个或多个成员
12 ZREMRANGEBYLEX key min max 移除有序集合中给定的字典区间的所有成员
13 ZREMRANGEBYRANK key start stop 移除有序集合中给定的排名区间的所有成员
14 ZREMRANGEBYSCORE key min max 移除有序集合中给定的分数区间的所有成员
15 ZREVRANGE key start stop [WITHSCORES] 返回有序集中指定区间内的成员,通过索引,分数从高到底
16 ZREVRANGEBYSCORE key max min [WITHSCORES] 返回有序集中指定分数区间内的成员,分数从高到低排序
17 ZREVRANK key member 返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序
18 ZSCORE key member 返回有序集中,成员的分数值
19 ZUNIONSTORE destination numkeys key [key ...] 计算给定的一个或多个有序集的并集,并存储在新的 key 中
20 ZSCAN key cursor [MATCH pattern] [COUNT count] 迭代有序集合中的元素(包括元素成员和元素分值)
21 BZPOPMAX kes timeout BZPOPMAX是有序集ZPOPMAX原语的阻塞变体。 当没有任何成员从任何给定的有序集中弹出时,
它会阻止连接 timeout 为阻塞的超时时间,防止一直阻塞 例如: BZPOPMAX zset1 zset2 0
22 BZPOPMIN 阻塞抛出最小值
23 ZPOPMAX 抛出最大值
24 ZPOPMIN 抛出最小值
25 ZREVRANGEBYLEX 当排序集中的所有元素都插入相同的分数时,为了强制执行词典排序,此命令将返回排序集中的所有元素,其key值为max和之间min
Python的Zset
python-redis提供了对应的25种命令支持, 对应的名称与命令行基本一致
如下为一些函数的用法:
def zadd(self, name, mapping, nx=False, xx=False, ch=False, incr=False)
#在name对应的有序集合中添加元素
rediscli.zadd("me1", mapping={"x1": 1, "x2": 3})
1
def zcard(self, name)
#获取有序集合的成员数
rediscli.zcard("me1")
1
def zcount(self, name, min, max)
#获取name对应的有序集合中分数 在 [min,max] 之间的个数
rediscli.zcount("me1", 0, 5)
1
def zincrby(self, name, amount, value)
#有序集合name中对指定成员的分数加上增量 increment
def zinterstore(self, dest, keys, aggregate=None)
#计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中
def zlexcount(self, name, min, max)
#在有序集合中计算指定字典区间内成员数量
rediscli.zlexcount('me1', "[a", "[v")
1
def zpopmax(self, name, count=None)
#抛出最大值
def zpopmin(self, name, count=None)
#抛出最小值
def bzpopmax(self, keys, timeout=0)
#抛出最大值
def bzpopmin(self, keys, timeout=0)
def zrange(self, name, start, end, desc=False, withscores=False, score_cast_func=float)
#按照索引范围获取name对应的有序集合的元素
"""参数:
name,redis的name
start,有序集合索引起始位置(非分数)
end,有序集合索引结束位置(非分数)
desc,排序规则,默认按照分数从小到大排序
withscores,是否获取元素的分数,默认只获取元素的值
score_cast_func,对分数进行数据转换的函数"""
rediscli.zrange('me1', 0, 5)
输出: ['x1', 'x2']
rediscli.zrange('me1', 0, 5, withscores=True)
输出:
[('x1', 1.0), ('x2', 3.0)]
1
2
3
4
5
6
def zrangebylex(self, name, min, max, start=None, num=None)
#通过字典区间返回有序集合的成员
"""参数:
name,redis的name
min,左区间(值)。 + 表示正无限; - 表示负无限; ( 表示开区间; [ 则表示闭区间
min,右区间(值)
start,对结果进行分片处理,索引位置
num,对结果进行分片处理,索引后面的num个元素"""
zrangebylex('me1', '-', '(x')
1
def zrevrangebylex(self, name, max, min, start=None, num=None)
def zrangebyscore(self, name, min, max, start=None, num=None, withscores=False, score_cast_func=float)
rediscli.zrangebyscore('me1', 2, 5)
1
def zrank(self, name, value)
#获取某个值在 name对应的有序集合中的排行(从 0 开始)
def zrem(self, name, *values)
#删除name对应的有序集合中值是values的成员
def zremrangebylex(self, name, min, max)
def zremrangebyrank(self, name, min, max)
#根据排行范围删除
def zremrangebyscore(self, name, min, max)
#根据分数范围删除
def zrevrange(self, name, start, end, withscores=False, score_cast_func=float)
def zrevrangebyscore(self, name, max, min, start=None, num=None, withscores=False, score_cast_func=float)
def zrevrank(self, name, value)
def zscore(self, name, value)
zscan(name, cursor=0, match=None, count=None, score_cast_func=float)
rediscli.scan()
输出: (0L, ['me1', 'm1', 'name', 'm2'])
1
2
3
zscan_iter(name, match=None, count=None,score_cast_func=float)
#列出所有键, 生成器的形式,相较于字符串新增score_cast_func,用来对分数进行操作
def zinterstore(dest, keys, aggregate=None)
#获取两个有序集合的交集,如果遇到相同值不同分数,则按照aggregate进行操作
aggregate的值为: SUM MIN MAX
def zunionstore(dest, keys, aggregate=None)
#获取两个有序集合的并集,如果遇到相同值不同分数,则按照aggregate进行操作
aggregate的值为: SUM MIN MAX
示例程序:
# coding:utf-8
import redis
rediscli = redis.Redis(host='127.0.0.1', port=8888, db=13)
print rediscli.zadd("me1", mapping={"x1": 1, "x2": 3})
print rediscli.zadd("me2", mapping={"x1": 1, "x3": 5, "x4": 3})
print rediscli.zcard("me1")
print rediscli.zcount("me1", 0, 5)
print rediscli.zrange('me1', 0, 5, withscores=False)
print rediscli.zrange('me1', 0, 5, withscores=True)
print rediscli.zincrby("me1", amount=1, value="x1")
print rediscli.zinterstore(dest="me3", keys=['me1', 'me2'])
print rediscli.zrange('me3', 0, 5, withscores=True)
print rediscli.zlexcount('me1', "[a", "[v")
print rediscli.zrangebylex('me1', '-', '(x')
print rediscli.zrangebyscore('me1', 2, 5)
print rediscli.zrank('me1', 'x1')
print rediscli.zscore('me1', 'x1')
print rediscli.zadd('me1', mapping={"x4": 4})
print rediscli.zrem('me1', 'x4')
print rediscli.zremrangebyrank('me1', 7, 10)
print rediscli.zremrangebyscore('me1', 11, 15)
print rediscli.zrevrangebyscore('me1', 8, 3)
print rediscli.zrevrange('me1', 0, -1, withscores=True)
print rediscli.zrange('me1', 0, -1, withscores=True)
print rediscli.scan()
输出结果:
2
3
2
2
['x1', 'x2']
[('x1', 1.0), ('x2', 3.0)]
2.0
1
[('x1', 3.0)]
0
[]
['x1', 'x2']
0
2.0
1
1
0
0
['x2']
[('x2', 3.0), ('x1', 2.0)]
[('x1', 2.0), ('x2', 3.0)]
(0L, ['me3', 'me2', 'me1'])
参考:
python redis详解(七)ZSET有序集合_comprel的博客-CSDN博客_python redis zset