我们应该在 ext3 上使用 data=writeback 和 barrier=0 挂载吗?

Nei*_*ilB 14 ext3 mount centos performance-tuning write-barrier

我们一直在托管公司的 VM 上运行服务器,并且刚刚注册了专用主机(AMD Opteron 3250,4 核,8GB RAM,软件 RAID 中的 2 x 1TB,ext3)。

在运行性能测试时,我们注意到一些 SQLite 转换(插入、删除和/或更新的组合)比我的 2010 MacBook Pro 花费的时间长 10 到 15 倍。

经过大量的谷歌搜索和阅读,我们开始查看挂载选项,它们是:

    data=ordered,barrier=1
Run Code Online (Sandbox Code Playgroud)

我们做了一些实验,并获得了最佳性能

    data=writeback,barrier=0
Run Code Online (Sandbox Code Playgroud)

我已经阅读了这些内容,并了解他们正在做的事情的基础知识,但我对我们这样跑步是否是个好主意没有很好的感觉/感觉?

问题

对于托管服务,上述配置是否明智?

如果我们遇到停电或严重崩溃,那么我们最终可能会丢失数据或文件损坏。如果我们每 15 分钟拍摄一次数据库快照,这可能会缓解这种情况,但拍摄快照时数据库可能不会同步。我们应该(可以?)如何确保这种快照的完整性?

我们应该考虑其他选择吗?

谢谢

Huy*_*ens 16

第一个建议
如果你不能丢失任何数据(我的意思是一旦用户输入了新数据,如果在接下来的几秒钟内不会丢失)并且因为你没有像 UPS 这样的东西,那么我不会删除写屏障,我也不会切换到写回。

移除写屏障
如果你移除写屏障,那么在崩溃或断电的情况下,文件系统将需要做一个 fsck 来修复磁盘结构(注意即使打开了屏障,大多数日志文件系统仍然会做一个 fsck,即使虽然重播日志应该已经足够了)。移除写屏障时,建议尽可能移除任何磁盘缓存(在硬件上),这有助于将风险降至最低。不过,您应该对此类更改的影响进行基准测试。你可以试试这个命令(如果你的硬件支持的话)hdparm -W0 /dev/<your HDD>
请注意,ext3 使用 2 个障碍来更改元数据,而 ext4 在使用 mount 选项时仅使用一个journal_async_commit

尽管Ted T'so 解释了为什么在 ext3 的早期发生了一些数据损坏(在内核 3.1 之前默认情况下屏障是关闭的),但日志的放置方式是除非发生日志日志换行(日志是循环日志)数据以安全的顺序写入磁盘- 日志第一,数据第二 - 即使硬盘支持写入重新排序。
基本上,当日志日志回绕时发生系统崩溃或断电将是不幸的。但是,您需要保留data=ordered. 尝试data=ordered,barrier=0另外进行基准测试。

如果您可以承受丢失几秒钟的数据,您可以激活这两个选项data=writeback,barrier=0,然后尝试使用该commit=<nrsec>参数进行试验。在此处查看此参数的手册。基本上,您给出了几秒钟的时间,这是 ext3 文件系统将同步其数据和元数据的时间段。
您还可以尝试使用一些关于脏页(需要写入磁盘的页面)的内核可调参数进行摆弄和基准测试,这里有一篇很好的文章解释了有关这些可调参数的所有内容以及如何使用它们。

关于障碍的总结
您应该对更多的可调参数组合进行基准测试:

  1. 使用data=writeback,barrier=0会同hdparm -W0 /dev/<your HDD>
  2. data=ordered,barrier=0
  3. 使用data=writeback,barrier=0结合其他安装选项commit=<nrsec>,并尝试nrsec不同的值
  4. 使用选项 3. 并尝试在内核级别进一步调整脏页。
  5. 使用 safe data=ordered,barrier=1,但尝试其他可调参数:尤其是文件系统电梯(CFQ、Deadline 或 Noop)及其各自的可调参数。

考虑迁移到 ext4 并对其进行基准测试
如上所述,ext4 需要比 ext3 更少的写入障碍。此外,ext4 支持对于大文件可能会带来更好性能的范围。所以这是一个值得探索的解决方案,尤其是因为它很容易从 ext3 迁移到 ext4 而无需重新安装:官方文档;我在一个系统上这样做了,但使用了这个Debian 指南。从内核 2.6.32 开始,Ext4 就非常稳定,因此在生产中使用是安全的。

最后的考虑
这个答案还远未完成,但它为您提供了足够的材料来开始调查。这非常依赖于需求(在用户或系统级别),很难有一个直接的答案,对此感到抱歉。


Nei*_*ilB 10

警告:以下可能有不准确之处。随着我的学习,我一直在学习很多这样的东西,所以请加一点盐。这很长,但您可以阅读我们正在使用的参数,然后跳到最后的结论。

有许多层可以让您担心 SQLite 写入性能:

考虑性能的不同层次

我们查看了以粗体突出显示的内容。具体参数是

  • 磁盘写入缓存。现代磁盘具有 RAM 缓存,用于优化相对于旋转磁盘的磁盘写入。启用此功能后,可以将数据写入乱序块,因此如果发生崩溃,您最终会得到部分写入的文件。使用 hdparm -W /dev/... 检查设置并使用 hdparm -W1 /dev/... 进行设置(将其打开,-W0 将其关闭)。
  • 屏障=(0 | 1)。网上有很多评论说“如果你用barrier = 0运行,那么就不要启用磁盘写入缓存”。您可以在http://lwn.net/Articles/283161/找到有关障碍的讨论
  • 数据=(日志| 有序| 回写)。查看http://www.linuxtopia.org/HowToGuides/ext3JournalingFilesystem.html了解这些选项的说明。
  • 提交= N。告诉 ext3 每 N 秒同步所有数据和元数据(默认为 5)。
  • SQLite pragma synchronous=ON | 离开。当 ON 时,SQLite 将确保事务在继续之前“写入磁盘”。关闭它基本上会使其他设置变得无关紧要。
  • SQLite 编译指示 cache_size。控制 SQLite 将为其内存缓存使用多少内存。我尝试了两种大小:一种是整个 DB 都适合缓存,另一种是缓存是最大 DB 大小的一半。

ext3 文档中阅读有关 ext3 选项的更多信息。

我对这些参数的多种组合进行了性能测试。ID是一个场景编号,后面会提到。

我试过的场景

我首先在我的机器上使用默认配置作为场景 1 运行。场景 2 是我认为是“最安全的”,然后在适当/提示的情况下尝试了各种组合。对于我最终使用的地图,这可能最容易理解:

将相关场景映射到参数

我编写了一个测试脚本,它运行了很多事务,包括插入、更新和删除,所有这些都在只有 INTEGER、只有 TEXT(带有 id 列)或混合的表上。我在上面的每个配置上运行了多次:

显示场景时间的图

底部的两个场景是 #6 和 #17,它们具有“pragma synchronous=off”,因此不出所料,它们是最快的。下一个由三个组成的集群是 #7、#11 和 #19。这三个在上面的“配置图”中以蓝色突出显示。基本上配置是磁盘写入缓存打开,barrier=0,并且数据设置为“journal”以外的其他内容。在 5 秒(#7)和 60 秒(#11)之间更改提交似乎没什么区别。在这些测试中,data=ordered 和 data=writeback 之间似乎没有什么区别,这让我感到惊讶。

混合版本测试中峰。在此测试中,有一组场景明显更慢。这些都是带有data=journal 的。否则其他场景之间没有太大区别。

我进行了另一个计时测试,它对不同类型的组合进行了更加异构的插入、更新和删除组合。这些花费了更长的时间,这就是为什么我没有将它包含在上面的图中:

混合类型和插入/更新/删除

在这里您可以看到写回配置(#19)比有序配置(#7 和#11)慢一些。我预计回写会稍微快一点,但也许这取决于您的写入模式,或者我还没有在 ext3 上阅读足够多:-)

各种场景在一定程度上代表了我们的应用程序完成的操作。在选择了一些场景的候选清单后,我们使用我们的一些自动化测试套件运行了计时测试。它们与上述结果一致。

结论

  • 承诺的参数似乎没有多大的区别,所以我们要离开,在5秒。
  • 我们将启用磁盘写入缓存,barrier=0data=ordered。我在网上阅读了一些认为这是一个错误设置的内容,而其他一些内容似乎认为这应该是很多情况下的默认设置。我想最重要的是你做出了一个明智的决定,知道你在做什么权衡。
  • 我们不会在 SQLite 中使用同步编译指示。
  • 正如我们预期的那样,设置 SQLite cache_size pragma 以便数据库适合内存提高了某些操作的性能。
  • 上述配置意味着我们要冒更大的风险。我们将使用SQLite 备份 API将部分写入时磁盘故障的危险降至最低:每 N 分钟拍摄一次快照,并保留最后 M 次。我在运行性能测试时测试了这个 API,它让我们有信心走这条路。
  • 如果我们仍然想要更多,我们可以考虑对内核进行处理,但是我们改进了很多东西,而没有去那里。

感谢@Huygens 提供的各种提示和指示。