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.
multi
和exec
无法达到我的目标,因为它实际上只在一个交易中提交lrange
,lpush
和delete
。到目前为止,我能想到的唯一方法是保留lpop
并将其添加到alist
,直到列表为空。
编辑,这就是我的想法:
如果您想确保仅使用watch
watch key
val = get key
val = val + 1
multi
set key val
exec
当你想要不被打扰时," (不是多线程中断),并且不关心它运行了多少次,事务(multi
和exec
)就足够了。
multi
val = lrange key 0 -1
delete key
exec
val
在完成后仍然是一个列表,就像在official-doc
事务中的所有命令都被序列化并执行 顺序。它永远不会发生另一个人发出的请求 客户端在Redis执行过程中提供服务 事务。
除了redis之外,我还将数据操作list.stream.parallelism
取出,现在该函数只关注数据获取器,这与上一个代码段完全相同。 ;)
答案 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()