2012-04-18 33 views
0

我的要求是编写一个永不结束的传入变量大小的二进制消息流到文件系统。平均大小为2KB的消息以1000个消息/秒达到。所以在一个小时内,消息的总数将是3600 * 1000 * 2 = 6.8GB。 消息的主要目的是以下 1.存档他们审计的目的 2.提供一个搜索界面在linux中可靠的写入

我的问题是

  1. 是否有解决这个问题
  2. 的开源软件如果进程以块大小的倍数写入并且进程在写入块的中间时崩溃,会出现什么样的错误?
  3. 可能发生哪种错误,其中应用程序写入了块大小,但文件系统未刷新将数据发送到磁盘。
  4. 可以在任何情况下损坏inode
  5. 在linux中是否有文件大小限制?
  6. 是否有理想的文件大小?大文件(GB)与中文文件(MB)的优缺点
  7. 其他需要注意的事项?
  8. 我的选择是使用C++,但如果需要的话,我可以这里是切换到C.

回答

2

一旦writewritev返回(即OS已经接受它),操作系统负责将数据写入到磁盘。这不再是你的问题,而且不管你的程序崩溃,它都会发生。请注意,对于一次接受或实际写入的数据的确切数量,您是否有无控制,也不知道它是否发生在多个文件系统块中,或者它是否是任何特定大小。您发送一个请求write,它告诉你它实际接受了多少,它会自行决定将它写入磁盘。
可能这会发生在块大小的倍数上,因为这对于操作系统来说是有意义的,但这是不能以任何方式保证(在许多系统上,包括Linux,读取和写入都是通过或紧密耦合与文件映射)。

同样的“不必关心”保证适用于文件映射(理论上的例外是,崩溃的应用程序原则上仍然可以写入仍然映射的区域,但是一旦您已经取消映射区域,则不能即使在理论上也是如此)。除非你拔掉插头(或内核崩溃),否则数据将被写入并且一致。
由于内存页面是设备块的倍数,并且文件映射不知道其他任何内容,因此数据将只能以多个文件系统块写入,它只是以这种方式工作。

您可以类型(忽略任何可能的无缓冲的磁盘上写入缓存)得到一些控制与fdatasync磁盘上的内容。当该函数返回时,之前缓冲区中的内容已发送到磁盘。
但是,这仍然不会阻止您的进程同时在另一个线程中崩溃,并且不会阻止某人拔出插件。 fdatasync优于fsync,因为它不会触及inode附近的任何东西,这意味着它更快更安全(由于长度尚未更新,您可能会丢失后续崩溃中写入的最后一个数据,但是您绝对不应该破坏/损坏整个文件)。使用C库函数(fwrite)自己进行缓冲并控制您写入的数据量,但只有“已写入”数据意味着它存储在C库拥有的缓冲区中(在您的过程中) 。如果进程死亡,数据就消失了。无法控制数据如何击中磁盘,或者如果有的话。 (Nb:你可以控制的一些,只要你可以fflush,这会在返回之前立即将缓冲区的内容传递给底层的写入函数,最有可能的是writev,这样你就回到了第一段。 )

异步IO(内核 aio)将绕过内核缓冲区,并通常直接从您的进程中提取数据。您的流程死亡,您的数据消失了。 Glibc aio使用在write上阻塞的线程,与第1段中的相同。

如果您随时拔出插头或打开“关闭”开关,会发生什么情况?没人知道。
通常一些数据会丢失,操作系统可以给很多保证,但是它不能做魔术。尽管在理论上,您可能有一个系统可以缓冲内存与电池或系统,并拥有庞大的专用磁盘缓存,这也是电池供电。没人能说。无论如何,计划丢失数据。
也就是说,什么是写一次应该不会,如果你继续追加到一个文件通常会损坏(虽然,真的什么都可能发生,而“不应该”,并不意味着很多)。总之,在追加模式下使用write或者使用文件映射应该足够好,它们就像你可以得到的一样好。除突然断电之外,它们可靠且高效。
如果电源故障是一个问题,UPS将提供比任何软件解决方案所能提供的更好的保证。

至于文件大小,我看不出有任何理由人为地限制文件大小(假设为合理的新的文件系统)。 “标准”Linux文件系统的普通文件大小限制(如果有的话)在TB级范围内。
无论哪种方式,如果你感到不安与破坏一个文件,不管是什么原因可能会破坏有价值的数据30天的想法,开始每天都有新的文件一次。它不需要额外的费用。

+0

至少在Linux系统中,你可以结合使用'fflush'用'fsync'或'sync',以确保所有的数据被写入到磁盘当然违反这个保证... – jofel 2012-04-18 10:25:23

+0

@jofel:的确,我在编写这个时编辑了它。 :-)但是还有更多。首先它阻塞,除非你有多个线程,否则每秒钟到达1000条消息。对于多个线程,同步不会产生任何影响,因为另一个线程可能在同步过程中结束您的进程。另外,在磁盘上有未知的电源故障行为写入缓存(希望是一个好的,但谁知道)。现在当然也有非阻塞同步,但是...... – Damon 2012-04-18 10:35:23

0

问题,该方案未确切说明。 因此,一些答案是猜测:

  1. 是 - 它被称为'g ++'。 ;-)
  2. 许多不同。恕我直言,尽量通过为您的程序编写好的和许多测试用例来避免这种情况。
  3. 根据您的系统和您的程序,将'only'写入内存缓冲区是正常的做事方式。应该没有问题。
  4. 这取决于故障情况和使用的文件系统。 (也有文件系统没有inodes。)
  5. 每个文件系统都有它的文件大小限制。正确的答案(对你来说可能没用)是:是的。
  6. 否 - 这在很大程度上取决于您的应用程序和您的环境(如硬盘,备份系统,IO系统,...)
  7. 需要更多信息来回答此问题。
  8. 不是问题。

希望这有助于第一步。 如果您决定朝哪个方向行进,请在问题中添加信息 - 您提供的要求越多,回答 的效果就越好。

0

你手边有一个有趣的问题。我不是这方面的专家,但有足够的知识来评论这些。

如果您还没有阅读本文,您可以阅读本文,以获得有关各种文件系统linux的综合概述,他们的优点&缺点,限制等。 Comparison of FileSystems in Linux

1)我所遇到的自动旋转日志文件库,在Python/Perl中,确保在C/C++太可用相同。 2/3/4)日志文件系统在很大程度上防止文件系统崩溃。他们也支持数据记录,但没有使用太多。

Check this for more info on journaling

0

你应该使用SQLite。它解决了你需要的一切。包括速度,如果你正确使用该数据库。写作过程中突然断电(或者其它硬件故障)可能 -