可以利用redis的list结构来实现消息队列功能,使用lpush、rpush来实现入队,lpop、rpop来实现出队列。
我们统一从左边push、从右边pop,即用lpush和rpop组合。
当list中没有元素时,rpop会返回nil,这样我们需要不断用轮询队列,直到队列中有元素,然后pop出来。
为了避免不断轮询带来的性能损耗,我们这里使用brpop命令,brpop使用了系统提供的阻塞原语,在队列中没有元素时,就会一直阻塞或者超出设置时间返回,当队列中有元素时,会执行rpop命令并返回。
- Push
list的lpush支持单个或者多个元素的push,为了编写更通用的方法,我们实现批量push的功能
import "github.com/garyburd/redigo/redis"
func BatchPushQueue(queueName string, keys []string) (err error) {
if len(keys) == 0 {
return
}
con := pool.Get()
defer con.Close()
_, err = con.Do("lpush", redis.Args{}.Add(queueName).AddFlat(keys)...)
return
}
- Pop
brpop会一致阻塞住直到队列中有元素,但是它支持设置timeout,当阻塞时间超过timeout时,pop会返回nil。当timeout设置为0时,表示阻塞时间无限制。
brpop支持监听多个list,因此它有两个返回值,第一个返回值是list的名称,即key的名称,第二个返回值是pop出来的元素。我们只是监听一个list,因此我们会取返回值中的第二个元素。
//timeout is seconds which command 'brpop' will block when queue is