在生产环境中直接使用 rm 命令删除大文件或大量文件时,可能会对系统的 I/O 资源造成过度占用,进而影响线上业务的性能和稳定性。这是因为删除操作涉及大量的磁盘读写操作和元数据更新,特别是在删除大量小文件或非常大的文件时,对系统的 I/O 负载影响尤为明显。
为了避免这些问题,可以采用一些更优雅的删除方法,以减少对系统的 I/O 影响。以下是几种有效的解决方案:
避免直接使用 rm 命令删除大文件的几种方法
1. 使用 locate + pv 命令删除文件
pv 命令是一个管道监视器,通常用于显示数据流的进度。通过将文件的删除操作通过管道传递给 pv,可以控制删除的速率,从而降低 I/O 峰值负载。
**
# 找到需要删除的文件
locate /path/to/directory/ | pv -qL 10 | xargs -I {} rm {}
解释:
这种方法可以有效地限制删除操作的速率,从而减轻对系统的瞬时 I/O 压力。
2. 使用 find + cgroup 控制 I/O
cgroup 是 Linux 的控制组功能,可以用来限制进程的资源使用,包括 CPU 和 I/O。可以使用 cgroup 来限制 find 删除文件时的 I/O 优先级。
********
# 创建一个新的 cgroup 控制组
cgcreate -g blkio:/slowrm
# 限制 I/O 使用,限制为 5MB/s
echo "5242880" > /sys/fs/cgroup/blkio/slowrm/blkio.throttle.write_bps_device
# 在限制下执行删除操作
cgexec -g blkio:slowrm find /path/to/directory/ -type f -exec rm {} \;
解释:
这种方法可以更精确地控制删除操作的 I/O 带宽,从而对系统负载产生更少的影响。
3. 使用 cgroup + rsync 将文件移动到一个单独的临时目录再删除
rsync 是一个高效的数据传输工具,通过使用 rsync 将大文件或大量文件移动到一个临时目录,然后异步删除,能有效减少对在线系统的影响
****************
# 创建一个新的 cgroup 控制组
cgcreate -g blkio:/slowrsync
# 限制 I/O 使用
echo "5242880" > /sys/fs/cgroup/blkio/slowrsync/blkio.throttle.write_bps_device
# 创建一个空目录作为目标目录
mkdir /tmp/empty
# 使用 `rsync` 的 `--delete` 选项同步到空目录,从而删除源文件
cgexec -g blkio:slowrsync rsync -a --delete /tmp/empty/ /path/to/directory/
# 删除空目录中的文件
rmdir /tmp/empty
解释:
通过这种方式,可以先将文件从生产路径中移动出去,再异步删除,从而减小直接删除操作对系统 I/O 的影响。
4. 使用 timeout + ionice 设置 I/O 优先级
ionice 是一个 I/O 调度程序,可以用来设置进程的 I/O 优先级。结合 timeout 命令,可以对 rm 操作设置 I/O 优先级,从而降低对系统 I/O 的影响。
timeout 3600 ionice -c2 -n7 -p $$ rm -rf /path/to/directory/*
解释:
这种方法通过设置较低的 I/O 优先级,可以显著降低删除操作对系统 I/O 资源的占用,从而减少对其他业务的影响。
总结
直接使用 rm 删除大文件或大量文件可能会对系统的 I/O 造成较大的影响,从而影响线上业务的正常运行。通过采用 locate + pv、find + cgroup、cgroup + rsync 以及 timeout + ionice 等方法,可以有效地减轻删除操作对系统的 I/O 压力。
这些方法通过限制删除操作的速度、设置 I/O 优先级以及异步处理等手段,能够在删除文件的过程中保持系统的稳定性和业务的连续性,是线上生产环境中常用的安全操作策略。希望这些方法能帮助你更好地管理文件删除任务,从而减少对业务系统的干扰。
注意: 在实际生产环境中使用这些方法时,请务必在测试环境中进行充分验证,确保对系统没有其他不可预见的影响。同时,根据业务场景的不同,可以对这些策略进行适当的调整和优化。
附加:
自动创建cgroup代码
******************************************
#!/bin/bash
# 检查是否具有 root 权限
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root" 1>&2
exit 1
fi
# 检查 cgroup 控制器是否已正确挂载
if [ ! -d /sys/fs/cgroup/blkio ]; then
echo "The blkio cgroup controller is not mounted" 1>&2
exit 1
fi
# 检查 cgroup 是否已存在
if [ ! -d /sys/fs/cgroup/blkio/lpdelcgroup ]; then
mkdir /sys/fs/cgroup/blkio/lpdelcgroup
fi
# 遍历所有磁盘并设置 I/O 限制
lsblk -o MAJ:MIN,NAME|egrep "^[ |0-9]+:[0-9| ]+[a-z]+" | while read -r line; do
# 获取磁盘的主次设备号
major=$(echo "$line" | awk '{print $1}')
# 检查是否已经设置了相同的主设备号
if grep -qF "$major " /sys/fs/cgroup/blkio/lpdelcgroup/blkio.throttle.write_bps_device; then
echo "Skipping $major as it is already throttled"
continue
fi
# 设置读写限制
if ! echo "$major 1048576" > /sys/fs/cgroup/blkio/lpdelcgroup/blkio.throttle.write_bps_device; then
echo "Failed to set write throttle for $major" >&2
continue
fi
if ! echo "$major 1048576" > /sys/fs/cgroup/blkio/lpdelcgroup/blkio.throttle.read_bps_device; then
echo "Failed to set read throttle for $major" >&2
continue
fi
done
echo "All disks have been added to the cgroup and I/O limits have been set."
有问题请加博主微信进行沟通!
全部评论