list 是 Redis 中操作比较频繁的数据结构,本文将结合 Python 对其进行相关操作并按“是否发生阻塞”分成两个部分:
- 非阻塞指令
- 阻塞指令
非阻塞操作
Redis 的 list 操作中,非阻塞指令包括:
- LPUSH 和 LPUSHX
- RPUSH 和 RPUSHX
- LPOP 和 RPOP
- LLEN
- LRANGE
- LREM
- LINDEX
- LSET
- LTRIM
- LINSERT
- RPOPLPUSH
以下是各指令的 Python 代码示例:
import redis
redis_config = {
'host': 'redis-testing',
'port': 6379,
'db': 1,
}
rs = redis.Redis(**redis_config)
if __name__ == '__main__':
# LPUSH
# 创建 colors,并向左添加两个元素
# 返回添加后列表的长度
print(rs.lpush('colors', 'green', 'yellow')) # 2
# LPUSHX
# 向 colors 添加新的元素
# 返回添加后列表的长度
print(rs.lpushx('colors', 'red')) # 3
# LPUSHX
# 向不存在的列表添加元素,不会创建相应列表并返回 0
print(rs.lpushx('notExistColors', 'green')) # 0
# RPUSH
# 向右添加一个元素
# 返回添加后列表的长度
print(rs.rpush('colors', 'gray')) # 4
# RPUSHX
# 向右添加一个元素
# 返回添加后列表的长度
print(rs.rpushx('colors', 'orange')) # 5
# RPUSHX
# 向不存在的列表添加元素,不会创建相应列表并返回 0
print(rs.rpushx('notExistColors', 'green')) # 0
# LPOP
# 取列表左边的第一个元素并从列表中移除该元素
print(rs.lpop('colors')) # b'red'
# RPOP
# 取列表右边的第一个元素并从列表中移除该元素
color = rs.rpop('colors')
print(color) # b'orange'
# LLEN
# 获取列表中元素的个数
# 如果指定列表不存在,返回 0
print(rs.llen('colors')) # 3
print(rs.llen('notExistColors')) # 0
# LRANGE
# 取列表中指定区间内连续的子集
# 取全部
print(rs.lrange('colors', 0, -1)) # [b'yellow', b'green', b'gray']
# 取闭区间 [0, 1] 的元素
print(rs.lrange('colors', 0, 1)) # [b'yellow', b'green']
# LREM
# 从左端删除指定个数的元素
# 第三个参数指定要删除的值
# 返回被删除元素的个数
print(rs.lrem('colors', 2, 'green')) # 1
# LINDEX
# 取指定位置上的元素
print(rs.lindex('colors', 0)) # b'yellow'
# 超过列表索引最大值返回 None
print(rs.lindex('colors', 3)) # None
# LSET
# 设置指定位置的值
# 返回是否设置成功
print(rs.lset('colors', 0, 'red')) # True
# LTRIM
# 截取原列表并保存至原列表
# 返回是否截取成功
print(rs.ltrim('colors', 0, 0)) # True
# LINSERT
# 在指定元素前或后插入元素
# 返回插入成功后的列表长度
print(rs.linsert('colors', 'AFTER', 'red', 'green')) # 2
# 向不存在的列表插入元素返回 0
print(rs.linsert('notExistColors', 'BEFORE', 'red', 'green')) # 0
# RPOPLPUSH
# 操作两个列表,从一个列表右端弹出元素并向左端添加到另一个列表
# 返回被操作的元素
rs.lpush('otherColors', 'yellow')
print(rs.rpoplpush('colors', 'otherColors')) # b'green'
rs.delete('colors')
rs.delete('otherColors')
代码保存在:https://github.com/a2htray/code-notebook/blob/main/Redis/app/list.py。
阻塞操作
阻塞操作是指各别指令在执行过程中会发生阻塞,并且在满足某特定条件下才返回相应值,阻塞指令包括:
- BLPOP
- BRPOP
- BRPOPLPUSH
比如,在执行 BLPOP 指令并且指定列表为空时,BLPOP 指令会阻塞当前的进程,只有当列表非空才会有返回,如以下代码:
import redis
from threading import Thread
redis_config = {
'host': 'redis-testing',
'port': 6379,
'db': 1,
}
rs = redis.Redis(**redis_config)
def lpush(key, *months):
for month in months:
rs.lpush(key, month)
def blpop(key, timeout):
while True:
ret = rs.blpop(key, timeout)
if ret is None:
break
key, month = ret
print(month)
if __name__ == '__main__':
producer = Thread(target=lpush, args=('months', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12))
consumer = Thread(target=blpop, args=('months', 2))
producer.start()
consumer.start()
producer.join()
consumer.join()
输出:
# 输出是无序的,结果非一致
b'1'
b'2'
b'3'
b'4'
b'5'
b'8'
b'7'
b'9'
b'10'
b'12'
b'11'
b'6'
代码保存在:https://github.com/a2htray/code-notebook/blob/main/Redis/app/list_block_ops.py。
上述代码以 BLPOP 为例,实现的功能为:
- 启动两个线程,分别为生产者(执行 lpush)和消费者(执行 blpop)
- lpush 会持续向
months
列表添加 12 个元素 - blpop 会持续向
months
列表取 1 个元素
小结
Python redis 包中定义的方法与 Redis 指令名称一致,熟悉 Redis 指令就等于会使用 redis 包。
评论