redis-API使用
文章目录
- Redis-API使用
-
- 1. String
-
- 1. **set / setnx**
- 2. **setex**
- 3. **psetex**
- 4. **mset**
- 5. **incr / incrbyfloat**
- 6. **decr**
- 2. Hash
-
- 1. **hset / hget**
- 2. **hmset / hmget**
- 3. **hgetall**
- 4. **hlen / hkeys / hvals / hexists /hdel**
- 5. **hincrby / hincrbyfloat**
- 3. List
-
- 1. **lpush / rpush / llen /lrange**
- 2. **linsert**
- 3. lset
- 4. **lrem / lpop / rpop / blpop**
- 4. Set
-
- 1. **sadd**
- 2. **scard / sdiff**
- 3. **sdiffstore / sinterstore / sunionstore**
- 4. **sinter**
- 5. **smembers / sismember**
- 6. **smove**
- 7. **srem**
- 8. **sunion**
- 5. Sorted Set
-
- 1. **描述:**
- 2. **命令:**
- 6. redis管道
-
- 1. **描述**
- 2. **演示**
- 7. Redis发布订阅
-
- 1. **描述**
- 2. **举例说明**
- 3. **python实现**
Redis-API使用
redis
中文官网:
https://www.redis.net.cn/tutorial/3501.html
redis-py 的API的使用可以分类为:
- 连接方式
- 连接池
- 操作
- String 操作
- Hash 操作
- List 操作
- Set 操作
- Sorted Set 操作
- 管道
- 发布订阅
连接方式和连接池上一篇文章已经具体讲解与使用。具体请参考上篇。
本篇使用redis_connect
代替连接
1. String
1. set / setnx
set(name, value, ex=None, px=None, nx=False, xx=False)
在Redis中设置值,默认,不存在则创建,存在则修改
参数详解
ex
: 过期时间(秒)px
: 过期时间(毫秒)nx
: 如果设置为True,则只有name不存在时,当前set操作才执行xx
: 如果设置为True,则只有name存在时,当前set操作才执行
"""
set
"""
# 1. 插入数据一条
redis_connect.set('name', 'xiaodong')
# 根据key获取value
value1 = redis_connect.get('name')
print(value) # xiaodong"""
setnx: 则只有name不存在时,当前set操作才执行
"""
redis_connect.setnx('name', 'xiaodong1')
value2 = redis_connect.get('name')
print(value) # xiaodong
上述代码打印结果
value1: xiaodong
value2: xiaodong
出现这种结果说明setnx执行成功。setnx是当key不存在的时候才会执行set操作。 value1的时候key已经存在了,因此不会执行setnx
更正
redis_connect.setnx('name2', 'xiaodong2')
value2 = redis_connect.get('name2')
# value2: xiaodong2
name2不存在则执行
2. setex
设置过期时间
redis_connect.setex('setex_key', 30, '今天天气真好')
value3 = redis_connect.get('setex_key')
print(value3)
# 过期后 None
参数解释:
setex(key, time, value)
- time: 时间(秒)
3. psetex
设置过期时间
redis_connect.psetex('psetex_key', 300, 'psetex')
value4 = redis_connect.get('psetex_key')
print(value4)
# 过期后为None
参数解释:
psetex(key, time, value)
- time: 时间(毫秒)
4. mset
批量设置值
redis_connect.mset({'key1': "value1","key2": "value2","key3": "value3"})
value5 = redis_connect.mget('key1', 'key2', 'key3')
value6 = redis_connect.mget(['key1', 'key2', 'key3'])
print(value5)
print(value6)
# ['value1', 'value2', 'value3']
5. incr / incrbyfloat
Incr: 自增(整数)
Incrbyfloat : 自增(浮点数)
redis_connect.incr("incr_key", 1)
value7 = redis_connect.get("incr_key")
print(value7)
# 每次 += 1
# 如果设置为其他数, 比如说3, 那就是在当前结果的基础上 += 3
# 不传值默认是 1redis_connect.incrbyfloat("incrbyfloat", 1.1)
value8 = redis_connect.get("incrbyfloat")
print(value8)
# 每次 += 1.1
6. decr
decr 自减 (默认为1), 对当前key的value每次 -= 1
redis_connect.decr("decr_key")
value9 = redis_connect.get("decr_key")
print(value9)
2. Hash
hash
表现形式类似于python中的字典dict
1. hset / hget
hset
: name, key, value
hget
: name, key
redis_connect.hset("hset_key", "name", "xiaodong")
v1 = redis_connect.hget("hset_key", "name")
print(v1) # xiaodong
hset_key 就相当于一个标志物,用来识别你身份的东西,可以这么理解
name, xiaodong. 这两个可以理解为python中的字典key-value 对应关系 {“name”: “xiaodong”}
hget
就是通过拿到你的身份标识 hset_key
然后去获取对应key的value, 对应的key就是name
, 获取到的值就是xiaodong, 有点类似于python中的字典通过key取值.
2. hmset / hmget
hmset
: hmset(name, dict)
hmget
: hmget(name, args)
info = {"name": "xiaodong","age": 22,"gender": "男"
}
redis_connect.hmset("hmset_key", info)
v2 = redis_connect.hmget("hmset_key", ['name', 'gender'])
print(v2)
# ['xiaodong', '男']
3. hgetall
hgetall
: 获取所有的键值对
v3 = redis_connect.hgetall("hmset_key")
print(v3)
# {'name': 'xiaodong', 'age': '22', 'gender': '男'}
4. hlen / hkeys / hvals / hexists /hdel
hlen
: hlen(name) : 获取name对应健值对的个数
hkeys
: hkeys(name): 获取name对应的所有的键
hvals
: hvals(name): 获取name对应的所有的值
hexists
: exists(name, key): 判断name下的键值对中是否存在key这个键
hdel
: hdel(name, key) : 删除name下的某个键
_hlen = redis_connect.hlen("hmset_key")
print(_hlen) # result: 3
_hkeys = redis_connect.hkeys("hmset_key")
print(_hkeys) # result: ['name', 'age', 'gender']
_hvals = redis_connect.hvals("hmset_key")
print(_hvals) # result: ['xiaodong', '22', '男']
_hexists = redis_connect.hexists("hmset_key", "name")
print(_hexists) # result: True
_hedl = redis_connect.hdel("hmset_key", "name")
print(redis_connect.hgetall("hmset_key")) # result: {'age': '22', 'gender': '男'}
5. hincrby / hincrbyfloat
hincrby
: hincrby(name, field, count)
hincrbyfloat
: hincrbyfloat(name, field, count)
功能: 自增count
区别: 前者整数后者浮点数
redis_connect.hincrby("hincrby_key", "count", 1)
_hincrby_result = redis_connect.hget("hincrby_key", "count")
# print(_hincrby_result)redis_connect.hincrbyfloat("hincrbyfloat_key", "count", 0.1)
_hincrbyfloat_result = redis_connect.hget("hincrbyfloat_key", "count")
print(_hincrbyfloat_result)
3. List
1. lpush / rpush / llen /lrange
lpush
: 将元素添加到最左侧
rpush
: 将元素尾部添加(右侧添加)
llen
: 获取元素个数
lrange
: 分片获取元素数据:
- lrange(name, start, end):
- start: 元素开始下标
- end:元素结束下标
redis_connect.lpush("lpush_key", "张三")
redis_connect.lpush("lpush_key", "李四")
redis_connect.lpush("lpush_key", "王五")
v1 = redis_connect.lrange("lpush_key", 0, -1)
print(v1) # result: ['王五', '李四', '张三']redis_connect.rpush("rpush_key", "张三")
redis_connect.rpush("rpush_key", "李四")
redis_connect.rpush("rpush_key", "王五")
v2 = redis_connect.lrange("rpush_key", 0, -1)
print(v2) # result: ['张三', '李四', '王五']v3 = redis_connect.llen("rpush_key")
print(v3) # result: 3
2. linsert
linsert
: 元素在指定位置插入
linsert(name, where, target, value)
- name: redis要查找的key
- where: AFTRE / BEFOR
- target: 标杆值, 即在它之前或者是之后插入数据的位置
- value: value
# 先声明一个列表
_lpush_list = redis_connect.lpush("mytest", "张三", "李四", "王五")
test_list = redis_connect.lrange("mytest", 0, -1)
print(test_list) # result: ['王五', '李四', '张三']
# 在李四之前加入一个"赵六"
redis_connect.linsert("mytest", "BEFORE", "李四", "赵六")
print(redis_connect.lrange("mytest", 0, -1)) # result: ['王五', '赵六', '李四', '张三']
# 在赵六之后加入一个xiaodong
redis_connect.linsert("mytest", "AFTER", "赵六", "xiaodong")
print(redis_connect.lrange("mytest", 0, -1))
# result: ['王五', '赵六', 'xiaodong', '李四', '张三']
3. lset
lset
: 对name对应的list中的某一个索引位置重新赋值
lset(name, index, value)
- name: redis要查找的key
- index: 元素下标
- value: 替换的值
# 假设 key: mytest value: ['王五', '赵六', 'xiaodong', '李四', '张三']
# 替换元素下标值为0的王五为王麻子
redis_connect.lset("mytest", 0, "王麻子")
print(redis_connect.lrange("mytest", 0, -1))
# result: ['王麻子', '赵六', 'xiaodong', '李四', '张三']
4. lrem / lpop / rpop / blpop
-
lrem: 删除list中的指定元素
lrem(name, num, value)
- name: redis查找的key
- num: 0 代表删除所有该相同元素。1 代表从前到后删除该相同元素1个,2则是2个, -1 则是代表从后往前删除1个,-2同理,3, 4, 5, 6 …
- value: 要删除的元素
-
lpop: 删除列表最左侧一个元素
-
rpop: 删除列表最右侧一个元素
-
blpop: 删除列表最左侧元素
blpop(name, timeout=0)
- timeout: 0 代表永远阻塞,当列表元素为空时,就会阻塞,直到有数据才会放开, 其他数字代表阻塞时间
# 1. 使用lrem 删除mytest中`所有`的 `日本` 元素
redis_connect.lrem("mytest", 0, "日本")
print(redis_connect.lrange("mytest", 0, -1))
# result: ['中国', '中国', '法国', '美国', '中国', '王麻子', '赵六', '赵六', '李四', '张三']# 2. 删除张三 (张三是列表最右侧的第一个元素)
redis_connect.rpop("mytest")
# 3. 删除中国 (中国在列表最左侧的第一个元素)
redis_connect.lpop("mytest")
4. Set
Redis的Set是string类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。
Redis 中 集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。
学习集合之前先简单了解3个概念:
- 交集: 在所有集合中出现过最少两次的元素
- 并集: 将多个集合的元素合并到一起并且去重组成的新元素
- 差集: 在第一个集合中存在,在其他集合中不存在的元素。
1. sadd
命令 | 描述 |
---|---|
sadd key member1 [member] | 向集合中添加一个或者多个元素成员 |
python
代码示例
redis_connect.sadd("mykey", "redis")
redis_connect.sadd("mykey", "mysql")
redis_connect.sadd("mykey", "mongodb")
# result: {'mysql', 'redis', 'mongodb'}
2. scard / sdiff
命令 | 描述 |
---|---|
scard key | 获取集合的成员数 |
sdiff key1 [key2] | 返回给定所有集合的差集(给定一个key则是返回当前key下的所有元素,如果是多个,则返回的是交集) |
python
代码示例
redis_connect.sadd("mykey", "redis")
redis_connect.sadd("mykey", "mysql")
redis_connect.sadd("mykey", "mongodb")
redis_connect.sadd("mykey1", "redis")
redis_connect.sadd("mykey1", "mysql")
redis_connect.sadd("mykey1", "mongodb")print(redis_connect.scard("mykey"))
# result: 3
print(redis_connect.scard("mykey1"))
# result: 3
print(redis_connect.sdiff("mykey"))
# result: {'mysql', 'redis', 'mongodb'}
print(redis_connect.sdiff("mykey", "mykey1"))
# result: set() 为空。 求的是mykey 和 mykey1 的交集
体现差集
redis_connect.sadd("key1", "redis", "mongodb", "mysql", "python", "Django")
redis_connect.sadd("key2", "redis", "mongodb")# 求出key1和key2之间的差集
print(redis_connect.sdiff("key1", "key2"))
# result: {'mysql', 'python', 'Django'}
3. sdiffstore / sinterstore / sunionstore
命令 | 描述 |
---|---|
sdiffstore destination key1 [key2] | 将给定 集合之间的差集 存储到另一个指定的集合中, 如果该集合中的key存在则会覆盖 |
sinterstore destination key1 [key2] | 同上, sinterstore是将交集存储到指定的集合中,原理同上 |
sunionstore destination key1 [key2] | 同上, sunionstore是将并集存储到指定的集合中,原理同上 |
127.0.0.1:6379> keys *
1) "key2"
2) "key1"
127.0.0.1:6379> sdiffstore key3 key1 key2
(integer) 3
127.0.0.1:6379> keys *
1) "key2"
2) "key3"
3) "key1"
127.0.0.1:6379>
diffstore key3 key1 key2: 将key1与key2之间的差集存储到key3中,如果key3不存在会创建key3, 存在则会覆盖
# 将key1和key2之间的差集覆盖掉key1中
connect_redis.sdiffstore("key1", "key1", "key2")
"""
key1: result
1) "mysql"
2) "Django"
3) "python"
"""
4. sinter
命令 | 描述 |
---|---|
sinter key1 [key2] | 返回给定集合之间的交集 |
127.0.0.1:6379> sinter key1 key2
(empty array)
127.0.0.1:6379> sinter key1 key3
1) "Django"
2) "mysql"
3) "python"
127.0.0.1:6379>
由于上一步骤操作中
key1已经更改为 “django”, “mysql”, “python”
key2为: “redis”, “mongo”
key3位: “django”, “mysql”, “python”
因此,key1 和 key2 的交集是空, key1 和 key3的交集 就为"django", “mysql”, “python”
因为: “django”, “mysql”, “python” 在两个集合中出现的次数大于等于2.
python代码示例:
# 求key1和key2的交集
v1 = redis_connect.sinter("key1", "key2")
# 求key1和key3的交集
v2 = redis_connect.sinter("key1", "key3")
print(v1) # result: set()
print(v2) # result: {'Django', 'mysql', 'python'}
5. smembers / sismember
命令 | 描述 |
---|---|
smembers key | 返回集合key的成员 |
sismember key value | 判断value是否是集合key成员 |
127.0.0.1:6379> smembers key1
1) "Django"
2) "mysql"
3) "python"
127.0.0.1:6379> sismember key1 xiaodong
(integer) 0
127.0.0.1:6379> sismember key1 python
(integer) 1
127.0.0.1:6379>
python代码返回
# 返回key1的集合成员
print(redis_connect.smembers("key1")) # result: {'mysql', 'python', 'Django'}# 判断 xiaodong 是否是key1的集合成员
_bool = redis_connect.sismember("key1", "xiaodong")
print(_bool) # result: False
6. smove
命令 | 描述 |
---|---|
smove source destination member | 将元素member从source集合中移动到destination集合中 |
127.0.0.1:6379> smembers key1
1) "Django"
2) "mysql"
3) "python"127.0.0.1:6379> smembers key2
1) "redis"
2) "mongodb"127.0.0.1:6379> smove key1 key2 Django
(integer) 1127.0.0.1:6379> smembers key1
1) "mysql"
2) "python"127.0.0.1:6379> smembers key2
1) "Django"
2) "redis"
3) "mongodb"
上述redis 将key1中的Django
元素移动到key2中
用python代码实现复原
# 将key2中的Django元素移动到key1中
redis_connect.smove("key2", "key1", "Django")
7. srem
命令 | 描述 |
---|---|
srem key member1 [member2] | 移除集合key中的一个元素或者多个元素 |
127.0.0.1:6379> smembers key1
1) "Django"
2) "mysql"
3) "python"
127.0.0.1:6379> srem key1 Django
(integer) 1
127.0.0.1:6379> smembers key1
1) "mysql"
2) "python"
上述redis,将key1中的Django元素删除
python
代码实现
# 移除mysql, python元素
redis_connect.srem("key1", "mysql", "python")
8. sunion
命令 | 描述 |
---|---|
sunion key1 [key2] | 返回集合key1 和 key2之间的并集 |
127.0.0.1:6379> smembers key1
1) "mysql"
2) "django"
3) "python"
127.0.0.1:6379> smembers key2
1) "redis"
2) "mongodb"
127.0.0.1:6379> sunion key1 key2
1) "redis"
2) "mysql"
3) "python"
4) "django"
5) "mongodb"
上述redis 返回的是key1 和 key2 之间的并集
python
实现
redis_connect.sunion("key1", "key2")
# result: {'mysql', 'redis', 'django', 'mongodb', 'python'}
5. Sorted Set
1. 描述:
Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
有序集合的成员是唯一的,但分数(score)却可以重复。
2. 命令:
下表列出了 redis 有序集合的基本命令:
序号 | 命令及描述 |
---|---|
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] 迭代有序集合中的元素(包括元素成员和元素分值) |
6. redis管道
1. 描述
Redis是一种基于客户端-服务端模型以及请求/响应协议的TCP服务。这意味着通常情况下一个请求会遵循以下步骤:
- 客户端向服务端发送一个查询请求,并监听Socket返回,通常是以阻塞模式,等待服务端响应。
- 服务端处理命令,并将结果返回给客户端。
Redis 管道技术可以在服务端未响应时,客户端可以继续向服务端发送请求,并最终一次性读取所有服务端的响应。
2. 演示
python-redis默认在执行每次请求都会创建(连接池申请连接)和断开(归还连接池)一次连接操作,如果想要在一次请求中指定多个命令,则可以使用pipline实现一次请求指定多个命令,并且默认情况下一次pipline 是原子性操作。
import redispool = 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()
7. Redis发布订阅
1. 描述
redis发布者订阅者模式(pub/sub)是一种消息通信模式: 发布者(pub)发送消息,订阅者(sub)接受消息
redis客户端可以订阅任意数量的频道
2. 举例说明
- 我们平时经常也会去购物平台去购物,比如你在买衣服的时候你不知道你需要买多大号码的衣服,这个时候你就会去询问客服。而客服和客户就好比你就是发布者,客服就是订阅者,中间的频道就是这个客服平台。你向客服平台发送了一条消息,那么客服就会通过这个聊天平台看到你发送的消息,来回复。
- 群聊: 比如
相亲相爱一家人
这个群,就是频道,在这个群里的每个人都可能是发布者,也都可能是订阅者。谁发消息,谁就是发布者,发布的消息在这个群聊里都可以看到,那就是订阅者。
在这里呢,我会启动两个redis客户端来真实模拟发布者订阅者。
- 现在redis中创建一个
we are family
的一个频道
- 打开另一个redis客户端,给这个频道发送消息
- gif动图展示
3. python实现
-
定义一个公共的封装类
import redisclass RedisHelper:def __init__(self, host, password, channal, port=6379, decode_responses=True):# 使用redis连接池连接pool = redis.ConnectionPool(host=host, password=password, port=port, decode_responses=decode_responses)self.redis_connect = redis.StrictRedis(connection_pool=pool)# 创建频道self.channal = channaldef publish(self, message: str) -> bool:"""发布者发布消息:param message: 消息"""self.redis_connect.publish(self.channal, message)return Truedef subscribe(self):# 1. 返回发布订阅对象pub = self.redis_connect.pubsub()# 2. 订阅一个频道pub.subscribe(self.channal)# 3. 监听消息message_strem = pub.listen()for message in message_strem:# message: {'type': 'subscribe', 'pattern': None, 'channel': 'channel_1', 'data': 1}match message["type"]:case "subscribe":msg = f"频道: {self.channal}, 订阅成功"print(msg)case "message":msg = message['data']print(f"频道: {self.channal}发送了一条通知: {str(message['data'])}")return msg
-
创建publish.py 发布者
from redis_sub_pub import RedisHelperfor _ in range(10):channel = input("请输入你要发布的频道:")message = input("请输入你要发布的消息:")redis_helper = RedisHelper(host="localhost", password="Dxl1233210.", channal=channel)redis_helper.publish(message)
- 创建接收 sub.py
from redis_sub_pub import RedisHelperchannel = input("请选择您要进入的频道:")redis_helper = RedisHelper(host="localhost", password="Dxl1233210.", channal=channel
)while 1:import timemsg = redis_helper.subscribe()time.sleep(1)
- 效果演示