2013-01-08 45 views
2

所以,这是我的场景。用于高性能小数据的本地数据存储

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

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

有什么建议吗?

+0

实现容错的唯一方法是冗余。无法保证单台机器的处理。一旦你有了冗余,你就可以开始考虑扩展,通过使集群中的每台机器负责仅存储部分数据,使用Zookeeper之类的框架在机器之间进行协调。 – parsifal

回答

2

至少你应该看一看。 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时,您提交该批次的事务,稍等一会再重复。

+0

感谢您的回答!我不确定这一点。 我需要刷新到我的主数据库的数据将大约为10k条记录(非常简单的模式,如K-V对)。 java-chronicle能否给我这样的能力:1.继续写作,2.一次全部阅读,3.冲洗它。我在'/ testing'中看到你有一些例子,但是仍然对使用这个lib的实用方法感到困惑。你能指点我一个“入门”链接什么的? – John

+0

作家可以在不知道读者正在做什么的情况下继续写作,并且不会放慢速度,但不管它落后多远。读者可以阅读它想要写多少的方式。这个库不需要冲洗。它假定您将每天或每周旋转一个文件。 –

0

Martin Fowler发布了他的LMAX架构的文章,它允许在主存储器中进行数百万次交易,并有可能在出现故障时进行恢复。如果你想每秒百万和持久性,你可以尝试entires的http://martinfowler.com/articles/lmax.html

0

我推断你的问题是DB负载,而不是过程负载。这就向我提出了一个问题,为什么您希望批量操作更便宜,从您的问题到目前为止,您听起来像是每小时支付600美元而不是每分钟10美元,但负载会同样糟糕。

如果您可以便宜地处理批处理操作,那么您只需要缓存到节省成本的媒介中,然后从那里加载。想到的两件事是用JSON写入平面文件,并使用Memcached(也可能是JSON),其中加载发生在单独的进程(或线程池)中。您需要确保两者之间的原子性。对此,可能有更多的现成解决方案,我会留下更多有见识的答案来提醒。

根据你期望崩溃的程度有多糟糕,你也可以在机器崩溃之前设置一个关闭钩子以便转储,尽管这是充其量的问题。

+0

是的,我的问题是数据库负载。与使用hsqldb相比,写入本地文件将会很昂贵。 Memcached对于这样一个小的(和临时的)数据集可能是一种矫枉过正。 – John

0

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

当涉及到数据库读取时,数据库的网站也会进行密集缓存。但是解析SQL很昂贵,所以使用客户端缓存是非常好的选择。考虑EhCache。它支持2级缓存:预定义数量的项目保存在内存中,其他组溢出到磁盘(如果需要,只能使用内存缓存)。从内存缓存中读取的时间大约是访问时间的HashMap。当然,你拥有的RAM越多,你的内存缓存效率就越高。

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