0%

Redis学习笔记(二)

学习完数据结构之后,就来看看利用其中列表的特性来实现任务队列。
列表可以存储一个有序的字符串列表,通常的命令分别是:

  • LPUSH(左边添加)
  • LPOP(从左边弹出)
  • RPUSH(右边添加)
  • RPOP(从右边弹出)

其实用上面四个命令就能实现一个任务队列,基本上就是生产者从一端不停的添加元素,而消费者从另一端不停的取出元素即可。

任务队列

用列表做任务队列有几个优点:

  1. 因为列表类型内部是用双向链表实现的,所以不管从哪一端添加元素都是非常快的。
  2. 当然生产者只管往列表里面添加任务,还可以由多个消费者来执行任务,这样就可以降低一个服务器的负载。
  3. 生产者和消费者之间不会产生耦合关系,只需要约定好内容格式即可,这样即使使用不同语言,一样能够实现

伪代码:

1
2
3
4
5
6
7
# 写一个无限循环函
while True:
task = RPOP queue
if task == True:
execute(task)
else:
time.sleep(1)

当然RPOP有一个问题就是需要隔一秒去取一次是否有任务,主动发起可能会浪费资源,Redis还提供了另外一个命令BRPOP(当然还有BLPOP),二者唯一的区别就是,当队列中没有任务时,会一直阻塞连接,直到有新的任务进来了,这样伪代码可以这么写:

1
2
3
4
5
while True:
# BRPOP 接受两个参数,第一个是键名,第二个是超时时间,为0则不超时
task = BRPOP queue, 0
# BRPOP 会返回一个数组,第二个就是我们的任务
execute(task[1])

优先级队列

BRPOP命令可以接受多个键值

1
BRPOP key1 [key2 ...] timeout

逻辑如下:

  • 如果所有键都没有元素则阻塞
  • 如果其中一个键有元素就会弹出
  • 如果多个键都有元素,则会按照从左到右的顺序依次取出

所以我们可以利用这一特性来实现优先级队列,将优先级高的键值放在左侧

1
2
3
4
while True:
# class1 为最高优先级,放最左侧
task = BRPOP queue:class1, queue:class2, queue:class3,0
execute(task[1])

Welcome to my other publishing channels