使用符号链接存储数据

时间:2017-03-07 00:53:55

标签: unix filesystems storage symlink

我正在处理的应用程序需要使计数器的值在多个调用中保持不变,这样每次再次启动应用程序时,都会读回计数器的值并从那里继续计数。该值应以人类可读的形式存储,以便在需要时可以轻松检查,并且应该以原子方式更新,以便失败不会弄乱先前的持久值。

使用普通的旧文本文件似乎太无聊了,所以经过一些创造性的思考后,我发现我可以通过将计数器存储为符号链接目标来实现相同的目标。

基本上,使用sh作为原型语言,而不是使用

echo $counter > file.tmp && mv file.tmp file || rm -f file.tmp

我愿意

ln -s $counter file.tmp && mv file.tmp file || rm -f file.tmp

后一种方法的优点是我只需要一个系统调用来写入文件,而不是前一种情况下至少 3。

作为额外的好处,从shell中执行ls -l会自动显示文件的内容:

$ ls -l the.counter.is
lrwxrwxrwx 1 fabio fabio 4 mar  7 01:08 the.counter.is -> 1234

关于性能的问题,在我的PC上执行比较两种方法(see it here)的测试程序,我得到的结果符合预期,符号链接方法比标准方法快7倍(注意该测试并不关心原子性):

$ uname -a && ./linkfile 10000 4095 /tmp/test
Linux Fabio-Asus 4.8.0-40-generic #43-Ubuntu SMP Thu Feb 23 16:01:19 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
Starting test... [10000, 4095]
writeToFile: 155.537ms
writeToLink: 23.4132ms

然而,on coliru我得到了不同的结果,略微支持标准方法:

uname -a && g++ -O3 -o test main.cpp && sync && ./test 10000 4095 x
Linux stacked-crooked 4.4.0-57-generic #78-Ubuntu SMP Fri Dec 9 23:50:32 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
Starting test... [10000, 4095]
writeToFile: 21.8001us
writeToLink: 33.9217us

每个方法的测试包含10000次迭代,每次迭代写入4095个字节,并平均执行时间。

4095字节的原因是导致symlink系统调用因ENAMETOOLONG而失败的原因。

所以问题是:

  1. 除了疯狂的我之外,有没有人曾经使用过这种方法存储数据?
  2. 如果是,针对什么用例?
  3. 请记住,我的电脑运动i7-6500U CPU @ 2.50GHz,您是否知道为什么在coliru上标准方法比在我的电脑上快得多,两者都与符号链接方法并且在绝对时间内?如果是因为某些缓存,为什么那些也不会影响我的PC,为什么它们不会对符号链接方法产生积极影响?

1 个答案:

答案 0 :(得分:0)

我的回答:

  1. 是的,我看过用于存储数据的符号链接。正如您已经解释过的那样,在符号链接而不是文件中存储小块数据会带来巨大的性能提升。我相信符号链接值直接存储在inode中,这使其更具存储效率。另一个巨大的优势是原子性 - 符号链接创建是一个原子过程,有助于处理并发问题。
  2. 符号链接中存储的值主要是元数据,特定于应用程序。例如,如果我必须构建一个逐步解析大量动态日志文件的解析器,我可能希望将最后一个字节位置存储在符号链接中。符号链接也可用于实现锁定。我见过flock在NFS上不可靠并且使用了符号链接的情况。
  3. 我不确定这个 - 可能存在实现差异?