Java快速数据存储和检索

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

  1. 极快的检索和插入
  2. 每条记录都有一个唯一的密钥。 此密钥将用于检索记录
  3. 存储的数据应该是持久的,即应在JVM重启时可用
  4. 一个单独的进程会每天一次将陈旧记录移动到RDBMS

你们有什么感想? 由于延迟问题,我无法使用标准数据库。 像HSQLDB / H2这样的内存数据库具有性能约束。 此外,记录是简单的字符串对象,不符合SQL条件。 我正在考虑某种基于平面文件的解决方案。 有任何想法吗? 任何开源项目? 我相信,必须有人在此之前解决了这个问题。

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

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

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

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

我们必须决定,

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

解决方案可能是

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

可以找到NoSQL工具列表,例如。 在这里 。

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

看看LinkedIn的Voldemort 。

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

像CouchDB这样的东西呢?

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

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

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

Tuple space / JavaSpace会起作用吗? 另请查看其他企业数据结构,如Oracle Coherence和Gemstone 。

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

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

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

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

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

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

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

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

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

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

它很简单,也可能很快。 当然,您将失去包括ACID原则在内的交易。

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

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

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

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

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

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

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

ChronicleMap.get()始终比1 us快,有时快到100 ns / operation。 这是class上最快的解决方案。

您需要的所有记录和密钥是否会同时存储在内存中? 如果是这样,你可以使用HashMap ,因为它是Serializable。