redis collection atomic lpop all

时间:2017-09-11 08:36:50

标签: java-8 redisclient

redis list,制作人保持lpush。在另一个线程中,消费者定期从列表中取出所有内容,并对元素进行分类。因为制作人不断推动,所以必须以原子方式完成全力以赴。那么有一种有效的方法吗? spring-data-redis 可以使用。

// producer
getOpsForList.push(k, v);

// consumer
alist = range(k,0,-1); // take all out
alist.parallelStream() // during which a producer thread could push but I hope it is "blocked".
delete(k);  // list is now empty and push from producer is unblocked.

multiexec无法达到我的目标,因为它实际上只在一个交易中提交lrangelpushdelete。到目前为止,我能想到的唯一方法是保留lpop并将其添加到alist,直到列表为空。

编辑,这就是我的想法: 如果您想确保仅使用watch

运行一次操作
watch key
val = get key
val = val + 1
multi
set key val
exec

当你想要不被打扰时," (不是多线程中断),并且不关心它运行了多少次,事务(multiexec)就足够了。

multi
val = lrange key 0 -1
delete key
exec

val在完成后仍然是一个列表,就像在official-doc

中所说的那样
  

事务中的所有命令都被序列化并执行   顺序。它永远不会发生另一个人发出的请求   客户端在Redis执行过程中提供服务   事务。

除了redis之外,我还将数据操作list.stream.parallelism取出,现在该函数只关注数据获取器,这与上一个代码段完全相同。 ;)

1 个答案:

答案 0 :(得分:0)

  

一个很好的例子来说明如何使用WATCH创建新的原子操作,否则Redis不支持它是实现ZPOP,这是一个弹出元素的命令,其中得分较低以原子方式设置。

文档中有ZPOP的实现,如下所示:

WATCH zset
element = ZRANGE zset 0 0
MULTI
ZREM zset element
EXEC

您需要做的是重复上述操作如果EXEC失败(即返回空回复)。生成器操作lpush是原子操作,因此不需要使用watch命令。例如:

// consumer pesudo code
do {
  watch(k);
  transaction = multi();
  alist = transaction.range(k,0,-1); 
  transaction.delete(k);  
  status = get status of transaction.exec();
} while(status == null);

alist.parallelStream()