我们有一个应用程序,它进行了大量日志记录。我们记录的介质是 SLC SSD 驱动器,但我们开始在现场看到一些故障。我们可以关闭日志记录(我们确实这样做了),设置日志级别(我们有),但有时工程师会打开日志记录来诊断故障,然后忘记关闭它,这会导致一段时间后 SSD 出现故障。
查看日志代码,我们将日志条目保存到队列中,每 5 秒遍历集合并使用 File.AppendAllText 将行写入文件。
根据 MSDN,这会写入文件然后关闭它。
有什么更好的方案可以实现相同的功能但又能防止(或减少)SSD 的损坏?
在软件启动时打开 FileStream,在使用过程中写入流并在软件退出前关闭,这样会更好吗?这会如何缓解磁盘级别的情况?涉及哪些过程,以及这比打开文件并立即关闭文件有什么好处。使用 FileStream 感觉更好,但在进行更改之前我需要更具体的理由。
也许还有更好的方法我们还没有考虑到。
答案1
好的,我非常确定我知道你的答案。
据我所知,File.AppendAllText
它被用来写每行AppendAllText
到日志文件。这意味着每次调用时都会打开、写入和关闭日志文件。
如果不了解具体AppendAllText
实现方式,我们不妨假设最多只有额外的数据和相应的元数据(文件系统内容)被写入磁盘。
经过一段时间的反复上述操作,确实会损坏 SSD(MLC 的更换速度比 SLC 快)。这是因为 SSD 只能以大块的形式写入其内部存储。
例子
以 128GB SSD 为例,其内部块大小为 512KB。总共有 262,144 个块。
简单来说,甚至不计算元数据(文件系统)的写入,如果你打开-写入-关闭 262,144 个小文件,你将导致每一个SSD 上的块已被写入。再执行 1000-4000 次(取决于 SSD),您基本上已经将其杀死。
现在我确信 SSD 有巧妙的方法可以最大限度地减少上述类型的磨损,因此请谨慎看待这个例子。但这里的原则是正确的,而且很重要:SSD 不喜欢数百万个小写入。
向日志文件添加一行构成一次小数据写入(或者可能是一次大写入,取决于 MS 如何实现)和一次或多次小写入来更新元数据。
可能的解决方案
降低日志写入频率,比如每60秒一次,和/或...
将日志文件作为打开
Stream
,在循环中附加任何内容,然后刷新/关闭流。这种方法意味着文件只打开一次,写入,然后关闭。.NET 和 OS 将优化写入。使用非 SSD 硬盘进行日志记录。如果无法更改日志记录代码,但可以指定日志记录路径,那么这可能是最佳选择。即使是 USB 硬盘也可以!只要它不是 SSD。