本地数据存储,用于高性能的小数据

时间:2013-01-08 19:45:22

标签: java

所以,这是我的情景。

我有数百万个事件进来,我不想将这些数据直接丢给我的数据库。我想要一个“批处理”操作,其中java代码保存事件,直到达到阈值(比如说每10秒)并且它们对主数据库进行批量插入。

我还需要容错,因为如果机器崩溃,我不想丢失数据。 我正在考虑将hsqldb用于保存这些事件(将在10k左右)持续10秒。

有什么建议吗?

4 个答案:

答案 0 :(得分:2)

如果你想要每秒数百万的entires和持久性,你可以试试。 Java Chronicle 您可以使用不同的进程来使用数据,因此如果程序死亡,数据仍将写入数据库。 (此外,您的主进程不会因为必须执行数据库更新而变慢)它还支持通过TCP复制到多台计算机。

基于此测试的简单示例HERE

 // create a Chronicle for reading or writing.
 String basePath = TMP + File.separator + "deleteme.ict";
 IndexedChronicle tsc = new IndexedChronicle(basePath);

 // create a handle to excerpts in the chronicle.
 Excerpt excerpt = tsc.createExcerpt();

 // add 1024 entries.
 int counter = 1;
 for (int i = 0; i < 1024; i++) {
        excerpt.startExcerpt(129);
        for (int j = 0; j < 128; j += 8)
            excerpt.writeLong(counter++);
        excerpt.write(-1);
        excerpt.finish();
 }

 // somewhere else read the file
    int counter2 = 1;
    Excerpt excerpt2 = tsc.createExcerpt();
    while (excerpt2.nextIndex()) {
        for (int j = 0; j < 128; j += 8) {
            long actual = excerpt2.readLong();
            long expected = counter2++;
            if (expected != actual)
                assertEquals(expected, actual);
        }
        assertEquals(-1, excerpt2.readByte());
        excerpt2.finish();
    }
    assertEquals(counter, counter2);

这允许您在可用时进行批处理,以最大程度地降低未将其添加到数据库的风险。当nextIndex()返回false时,您提交批处理的事务,稍等一会再重复。

答案 1 :(得分:0)

Martin Fowler发布了他的LMAX架构文章,该文章允许在主内存中进行数百万次交易,并且可以在发生故障时进行恢复。

至少你应该看看:http://martinfowler.com/articles/lmax.html

答案 2 :(得分:0)

我推断你的问题是数据库负载,而不是进程负载。这就向我提出了一个问题,为什么你期望批量操作更便宜,从你的问题到目前为止,你只想每小时支付600美元,而不是每分钟10美元,但负载也同样糟糕。

如果您可以廉价地处理批处理操作,那么您只需要缓存到便宜的中间件,然后从那里加载。我想到的两件事是用JSON写入平面文件,并使用Memcached(也可能是JSON),其中加载发生在一个单独的进程(或线程池)中。您需要确保两者之间的原子性。可能会有更多开箱即用的解决方案,我将留下更多知识渊博的答案。

根据您预期崩溃的严重程度,您还可以在机器崩溃之前将关闭挂钩设置为转储,尽管这是最好的做法。

答案 3 :(得分:0)

批处理操作实际上是在数据库级别处理的。数据库将单个(或几个)写入中的多个事务合并到事务日志中,写入从事务日志移动到表,但它们被分组以最小化磁盘写入。至少使用 Oracle 。这就是为什么它如此高效,而且如此昂贵。但也可以这样, PostgreSQL 将满足您的期望。首先测试。

在数据库读取方面,还有来自数据库站点的密集缓存。但是解析SQL很昂贵,因此使用客户端缓存是非常好的选择。考虑 EhCache 。它支持2级缓存:预定义数量的项目保留在内存中,其他组溢出到磁盘(如果需要,可以只使用内存缓存)。内存缓存的读取时间与 HashMap 访问时间有关。当然,你拥有的内存越多,内存缓存的效率就越高。

在容错方面,数据库保证不缓存。这只是写入而不是读取的问题。例如,不要尝试使用hsqldb自己实现某些功能。 磁盘写入总是很昂贵。你不会写任何比Oracle好的东西,因为你没有这么多的人和时间:)他们的事务日志机制非常高效。当系统崩溃时,只要执行提交,就会从该日志恢复操作。