提问者:小点点

节点fs.fsync(何时使用?)


我想安全地编写一个文件,但我不想理解fsync的正确用法/位置。

https://linux.die.net/man/2/fsync

读了^那个之后,我对在哪里有效地使用它感到迷惑不解。

问题,我是不是:

fs.write('temp/file.txt','utf-8',function(error){
    if(error){fs.unlink('temp/file.txt',function(){cb(error,undefined);});}
    else{
        fs.rename('temp/file.txt','real/file.txt',function(){
            fs.fsync('real/file.txt',function(){
                cb(undefined,true);
                });
            });
        }
    });

我正在编写执行许多文件更改的东西。 我已经看过编写原子的模块,但我想了解过程。


共1个答案

匿名用户

fsync是极少使用的函数之一。

所有操作系统都通过缓存读写来掩盖存储设备慢的事实。 当您写入文件时,它不会立即写入实际的存储介质; 它会在缓存中捕获它,告诉你的程序写操作已经完成,然后把内容写到后台的存储设备中。 不过,操作系统将保持一切一致; 如果另一个应用程序从该文件中读取,它将看到新的内容,因为操作系统将从缓存中提供内容。

请注意,这并不是通用的; 我相信Windows禁用了可移动存储设备的缓存,以防止当人们拉出驱动器时数据丢失。 还有一些标志可以传递给open()以禁用缓存。

对于几乎所有的用例,您都不需要关心这种情况的发生。 对您来说,唯一的结果是您的程序可以更快地继续。 但在某些情况下,这是有问题的:

  • 如果断电,缓存的内容也会丢失,因此磁盘不会包含文件的所有新内容。
  • 如果驱动器被删除,写操作也会同样丢失。 这对于可移动存储设备来说是非常典型的,而且我非常确定90%的人都忽略了“安全删除”提示;)。
  • 我认为直接从设备(即Linux中的/dev/sdx)进行直接读取将绕过此缓存,但我不能100%确定。

例如,数据库就是需要它的例子。 当您运行更新查询时,数据库通常会更新其内存中的状态,并将更改写入事务日志。 但是,可靠性对于数据库来说是一件好事,因此它将写入事务日志,并在响应用户之前对该文件执行fsync(或者将以未缓冲的方式打开事务日志),这样就可以在一定程度上保证事务已被持久化。

在您的示例中,fsync将确保重命名实际上已经发生,并且已经刷新到磁盘。