lua + redis 的去重队列

    背景是任务派发系统,我们我们的任务落地在mysql, 然后有通过redis 的list 做队列,因为任务是幂等的,所以,超时任务和失败重试任务会重新入队。这里出现了一个情况,就是我们的任务,比如,视频转码,是极其耗时的,任务出现重复入队的情况,这不是我们所期望的,所以我们需要对任务进行去重。

该文章后续仍在不断的更新修改中, 请移步到原文地址http://dmwan.cc

    因为redis 对lua 脚本是执行的,所以我们的思路是 list + set ,来保证队列去重。lua 脚本如下:

SCRIPT_PUSH = `
local q = KEYS[1]
local q_set = KEYS[1] .. "_set"
local v = redis.call("SADD", q_set, ARGV[1])
if v == 1
then
	return redis.call("RPUSH", q, ARGV[1]) and 1
else
	return 0
end
`

	SCRIPT_POP = `
local q = KEYS[1]
local q_set = KEYS[1] .. "_set"
local v = redis.call("LPOP", q)
if v ~= ""
then
	redis.call("SREM", q_set, v)
end
return v
`

    在push 任务之前,先看任务是否在set 中,在pop之后,立刻从set中删除,因为lua 脚本的原子性,所以,能起到去重的作用。

    在python 中调用的方式如下:    

import redis
 
SCRIPT_PUSH = '''
local q = KEYS[1]
local q_set = KEYS[1] .. "_set"
local v = redis.call("SADD", q_set, ARGV[1])
if v == 1
then
	return redis.call("RPUSH", q, ARGV[1]) and 1
else
	return 0
end
'''

	SCRIPT_POP = '''
local q = KEYS[1]
local q_set = KEYS[1] .. "_set"
local v = redis.call("LPOP", q)
if v ~= ""
then
	redis.call("SREM", q_set, v)
end
return v
'''

pool = redis.ConnectionPool(host='localhost', port=6379, db=0)
r = redis.Redis(connection_pool=pool)
 

script1 = r.register_script(SCRIPT_PUSH)
 

script2 = r.register_script(SCRIPT_POP)
 
print r.get("mykey")
print script1( keys=["mykey"], args = [1,0] )
print r.get("mykey"), "ok"

print r.get("mykey")
print script2( keys=["mykey"], args = [1] )
print r.get("mykey")

    golang 等其他语言,使用方式一样,没什么好说的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值