所以,这就是我的场景。
我有数百万个事件进入,我不想将这些数据直接扔到我的数据库中。我想要一个“批处理”操作,其中 java 代码保存传入的事件,直到达到阈值(比如每 10 秒),然后它们对主数据库进行批量插入。
我还需要容错,因为如果机器崩溃,我不想丢失数据。我正在考虑使用 hsqldb 将这些事件(大约 10k)保持 10 秒。
有什么建议么?
所以,这就是我的场景。
我有数百万个事件进入,我不想将这些数据直接扔到我的数据库中。我想要一个“批处理”操作,其中 java 代码保存传入的事件,直到达到阈值(比如每 10 秒),然后它们对主数据库进行批量插入。
我还需要容错,因为如果机器崩溃,我不想丢失数据。我正在考虑使用 hsqldb 将这些事件(大约 10k)保持 10 秒。
有什么建议么?
如果您想要每秒数百万个整数和持久性,您可以尝试。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 时,您提交批处理的事务,稍等片刻并重复。
Martin Fowler 发表了一篇关于他的 LMAX 架构的文章,该架构允许在主内存中进行数百万次事务,并在发生故障时可以恢复。
我推断您的问题是数据库负载,而不是进程负载。这向我提出了一个问题,为什么您希望批处理操作更便宜,从您目前的问题来看,听起来您宁愿每小时支付 600 美元而不是每分钟 10 美元,但负载也会一样糟糕。
如果您可以廉价地处理批处理操作,那么您只需要缓存到一个节省成本的媒介中,然后从那里加载。想到的两件事是用 JSON 写入平面文件,以及使用 Memcached(也可能是 JSON),其中加载发生在单独的进程(或线程池)中。您需要确保两者之间的原子性。可能有更多开箱即用的解决方案,我会留下更多知识渊博的答案来提出。
根据您期望崩溃的严重程度,您还可以设置关闭挂钩以在机器崩溃之前转储,尽管这充其量是值得怀疑的做法。
批处理操作实际上是在数据库级别处理的。数据库将单个(或几个)写入中的多个事务合并到事务日志中,写入从事务日志移动到表,但它们被分组以最小化磁盘写入。至少与甲骨文。这就是为什么它如此高效且如此昂贵的原因。但它可以是这样,PostgreSQL将满足您的期望。先测试。
在数据库读取方面,也有来自数据库站点的密集缓存。但是解析 SQL 的成本很高,所以使用客户端缓存是一个很好的选择。考虑EhCache。它支持 2 级缓存:预定义数量的项目保存在内存中,其他集合溢出到磁盘(如果需要,您可以只使用内存缓存)。从内存缓存中读取的时间大约是HashMap的访问时间。当然,您拥有的 RAM 越多,内存缓存的效率就越高。
当谈到容错时,数据库保证,缓存不会。这仅是写入问题,而不是读取问题。例如,不要尝试使用 hsqldb 自己实现某些东西。磁盘写入总是很昂贵。你不会写出比 Oracle 更好的东西,因为你没有这么多的人和时间 :) 他们的事务日志机制非常有效。并且当系统崩溃时,只要执行了提交,操作就会从该日志中恢复。