优化之前,mirrors 磁盘阵列(sdh)的 io util 常常在 90% 以上,有些时候甚至“稳定”在 100%。从sda 往 sdh 复制一些小文件,竟然不到 5MB/s。尝试调整了 iscsi 的 MTU、txqueuelen 等网络参数,没有效果,瓶颈可能不在网络上。以一块 7500rpm SATA 磁盘随机读 75~100 iops 计算,RAID6 的 iops 大约是 450~600 iops,与我们的测试结果基本相符,因此磁盘阵列可能本来就这么慢。

SSD(/dev/sdb)被格式化为 ext4 文件系统(UUID=8e19059d-358e-41ca-8896-b9b26a2d4f59),用 tune2fs 去掉了 journal。挂载参数为 nodev,nosuid,noatime,discard,挂载点为 /mnt/ssd。

用 fio 测试结果如下(使用 1G 文件):

  • 连续读 139327KB/s,34831 iops
  • 连续写 1001.1MB/s,256500 iops
  • 同时连续读写,与单独测试相比没有明显变化
  • 随机读 15708KB/s,3926 iops
  • 随机写 762047KB/s,190511 iops
  • 同时随机读写,与单独测试相比没有明显变化

写的性能这么好,估计是由于 buffer。连续读性能不高,是因为 SSD 在 RAID 卡后面,不过对我们来说足够了。我们最关心的随机读性能 3926 iops 达到了预期,目前磁盘阵列的随机读性能不到 500 iops。

SSD cache 的缓存策略基于 HTTP access log。每天凌晨,选出前一周的 HTTP 200 请求,按照 URL 访问频率降序排序,填满 SSD cache 为止。

注册登录 USTC LUG GitLab,即可查看源代码:https://gitgeek.net/mirrors/ssd-cache

cron-cache.sh 每天运行一次,生成缓存:

  1. 读出最近7天的 HTTP access log
  2. 取出 200 请求,统计 URL 访问频率
  3. 筛选至少访问过2次的文件,按频率降序排序,得到 filefreq-20131010.gz 这样的文件列表。
  4. 从上述文件列表中依次取出文件,获取其大小,添加到缓存列表(tocache-20131010)中,直到达到设定的缓存总大小。
  5. 用 rsync 把缓存列表中的文件同步到缓存区。用 rsync 的好处是文件没有被修改时不需要重新复制,由于多数文件的访问频率是相对稳定的,每天复制的数据量并不大。

每个源同步后,要刷新 cache,这是 update-cache.sh 的职责。它同样使用了 rsync。

200G 的缓存共缓存了 3696 个文件(其中 iso 文件占 422 个),根据前7天的 HTTP 200 日志,最多的在7天内被访问了 1036142 次,最少的在7天内被访问了 97 次。

SSD cache 的效果怎么样呢?200G 的 cache 同步完成后,

  • 磁盘阵列(sdh)的负载从一直 90%+,降到了时而 90%+,时而 50%~60%
  • 总流量增加了约 50Mbps(原来是 ~350 Mbps,后来是 ~400 Mbps)
  • load average 似乎没有明显变化
  • 被缓存文件的校内下载速度可达 50~70 MB/s,能够吃满 mirrors 的千兆网卡

希望 status.lug.ustc.edu.cn 和 mirrors 的 collectd-web 尽快恢复,以便对 SSD 的效果做更多更直观的观察和评估。