4

我正在评估 Java 中高效数据存储的选项。数据集是带有命名主键的时间戳数据值。例如

Name: A|B|C:D
Value: 124
TimeStamp: 01/06/2009 08:24:39,223

可能是给定时间点的股票价格,所以我想它是一个经典的时间序列数据模式。但是,我真的需要一个通用的 RDBMS 解决方案,它可以与任何合理的 JDBC 兼容数据库一起使用,因为我想使用 Hibernate。因此,对 Oracle 等数据库的时间序列扩展并不是一个真正的选择,因为我希望实现者能够使用他们自己的支持 JDBC/Hibernate 的数据库。

这里的挑战仅仅是可以在短时间内积累的海量数据。到目前为止,我的实现主要集中在定义定期汇总和清除计划,其中原始数据被聚合到 DAY、WEEK、MONTH 等表中,但缺点是粒度的早期损失以及存储在不同的周期之间的周期不匹配的轻微不便聚合体。

挑战的选择有限,因为在保持数据的原始粒度的同时可以物理压缩多少数据是有绝对限制的,而使用关系数据库的指令和支持通用 JDBC 的指令加剧了这一限制.

借用经典数据压缩算法的概念概念,并利用同一命名键的许多连续值可以预期相同的事实,我想知道是否有方法可以通过将重复值合并为无缝减少存储记录的数量一个逻辑行,同时还存储一个计数器,该计数器有效地指示“下一个n记录具有相同的值”。实现这一点似乎很简单,但要权衡的是,现在使用标准 SQL 查询数据模型非常复杂,尤其是在使用任何类型的聚合 SQL 函数时。这显着减少了数据存储的有用性,因为只有复杂的自定义代码才能将数据恢复到“解压缩”状态,从而导致与数百个无法正确呈现此数据的工具的阻抗不匹配。

我考虑了定义自定义 Hibernate 类型的可能性,这些类型基本上可以“理解”压缩数据集并将其备份并返回带有动态创建的合成行的查询结果。(除了严格控制的输入流之外,数据库将只读给所有客户端)。除了原始 JDBC(例如 JasperReports)之外,我想到的一些工具将与 Hibernate/POJOS 集成,但这并不能真正解决聚合函数问题,并且可能还有许多其他问题。

因此,我可能不得不使用更专有的 [可能是非 SQL] 数据存储(任何建议表示赞赏),然后专注于编写伪 JDBC 驱动程序的可能不太复杂的任务,以至少简化与外部工具。

我听说过一种称为“位压缩文件”的东西作为实现这种数据压缩的机制的参考,但我不知道有任何数据库提供这个以及我想要做的最后一件事(或者可以做,真的...... ) 是写我自己的数据库。

有什么建议或见解吗?

4

5 回答 5

4

Hibernate(或任何 JPA 解决方案)不适合这项工作。

JPA/Hibernate 不是一个轻量级的解决方案。在大容量应用程序中,开销不仅很大,而且令人望而却步。您确实需要研究网格和集群解决方案。我不会在这里重复对各种技术的概述。

我在金融市场信息系统方面有很多经验。你说的几件事让我印象深刻:

  • 你有很多原始数据;
  • 您想对该数据应用各种聚合(例如打开/最高/最低/关闭每日摘要);
  • 高可用性可能是一个问题(在这类系统中总是存在);和
  • 低延迟可能是一个问题(同上)。

现在对于网格/集群类型的解决方案,我将它们大致分为两类:

  1. 基于地图的解决方案,例如 Coherence 或 Terracotta;和
  2. 基于 Javaspaces 的解决方案,例如 GigaSpaces。

我经常使用 Coherence,Map 解决方案可能很好,但也可能有问题。连贯图可以在它们上面有监听器,您可以使用这种东西来执行以下操作:

  • 市场价格警报(用户可能希望在价格达到一定水平时收到通知);
  • 衍生品定价(例如,当标的证券改变最后交易价格时,交易所交易的期权定价系统将需要重新定价);
  • 交易匹配/预订系统可能希望匹配收到的交易通知以进行对账;
  • 等等

所有这些都可以通过侦听器完成,但在 Coherence 中,例如侦听器必须便宜,这会导致诸如 Map 具有侦听器之类的事情,而不是向另一个 Map 写入内容,这可以链接一段时间。此外,修改缓存条目可能会出现问题(尽管也有处理此类问题的机制;我说的是关闭市场价格警报这样的情况,这样它就不会再次触发)。

我发现 GigaSpaces 类型的网格解决方案对于此类应用程序更具吸引力。读取(或破坏性读取)操作是一种非常优雅且可扩展的解决方案,您可以获得具有亚毫秒性能的事务性网格更新。

考虑两种经典的队列架构:

  • 请求/响应:一条错误的消息会阻塞队列,虽然您可以有许多发送者和接收者(为了可扩展性),但扩大管道的数量并不总是那么简单;和
  • 发布/订阅:这将发送者和接收者解耦,但缺乏可扩展性,因为如果您有多个订阅者,他们将各自收到消息(不一定是您想要的预订系统)。

在 GigaSpaces 中,破坏性读取就像一个可扩展的发布-订阅系统,而读取操作就像传统的发布-订阅模型。在网格之上构建了一个 Map 和 JMS 实现,它可以进行 FIFO 排序。

现在我听到你问持久性怎么样?坚持是决定所有其他事情的结果。对于这种应用程序,我喜欢Persistence as a Service模型(讽刺的是,它是关于 Hibernate 的,但它适用于任何东西)。

基本上,这意味着您的日期存储命中是异步的,并且可以很好地处理汇总数据。就像您可以让服务监听交易通知并仅保留它感兴趣的通知(如果需要,在内存中聚合)。您可以通过这种方式进行开盘价/最高价/最低价/收盘价。

对于大量数据,您并不想将其全部写入数据库。反正不同步。持久存储加上数据仓库可能更适合您,但这又取决于需求、数量等。

这是一个复杂的话题,我只是真正接触过它。希望对您有所帮助。

于 2009-01-06T13:48:11.377 回答
2

我会看一个 面向列的数据库。对于这种应用程序来说会很棒

于 2009-01-06T16:13:23.610 回答
2

您可能会发现在 Money:Tech 上聆听Michael Stonebraker 的演讲很有趣。他谈到了您提到的一些需要,并说明了三大巨头(SQL Server、Oracle 和 DB2)如何永远无法满足滴答存储的需求(看起来您正在构建)。他超越了专栏商店,我同意这是正确的方向。他甚至讨论了压缩和速度,这对您来说都是问题。

这里还有一些您可能会感兴趣的链接:

于 2009-03-18T16:36:25.910 回答
1

许多支持 JDBC 的数据库管理系统(例如 Oracle)在物理存储引擎中提供压缩。例如,Oracle 有一个没有解压缩开销的“压缩”表的概念:

http://www.ardentperf.com/wp-content/uploads/2007/07/advanced-compression-datasheet.pdf

于 2009-01-07T18:31:29.667 回答
0

感谢您的回答。

Cletus,我很欣赏这个大纲,但我不能做出的权衡之一是放弃 DB 的灵活性和与 JDBC/Hibernate 的兼容性,以允许使用所有可用的工具。此外,虽然我没有明确说明这一点,但我不想强迫我的用户采用 [可能昂贵的] 商业解决方案。如果他们有数据库品牌 X,让他们使用它。如果他们不关心,我们推荐开源数据库品牌 Y。基本上,该应用程序有多个面孔,其中一个是传入数据的存储库,但另一个面孔是报告源,我真的不想进入撰写报告生成器的业务。

虽然我还没有真正对其进行负载测试,但我对LucidDB印象深刻。它是一个面向列的数据库,它提供了良好的查询性能和看似良好的数据压缩。它有一个 JDBC 驱动程序,但据我所知,它还没有 Hibernate 方言。它还支持用户定义的转换,简而言之,我认为这将使我能够无缝地实现将重复和连续值压缩到一个“行”中的想法,但在查询时将它们吹回到多个“合成”行中,所有这些都在无形中完成给查询调用者。最后,它支持外部表的这一漂亮特性,其他支持 JDBC 的数据库表可以放在 LucidDB 中。我认为这对于为其他数据库提供某种程度的支持可能是无价的。

感谢您的指点,Javaman。它把我划分到了 LucidDB 上。

于 2009-01-07T18:09:15.140 回答