Java 低延迟读写的持久化策略

Java 低延迟读写的持久化策略,java,database,caching,scalability,low-latency,Java,Database,Caching,Scalability,Low Latency,我正在构建一个应用程序,它包含一个功能,可以以或多或少的交互方式批量标记数百万条记录。用户交互非常类似于Gmail,用户可以标记单个电子邮件,或批量标记大量电子邮件。我还需要对这些标记成员身份的快速读取访问,并且读取模式或多或少是随机的 现在我们正在使用Mysql,并为每个标记文档对插入一行。将数百万行写入Mysql需要一段时间(高I/O),即使是大容量插入和大量优化。我们需要这是一个交互式过程,而不是批处理过程 对于我们存储和读取的数据,数据的一致性和可用性不如性能和可伸缩性重要。因此,在发生

我正在构建一个应用程序,它包含一个功能,可以以或多或少的交互方式批量标记数百万条记录。用户交互非常类似于Gmail,用户可以标记单个电子邮件,或批量标记大量电子邮件。我还需要对这些标记成员身份的快速读取访问,并且读取模式或多或少是随机的

现在我们正在使用Mysql,并为每个标记文档对插入一行。将数百万行写入Mysql需要一段时间(高I/O),即使是大容量插入和大量优化。我们需要这是一个交互式过程,而不是批处理过程

对于我们存储和读取的数据,数据的一致性和可用性不如性能和可伸缩性重要。因此,在发生写操作时发生系统故障的情况下,我可以处理一些数据丢失。但是,数据肯定需要在某个时刻持久化到辅助存储

总而言之,以下是要求:

  • 潜在数千万条记录的低延迟批量写入
  • 数据需要以某种方式持久化
  • 低延迟随机读取
  • 不需要持久写入
  • 最终的一致性是可以的
以下是我看过的一些解决方案:

  • 写在缓存(Terracotta、Gigaspaces、Coherence)之后,在缓存中记录被写入内存并异步地排入数据库。这些让我有点害怕,因为它们似乎给我想要避免的应用程序增加了一定程度的复杂性
  • 高度可扩展的键值存储,如MongoDB、HBase、Tokyo Tyrant

根据您的数据组织方式,您可能可以使用,
如果读取延迟不够低,还可以尝试添加缓存。Memcache是一种流行的解决方案

我曾参与过一个大型项目,该项目使用Asynchronous编写althoguh,在这种情况下,它只是使用后台线程手工编写的。您还可以通过将db写入过程卸载到JMS队列来实现类似的功能


有一件事肯定会加快db写入的速度,那就是分批执行。JDBC批量更新的速度可以比单个写入快几个数量级,如果异步执行,一次只需写入500次即可。

如果您有预算使用一致性,我强烈建议您这样做。Coherence中直接支持写后、最终一致性行为,并且对于数据库中断和Coherence群集节点中断(如果您在单独的JVM上使用>=3个一致性节点,最好在单独的主机上使用)都非常有效。我为一家财富100强公司的电子商务网站实施了大量CRM,效果非常好

这种体系结构的一个最好的方面是,您编写Java应用程序代码时,就好像没有任何写后行为发生一样,然后插入使其发生的一致性拓扑和配置。如果以后需要更改一致性的行为或拓扑,则不需要更改应用程序。我知道可能有一些合理的方法可以做到这一点,但这种行为直接得到一致性的支持,而不是必须发明或手工实现

说得好一点——您对增加应用程序复杂性的担忧是很好的。有了一致性,您只需将更新写入缓存(或者如果您使用Hibernate,它可以是二级缓存提供程序)。根据一致性配置和拓扑,您可以选择部署应用程序以使用写后、分布式缓存。因此,由于缓存的特性,您的应用程序不再复杂(坦率地说是不知道的)


最后,我在2005-2007年期间实施了上述解决方案,当时Tangosol实现了一致性,他们得到了最好的支持。我不确定Oracle下的情况如何-希望仍然良好。

Berkeley DB有一个非常高性能的基于磁盘的哈希表,支持事务,如果需要,可以与Java EE环境集成。如果您能够将数据建模为键/值对,那么这将是一个非常可扩展的解决方案

(注意:oracle大约在5-10年前购买了berkeley db;原始产品已经存在15-20年了)