Java快速数据存储&恢复

时间:2009-10-15 14:01:57

标签: java

我需要将记录存储到持久存储中并按需检索它。要求如下:

  1. 极快的检索和插入
  2. 每条记录都有一个唯一的密钥。此密钥将用于检索记录
  3. 存储的数据应该是持久的,即应在JVM重启时可用
  4. 一个单独的流程会每天一次将陈旧记录移至RDBMS
  5. 你们觉得怎么样?由于延迟问题,我无法使用标准数据库。像HSQLDB / H2这样的内存数据库具有性能约束。此外,记录是简单的字符串对象,不符合SQL条件。我正在考虑某种基于平面文件的解决方案。有任何想法吗?任何开源项目?我相信,必须有人在此之前解决了这个问题。

15 个答案:

答案 0 :(得分:7)

有许多不同的工具和方法,但我认为它们都不能满足所有要求。

对于低延迟,您只能依赖内存数据访问 - 磁盘在物理上太慢(以及SSD也是如此)。如果数据不适合单个机器的内存,我们必须将数据分配给更多节点,总结足够的内存。

对于持久性,我们必须将数据写入磁盘。假设最佳组织 这可以作为后台活动完成,而不会影响延迟。 但是对于可靠性(故障转移,HA或其他),磁盘操作不能完全独立于访问方法:我们必须在修改数据时等待磁盘以使shure我们的操作不会消失。 并发也会增加一些复杂性和延迟。

数据模型不限制此处:大多数方法都支持基于唯一键的访问。

我们必须决定,

  • 如果数据适合一台机器的内存,或者我们必须找到分布式解决方案,
  • 如果并发是一个问题,或者没有并行操作,
  • 如果可靠性严格,我们不能松动修改,或者我们可以忍受意外崩溃会导致数据丢失这一事实。

解决方案可能

    使用标准java库,文件等的
  • 自我实现的数据结构可能不是最佳解决方案,因为可靠性和低延迟需要巧妙的实现和大量的测试,
  • 传统的RDBMS 具有灵活的数据模型,持久的,原子的和隔离的操作,缓存等等 - 它们实际上知道得太多,而且很难分发。这就是为什么它们太慢,如果你不能关闭不需要的功能,通常就是这种情况。
  • NoSQL 键值商店是不错的选择。这些术语非常模糊,涵盖了大量工具。例子是
    • BerkeleyDB或Kyoto Cabinet作为单机持久键值存储(使用B树):如果数据集足够小以适合一台机器的内存,则可以使用它。
    • Project Voldemort作为分布式键值存储:在内部使用BerkeleyDB java版,简单且分布式,
    • ScalienDB作为分布式键值存储:可靠,但写入速度也不慢。
    • MemcacheDB,Redis其他具有持久性的缓存数据库,
    • 流行的NoSQL系统,如Cassandra,CouchDB,HBase等:主要用于大数据。

可以找到NoSQL工具列表,例如。 here

Voldemort的performance tests报告亚毫秒响应时间,这些可以很容易地实现,但我们也必须小心硬件(如上面提到的网络属性)。

答案 1 :(得分:5)

答案 2 :(得分:4)

如果所有数据都适合内存,MySQL可以在内存而不是磁盘(MySQL Cluster,Hybrid Storage)中运行。然后它可以为您处理将自己存储到磁盘。

答案 3 :(得分:4)

CouchDB这样的东西呢?

答案 4 :(得分:3)

我会使用 BlockingQueue 简单,内置于Java 我使用芝加哥商品交易所的实时数据做类似的事情 数据被发送到一个地方供实时使用......并发送到另一个地方(通过TCP), 使用BlockingQueue(生产者/消费者)将数据持久保存到数据库(Oracle,H2) 消费者使用延迟提交来避免数据库中 fdisk同步问题
(默认情况下H2类型数据库是异步提交并避免该问题) 我记录持续存在于消费者中以跟踪队列大小以确保
它能够跟上制作人的步伐。对我来说效果很好。

答案 5 :(得分:2)

带分片的MySQL可能是个好主意。但是,它取决于数据量,每秒事务数和所需的延迟。

在内存数据库中也是一个好主意。实际上MySQL也提供了基于内存的表。

答案 6 :(得分:2)

Tuple space / JavaSpace会有效吗?另请查看其他企业数据结构,例如Oracle CoherenceGemstone

答案 7 :(得分:1)

您是否真的证明使用像MySQL或SQL Server这样的进程外SQL数据库太慢,或者这是假设?

您可以将SQL数据库方法与内存缓存结合使用,以确保检索根本不会访问数据库。尽管记录是纯文本的,但我仍然建议在平面文件解决方案中使用SQL(例如,在表模式中使用文本列),因为RDBMS将执行文件系统无法进行的优化(例如,缓存最近访问的页面等)

但是,如果没有关于您的访问模式,预期吞吐​​量等的更多信息,我无法提供更多建议。

答案 8 :(得分:1)

如果你输掉一两个记录多少钱?他们来自哪里?您与来源有交易关系吗?

如果您有严格的可靠性要求,那么我认为您可能需要准备支付一些DB开销。

也许您可以将持久性问题与内存中的问题分开。使用pup-sub方法。一个用户在内存中寻找,另一个用户为后续启动保留数据?

如果您可以购买而不是构建,那么WebSphere eXtreme Scale(没有Java EE依赖性)等分布式cahcing产品可能会相关。

答案 9 :(得分:1)

如果在发生崩溃的情况下丢失了几个条目会有多糟糕?

如果不是那么糟糕,以下方法可能适合您:

为每个条目创建平面文件,文件名等于id。对于不那么多连续条目的可能的一个文件。

确保您的控制器具有良好的缓存和/或使用Java中实现的现有缓存之一。

与文件系统专家交谈如何快速实现这一目标

这很简单,也可能很快。 当然,你会失去交易,包括ACID原则。

答案 10 :(得分:1)

如果您正在寻找一个简单的键值存储,并且不需要复杂的SQL查询,Berkeley DB可能值得一看。

另一个替代方案是Tokyo Cabinet,一个现代DBM实现。

答案 11 :(得分:1)

亚毫秒的r / w意味着你不能依赖磁盘,你必须小心网络延迟。忘记基于标准SQL的解决方案,主存还是不存在。在ms中,您不能在GBit网络上获得超过100 KB的空间。问一位电信工程师,他们习惯于解决这些问题。

答案 12 :(得分:1)

MapDB提供持久保存到磁盘的高性能HashMaps / TreeMaps。它是一个可以嵌入Java程序的库。

答案 13 :(得分:0)

Chronicle Map是一个ConcurrentMap实现,它将密钥和值存储在内存映射文件中。所以你有持久的JVM重启。

ChronicleMap.get()始终快于1 us,有时快达100 ns /操作。它是班上的the fastest解决方案。

答案 14 :(得分:-1)

您需要的所有记录和密钥是否同时适合内存?如果是这样,你可以使用HashMap< String,String>,因为它是Serializable。