我有以下用例:多个客户端推送到共享Redis列表。单独的工作进程应该排空此列表(处理和删除)。 Wait / multi-exec到位以确保,这很顺利。
出于性能原因,我不想立即调用'drain'进程,但是在x毫秒之后,从第一个客户端推送到(然后为空)列表的那一刻开始。
这类似于分布式下划线/ lodash debounce function,当第一个项目进入时,计时器开始运行(即:'领先'而不是'尾随')
我正在寻找以容错方式可靠地执行此操作的最佳方法。
目前我倾向于采用以下方法:
NX
和px
方法Redis Set。这允许:
nx
参数用于px
参数用于1
,这意味着之前没有值。否则返回0
。 1
表示当前客户端是自Redis列表耗尽后第一个运行该进程的客户端。因此,这在纸上起作用,但感觉有点复杂。是否有其他方法可以以分布式容错方式工作?
顺便说一句:Redis和分布式队列已经到位,所以我不认为将它用于此问题是一个额外的负担。
答案 0 :(得分:5)
很抱歉,但正常的回复需要大量的文字/理论。因为你的好问题,你已经写好了答案:)
首先,我们应该定义术语。 “去抖”'在下划线/ lodash方面,应该在David Corbacho’s article解释下学习:
去抖动:将其视为"将多个事件分组在一个"中。想象一下,你回家,进入电梯,门正在关闭......突然你的邻居出现在大厅里,试图跳上电梯。讲礼貌!并为他打开门:你正在解除电梯的离开。考虑到同样的情况可能会再次发生在第三个人身上,等等......可能会在几分钟内推迟出发。
节气门:将其视为阀门,它可以调节执行的流量。我们可以确定在特定时间内调用函数的最大次数。因此,在电梯类比中,你很有礼貌地允许人们进入10秒,但是一旦延迟过去,你必须去!
您在询问debounce
sinse第一个元素是否会被列入列表:
这样,与电梯类比。电梯升空后10分钟电梯应该上升。无论有多少人挤进电梯里都没关系。
在分布式容错系统的情况下,这应被视为一组要求:
即。你应该知道(以分布式方式) - 一组工人必须等待,或者你可以开始列表处理。一旦我们说出"分发"和"容错"。这些概念总是与他们的朋友一起引导:
在实践中,我担心你的系统需要更复杂一点(也许你只是没有写过,而你已经拥有它)。
你的方法:
NX
保证一次只能完成一个进程(原子性)。 PX
确保如果此过程发生某些事情,则Redis释放锁定(关于死锁定的容错部分)。 Redis中的容错reliable queue processing围绕RPOPLPUSH构建:
要求 因此,如果工作人员崩溃,我们总是可以将损坏的消息从特殊列表返回到主列表。 Redis保证RPOPLPUSH / RPOP的原子性。也就是说,只有一小群工人要等待一段时间。
然后有两个选择。首先 - 如果有很多客户和较小的工人使用锁定工人。因此,尝试锁定工作中的互斥锁,如果成功 - 开始处理。
反之亦然。每次执行LPUSH / RPUSH时都要使用SET NX PX(要让"等待N次,然后再弹出#34;解决方案,如果你有很多工人和一些推送客户端)。所以推动是:
SET myListLock 1 PX 10000 NX
LPUSH myList value
每个工作人员只检查myListLock是否存在,我们应该在设置处理互斥锁之前至少等待关键TTL并开始耗尽。