我需要处理队列中的多个记录。但是由于一些外部问题,这些物品可能会偶尔发生多次。 我只需要处理一次项目
我计划使用的是PFADD到每个记录的redis(作为md5sum),然后查看是否返回成功。如果没有显示增量,则记录是重复的其他处理记录。
这看起来非常简单,但在使用PFADD
时我得到的误报太多了有更好的方法吗?
答案 0 :(得分:4)
作为概率数据结构,Redis的HyperLogLog表现出0.81%的标准误差。您可以通过使用多个HLL来减少(但永远不会消除)误报的可能性,每个HLL都会计算记录中不同哈希函数的值。
另请注意,如果您使用的是单个HLL,则无需对记录进行哈希处理 - 只需PFADD
即可。
或者,使用Redis Set保留所有标识符/哈希/记录,并使用SISMEMBER
进行100%准确的成员资格测试。当您存储每个已处理的元素时,此方法需要更多(RAM)资源,但除非您的队列非常庞大,否则对于适度的Redis实例来说不应该是一个问题。为了控制内存消耗,请根据日期在集合之间切换,并在Set键上设置到期(另一种方法是使用单个Sorted Set,并通过在分数中保留时间戳来手动删除旧项目。)
答案 1 :(得分:2)
通常,在分布式系统中,您必须在处理项目之间进行选择:
准确处理一次会很方便,但这通常是不可能的。
据说可以为您的特定用例提供可接受的解决方法,因为您建议存储已处理的项目可能是一种可接受的解决方案。
请注意,虽然PFADD使用的是HyperLogLog,速度快且scales but is approximate关于项目的数量,所以在这种情况下,我认为这不是你想要的。 但是,如果错误的可能性很小,那么这里最合适的数据结构将是Bloom filter(如here for Redis所述),它可以以非常高效的内存方式实现。 / p>
一个简单,高效且recommended的解决方案是使用一个简单的redis密钥(例如哈希)来存储类似布尔值的值(" 0"," 1& #34;或" true"," false")例如使用HSET或SET with the NX选项指令。如果您愿意,也可以将其置于namespace之下。它还具有能够使密钥到期的额外好处。
这样可以避免使用集合(不是SET命令,而是使用SINTER,SUNION命令),这些命令与{{{ 3}}如果要扩展到多个节点。虽然Redis cluster仍然很好(但缺少哈希的某些功能,比如生存时间)。
如果你使用哈希,我还建议你选择一个哈希函数,SISMEMBER的机会较少(碰撞意味着两个不同的对象以相同的哈希结束)。
散列的另一种方法是在将每个项目放入队列时为每个项目分配一个uuid(如果你想获得一些时间信息,则为一个squuid)。