《用 obsfs 把对象存储挂载到本地目录后,为什么不能当普通云硬盘用?》
用 obsfs 把对象存储挂载到本地目录后,为什么不能当普通云硬盘用?
用 obsfs 或 s3fs 这类基于 FUSE 的工具把对象存储桶挂载到 Linux 服务器的 /mnt/obs 目录后,df -h 里能看到几百 TB 的可用空间,平时用 cp 或 ls 操作文件也跟本地目录一模一样。不少人在磁盘告急时,会顺手把应用日志目录或临时解压目录直接指过去。结果没跑两天,进程就卡死了。
看着像本地目录,底层完全是两码事。云硬盘跑在 ext4 或 xfs 上,走的是块存储和 POSIX 文件系统协议,而对象存储底层是一套扁平的键值对(Key-Value)存储,所有读写操作经由 FUSE 拦截后,最终都要翻译成一条条 HTTP 请求发往远端接口。
在云硬盘上执行 mv /data/old_dir /data/new_dir,不管里面塞了十个文件还是五十万个文件,瞬间就能完成,因为文件系统只需要修改目录项(dentry)里的一个指针。对象存储里压根没有目录节点。你在控制台或挂载目录里看到的层级文件夹,只是对象键名(Key)里包含了斜杠字符 /,比如 old_dir/2026/a.jpg 只是一个带斜杠的完整字符串名字。
当你通过挂载目录执行 mv old_dir new_dir 时,由于对象存储不支持原位修改键名,obsfs 只能在后台先把该前缀下的所有对象列表拉下来,然后针对每一个文件发起一次远端复制(生成 new_dir/xxx),复制成功后再发起一次删除(删掉 old_dir/xxx)。目录里要是有几十万个小文件,一次普通的 mv 就会演变成几十万次 HTTP 请求,耗时十几分钟都算轻的,中途一旦断网还会留下一半新目录、一半旧目录的残局。批量迁移大目录别用 mv。直接用官方命令行工具 obsutil 走多并发同步稳得多。
往挂载目录里实时打应用日志也经常把机器拖垮。云硬盘上的日志文件每次追加一行,操作系统只需要往磁盘末尾对应的块(Block)里刷入几十个字节,但普通对象存储里的文件是不可变对象(Immutable Object),不支持在原有对象末尾直接追加字节,更不支持只改文件中间的某 4KB 数据。
把正在持续写入的 app.log 放在 obsfs 挂载目录里,程序每次触发文件刷盘或关闭时,FUSE 客户端都得在本地缓存目录(默认常在 /tmp 下)里先把整份文件拼好,再把整个文件重新上传覆盖远端对象。几 KB 时看不出来。一旦日志涨到几百 MB,每追加几行就要在后台重传几百 MB 的数据,不仅把服务器网卡带宽吃满,系统盘也会被本地缓存撑爆。
平时在云硬盘上敲 ls -l 或 find 遍历几万个文件的元数据,内核直接读内存里的 inode 缓存,几十毫秒就出结果了。换到挂载目录上,为了拿到每个文件的大小和修改时间,obsfs 往往需要分页调用列举接口,甚至对文件挨个发起 HEAD 请求去拉取元数据。文件一多,敲个 ls 都卡。
让老程序通过 obsfs 挂载目录直接读取静态资源、加载模型权重,或者把已经打包好的备份归档文件一次性写进去,用起来确实省事,不用改代码去接 SDK。但只要碰上持续追加写日志、频繁改目录名或者几万个小文件随机读写的场景,还是留在云硬盘或文件存储 NAS 上更踏实。
- 点赞
- 收藏
- 关注作者
评论(0)