Java 每秒3K传入请求的重复检测,推荐的数据结构/算法?

Java 每秒3K传入请求的重复检测,推荐的数据结构/算法?,java,algorithm,servlets,data-structures,concurrency,Java,Algorithm,Servlets,Data Structures,Concurrency,设计一个系统,其中服务端点(可能是一个简单的servlet)必须每秒处理3K请求(数据将通过http发布) 然后,这些请求将被存储到mysql中 我需要指导的关键问题是,他们将有高比例的重复数据发布到此端点。 我只需要将唯一的数据存储到mysql,那么您建议我使用什么来处理复制 发布的数据如下所示: <root> <prop1></prop1> <prop2></prop2> <prop3></prop3> &l

设计一个系统,其中服务端点(可能是一个简单的servlet)必须每秒处理3K请求(数据将通过http发布)

然后,这些请求将被存储到mysql中

我需要指导的关键问题是,他们将有高比例的重复数据发布到此端点。

我只需要将唯一的数据存储到mysql,那么您建议我使用什么来处理复制

发布的数据如下所示:

<root>
<prop1></prop1>
<prop2></prop2>
<prop3></prop3>
<body>
maybe 10-30K of test in here
</body>
</root>

这里可能有10-30K的测试
我将编写一个方法,对prop1、prop2、pro3进行散列,以创建一个唯一的散列代码(body可以不同,但仍然被认为是唯一的)

我正在考虑创建某种并发字典,以便在请求之间共享

他们在24小时内重复发布数据的可能性更大。因此,我可以在每x小时后清除此字典中的数据

对存储重复数据的数据结构有何建议?考虑到每秒3K的请求,也就是说,它会很快变大,那么清除和存储多少记录呢

注意:他们将发布10000个不同的来源,重复的机会只会发生在给定的来源上。这意味着我可以有不止一本字典,也许可以有一组来源来传播信息。这意味着,如果source1发布数据,然后source2发布数据,则重复的变化非常小。但是,如果source1一天发布100次,重复的可能性非常高

注意:请暂时忽略将发布的数据保存到mysql的任务,因为这本身就是另一个问题,重复检测是我需要帮助的第一个障碍。有趣的问题

我可能会在这里查看HashMaps结构的某种HashMap,其中第一级HashMaps将使用源作为键,第二级将包含实际数据(用于检测重复项的最小值),并使用hashcode函数进行散列。对于实际实现,Java的ConcurrentHashMap可能是一个选择

通过这种方式,如果需要将负载分配到多台机器上,您还可以设置结构来根据源对传入负载进行分区


关于清除,我认为您必须使用类似于生产的数据来衡量确切的行为。您需要了解成功消除重复数据后数据的增长速度,以及数据在哈希映射中的分布情况。有了良好的分布和不太快的增长,我可以想象它足够好,偶尔做一次清理。否则,LRU策略可能会很好。

听起来您需要一个哈希结构,可以在固定时间内添加和检查密钥的存在。在这种情况下,请尝试实现一个。请注意,这是一种概率结构,即它可能会告诉您密钥存在,但它不存在,但如果您仔细调整参数,则会使失败概率极低


编辑:正常,因此不接受bloom过滤器。要保持不断的查找(虽然不是不断的插入),请尝试查看。

您基本上是在寻找某种非常大的Hashmap和类似的内容

if(map.put(key,val)!=null)//发送数据

有很多不同的Hashmap实现,但是您可以看看。非阻塞PUT和针对大型可扩展问题设计的PUT可以很好地工作。映射还有迭代器,在使用它们遍历映射时不会抛出ConcurrentModificationException,这基本上是删除旧数据的一个要求。另外,
putIfAbsent
是您实际需要的全部-但不知道这是否比简单的put更有效,您必须询问Cliff或检查源代码


然后,诀窍是尽量避免通过使映射足够大来调整其大小-否则在调整大小时吞吐量将受到影响(这可能是一个问题)。并考虑如何实现旧数据的删除-使用一些空闲线程遍历迭代器并删除旧数据。

使用
java.util.ConcurrentHashMap
构建哈希映射,但确保在创建时为映射分配了正确的初始容量和并发级别

他们拥有所有相关信息:

initialCapacity—初始容量。实现执行以下操作: 内部大小调整以适应如此多的元素

concurrencyLevel—估计的并发更新线程数。这个 实现执行内部大小调整以尝试适应此情况 许多线程

只要您以正确的方式初始化ConcurrentHashMap,就应该能够使用putIfAbsent处理3K请求-确保这是负载测试的一部分

不过,在某些情况下,试图在一台服务器中处理所有请求可能会被证明是太多了,而且您必须在多台服务器之间实现负载平衡。在这一点上,您可以考虑使用散列索引来存储,而不是使用CHP。 不过,您仍然需要解决的有趣问题是:

  • 启动时将所有哈希加载到内存中
  • 确定何时从内存映射中删除哈希
1)像这样设置数据库

ALTER TABLE Root ADD UNIQUE INDEX(Prop1, Prop2, Prop3);

INSERT INTO Root (Prop1, Prop2, Prop3, Body) VALUES (@prop1, @prop2, @prop3, @body) 
ON DUPLICATE KEY UPDATE Body=@body
shell> mysqlimport [options] db_name textfile1 [textfile2 ...]
2)您不需要任何算法或花哨的哈希ADT

ALTER TABLE Root ADD UNIQUE INDEX(Prop1, Prop2, Prop3);

INSERT INTO Root (Prop1, Prop2, Prop3, Body) VALUES (@prop1, @prop2, @prop3, @body) 
ON DUPLICATE KEY UPDATE Body=@body
shell> mysqlimport [options] db_name textfile1 [textfile2 ...]
使用--replace或--ignore标志,以及,-compress

3)Java所能做的就是……

a) 生成CSV文件,使用StringBuffer类,然后每隔X秒左右使用一个新的StringBuffer进行交换,并将旧的.toString传递给线程,以将其刷新到文件/temp/SOURCE/TIME_STAMP.cs