Redis实现队列
Redis通过自带的数据结构list实现队列。
使用rpush和lpush进行入队操作,rpop和lpop进行出队列操作,不过要注意的是,redis实现的队列并没有ack确认机制,所以在数据的安全与稳定性上有个劣势。
127.0.0.1:6379> rpush queue a b c
(integer) 3
127.0.0.1:6379> rpush queue d
(integer) 4
127.0.0.1:6379> llen queue
(integer) 4
127.0.0.1:6379> lpop queue
"a"
127.0.0.1:6379> lpop queue
"b"
127.0.0.1:6379> llen queue
(integer) 2
队列功能可以实现了,但是如果队列控了的话,我们的客户端消费者还是在不停的取数据,会给redis造成很大的消耗,所以可以使用redis的阻塞读的方式,对list进行取值。
127.0.0.1:6379> blpop queue 5
1) "queue"
2) "c"
127.0.0.1:6379> blpop queue 1
1) "queue"
2) "d"
127.0.0.1:6379> blpop queue 11 # 阻塞时间到,继续读取
(nil)
(11.08s)
延时队列
延时队列就是该队列的每一个消息,都要过了该消息设置的等待时间之后,才可以被消费,redis中,延时队列的实现是通过zset来实现。
示例代码如下:
def delay(msg):
msg.id = str(uuid.uuid4())
value = json.dump(msg)
retry_ts = time.time()+5
redis.zadd("delay_queue",retry_ts,value)
def loop():
while True:
values = redis.zrangebyscore("delay_queue",0,time.time(),0,1)
if not values:
time.sleep(1)
continue
value = values[0]
success = redis.zrem("delay_queue",value)
if success:
msg = json.loads(value)
do_something()
通过zset的score排序属性,利用zrangebyscore获取小于等于当前时间的第一条消息,获取到了就从zset中删掉,确认无误后,小时完成业务逻辑。all done!