一日一技:如何从 Redis 的列表中一次性 pop 多条数据?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了一日一技:如何从 Redis 的列表中一次性 pop 多条数据?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2425字,纯文字阅读大概需要4分钟。
内容图文
![一日一技:如何从 Redis 的列表中一次性 pop 多条数据?](/upload/InfoBanner/zyjiaocheng/869/c3d094277b7844bb8b022824501ed761.jpg)
一日一技:如何从 Redis 的列表中一次性 pop 多条数据?
摄影:产品经理
产品经理说我炒的蛋炒饭比图中好吃
当我们想从 Redis 的列表里面持续弹出数据的时候,我们一般使用lpop或者rpop:
import redis
client = redis.Redis()
while True:
data = client.lpop('key')
if not data:
break
print(f'弹出一条数据:{data.decode()}')
但这种写法有一个问题,就是每弹出1条数据都要连接一次 Redis 服务器,当你要把1000万条数据从列表里面弹出来的时候,实际上超过一半的时间都消耗在了网络请求上面。
但是lpop与rpop都只接收一个参数,就是key。因此没有办法通过传入参数的方式让它一次弹出多条数据。
要获取多条数据,我们还有另一种方案,就是lrange:
client = client.lrange('key', 0, 5000)
这一行的意思是从列表中,获取前5001条数据(包含首尾)。但lrange只能获取数据,却不能删除数据。这就会导致在多个进程获取到重复的数据。
我们还知道Redis 的ltrim来删除数据:
client.ltrim('key', 5000, -1)
这样就能删除前5000条数据了。这里第三个参数之所以要用负数,是因为ltrim(key, start, end)的意思是说,保留列表 Key 的第start项到第end 项,其它项删除。那么如果 end为负数,表示倒数第几项,例如-1表示倒数第1项,-2表示倒数第2项。假设列表里面有10000项,那么 start 为5000,end 为-1,表示删除前5000条数据(0-4999),保留后面的。
于是有人问,能不能这样写代码呢:
import redis
client = redis.Redis()
data = client.lrange('key', 0, 4999)
client.ltrim('key', 5000, -1)
这样不就看起来像是弹出了5000条数据吗?
想法很好,但是由于获取数据与删除数据是两条命令,中间有时间差。这就导致在多个线程或者进程同时执行这两条代码的时候,出现竞争。也就是进程1刚刚获取了前5000条数据,然后进程2同样获取这5000条数据,然后进程1删除前5000条数据,然后进程2再删除5000条数据。
这样一来,两个进程获取了相同的5000条数据,但是却删了10000条数据。
为了解决这个问题,必须让获取数据与删除数据这两个操作变成一个“原子操作”。所谓的原子操作就是只一个最小的操作单位,它不会被中途打断。
要解决这个问题,我们就需要使用 Redis 的pipeline功能。它可以把多条命令放在一个网络请求中发送到服务器,并默认在一个事务中执行这些命令。一个事务是不会被打断的,从事务开始然后执行里面的多个命令到结束的整个过程,可以看做一个原子操作。
pipeline的使用方法如下:
import redis
client = redis.Redis()
def batch_lpop(key, n):
p = client.pipeline()
p.lrange(key, 0, n - 1)
p.ltrim(key, n, -1)
data = p.execute()
return data
batch_lpop('test_pipeline', 20)
当代码执行到p.execute()的时候,它才会真正去连接服务器,然后把待执行的命令在一个事务中一次性执行完成。并返回一个列表。返回的列表有两项,第0项是包含结果的列表,第1项为ltrim 的返回结果。如下图所示:
我们只需要使用第0项的结果即可。
内容总结
以上是互联网集市为您收集整理的一日一技:如何从 Redis 的列表中一次性 pop 多条数据?全部内容,希望文章能够帮你解决一日一技:如何从 Redis 的列表中一次性 pop 多条数据?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。