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

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

对于我们存储和读取的数据,数据的一致性和可用性并不像性能和可扩展性那么重要。因此,如果在写入过程中发生系统故障,我可以处理一些数据丢失的情况。然而,数据在某些时候肯定需要持久化到辅助存储。

所以,总结一下,有以下要求:

  • 低延迟批量写入可能数千万条记录
  • 数据需要以某种方式持久化
  • 低延迟随机读取
  • 不需要持久写入
  • 最终一致性没问题

以下是我看过的一些解决方案:

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

解决方案

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

该架构的最佳方面之一是,您编写 Java 应用程序代码时就好像没有发生任何后写行为,然后插入使之发生的 Coherence 拓扑和配置。如果您稍后需要更改 Coherence 的行为或拓扑,则无需对应用程序进行任何更改。我知道可能有一些合理的方法可以做到这一点,但这种行为在 Coherence 中得到直接支持,而不是必须发明或手动执行一种方法。

说得更清楚一点——您担心增加应用程序复杂性是一件好事。使用 Coherence,您只需将更新写入缓存(或者如果您使用 Hibernate,它可以是 L2 缓存提供程序)。根据您的 Coherence 配置和拓扑,您可以选择部署应用程序以使用后写式分布式缓存。因此,由于缓存的功能,您的应用程序不会变得更加复杂(并且坦率地说,您没有意识到)。

最后,我在 2005 年至 2007 年实施了上述解决方案,当时 Coherence 由 Tangosol 开发,他们得到了最好的支持。我不确定现在在 Oracle 的领导下情况如何——希望仍然很好。

其他提示

我曾经参与过一个使用异步写入的大型项目,尽管在这种情况下它只是使用后台线程手写的。您还可以通过将数据库写入进程卸载到 JMS 队列来实现类似的操作。

肯定会加快数据库写入速度的一件事是批量执行它们。JDBC 批量更新可以比单独写入快几个数量级,如果您异步执行更新,则一次只需写入 500 个更新。

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

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

http://www.oracle.com/technology/products/berkeley-db/je/index.html

(笔记:大约 5-10 年前,Oracle 收购了 berkeley db;最初的产品已经存在了 15-20 年)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top