Java 如何保持列表添加元素在redis上不重复?

Java 如何保持列表添加元素在redis上不重复?,java,caching,redis,Java,Caching,Redis,例如,redis上的列表1,2,3,4,5, server1希望1到8,因此它将添加6,7,8,如果成功,列表将为1,2,3,4,5,6,7,8 server2希望1到7,因此它将添加6,7,如果成功,列表将为e1,2,3,4,5,6,7 您可以看到元素6,7在重复,因此实际上列表可能是1,2,3,4,5,6,7,8,6,7或1,2,3,4,5,6,7,6,7,7 我正在制作一个跟踪记录缓存,如何解决这个问题?仅排序集?但是缓存需要lpush排序集是一种方法(甚至是集合)。列表本质上允许重复项。

例如,redis上的列表1,2,3,4,5,

server1希望1到8,因此它将添加6,7,8,如果成功,列表将为1,2,3,4,5,6,7,8

server2希望1到7,因此它将添加6,7,如果成功,列表将为e1,2,3,4,5,6,7

您可以看到元素6,7在重复,因此实际上列表可能是1,2,3,4,5,6,7,8,6,7或1,2,3,4,5,6,7,6,7,7


我正在制作一个跟踪记录缓存,如何解决这个问题?仅排序集?但是缓存需要lpush

排序集是一种方法(甚至是集合)。列表本质上允许重复项。实现您想要做的事情的唯一方法是使用MULTI/LREM/LPUSH/EXEC,但这不是一个好主意(LREM是O(N),随着列表的增长,这可能会非常昂贵)。

如果您真的想使用list,那么您可以添加另一个数据结构来获取数字是否存在fast:Set

使您的数据集与列表保持一致。当您想在列表中输入一个数字时,首先使用SISMEMBER检查该数字是否已经在集合(或列表)中,如果在,则不要输入,如果不在,则添加到集合中并输入到列表中。SISO成员是O(1),因此不会增加太多时间开销

还有一件事需要注意:

有一个事务问题,因为您有两个或多个服务器与redis保持连接。所以在上面,一些动作需要原子化。 例如,如果发生如下顺序的情况:

服务器1检查7使用SISMEMBER=>返回不存在

服务器2检查7使用SISMEMBER=>返回不存在

服务器1将7放入列表并将7放入集合

服务器2将7放入列表并将7放入集合

然后列表将有两个7。那么如何应对呢

至少也是最好的,服务器使用SISMEMBER检查一个数字,如果不存在,则使用SADD inser进入集合,如果存在,则不做任何设置应该是原子的。如果这是原子的,上面类似的东西会是这样的:

服务器1检查7使用SISMEMBER=>返回不存在&&sadd 7到集合中

服务器2检查7使用SISMEMBER=>返回已存在

服务器1 lpush 7进入列表

服务器2什么也不做

如何做到这一点?只需使用MULTI将SISMEMBER和SADD设置为原子

MULTI
   SISMEMBER set n
   SADD set n 
EXEC
然后,您可以使用SISMEMBER的回复来做出决定:lpush还是什么都不做。 而SADD一个重复的元素将被忽略,所以这无关紧要

已编辑

如果您想一次推送多个值,您可以使用来加快SIS成员的速度。例如,在一条管道中:

MULTI
   SISMEMBER set n1
   SISMEMBER set n2
   ...
   SADD set n1,n2,....
EXEC

并在一个回复中获得每个n的结果(存在或不存在),然后将所有需要lpush的值分组到一个数组中,lpush一次。

是的,SortedSet看起来很好,您希望排序(排序)并且没有重复(集)^^@azro,但排序集非常昂贵!sismember每次只检查一个元素,如果服务器1将添加1,2,3,4,5,服务器2将添加3,4,5,6,7,这是否意味着它们将循环很多?是的,这是一个折衷。但由于每个操作都是O(1),因此不会花费太多时间。它只需花费网络传输时间很多倍。如果你想加快速度,你可以试试管道。