zoukankan      html  css  js  c++  java
  • 记一次线上删除海量文件的思路和方法

    问题详情:

      web1 是整个架构的唯一web前端服务器,非常不好运的是,因为忘记定期清理每天产生的session文件,导致该web服务器的/home挂载点inode用光了。

      /home挂载点下不能继续生成文件,负载也因此飙到400,Nginx 、php-fpm 服务不可用,网站全部无法访问,严重影响线上业务。

    $ df -i
    Filesystem                                           Inodes     IUsed     IFree IUse% Mounted on
    /dev/sda2                                           6553600    109654   6443946    2% /
    tmpfs                                               4105528         1   4105527    1% /dev/shm
    /dev/sda1                                            128016        45    127971    1% /boot
    /dev/sda4                                         236511232 236500000     11232   100% /home

      /home/session 为session存放目录,子目录分为两层,即/home/session/{0,1,2...u}/{0,1,2...u}/ 下存放session文件。

    临时解决方法:

      1、借助其他服务器的inode。

       在另外一台服务器上共享nfs文件目录,挂载到web前端服务器上,用作session文件存放目录。

       将原/home/session改名为/home/session-bak,nfs目录挂载到/home/session。

      2、在共享nfs的服务器上,做定时任务,每15分钟扫一次session目录,删除180分钟以前的session文件。

       避免session单个子目录出现文件数超100万的情况,该情况下,无论何种删除文件的方法,都会非常缓慢。

    接下来就是如何快速删除前端web服务器上的海量文件了。

    问题解决思路探索:

      1、利用rm或rsync命令删除海量文件

    # rm -rf /home/session-bak
    
    # mkdir /home/blank
    # rsync -a --delete-before -H -v --progress --stats /home/blank /home/session-bak

        反馈:因/home/session-bak目录下有超过1亿的海量文件,两种方法效果对比并不明显。而且两种方法非常占用IO的,导致web前端服务器IO被占光,负载又飙到400多,业务大大受影响,不能这样删除海量文件。

      2、增加进程运行优先级,只有系统空闲的时候,才执行相应的删除操作

    # nice -n 19 rm -rf /home/session-bak
    
    # mkdir /home/blank
    # nice -n 19 rsync -a --delete-before -H -v --progress --stats /home/blank /home/session-bak

        反馈:线上业务IO正常,负载正常,但删除文件的速度太慢了。因/home/session-bak目录下有超过1亿的小文件,单次删除的文件数过大,单是构建删除列表就耗费相当久的时间。

      3、增加进程优先级,减少每次删除的文件数

        因/home/session-bak下有两层子目录,为了提升删除的速度,避免构建删除列表耗费过长的时间,可以每次删除第二层子目录里边的文件。

        用Python写个循环删除的脚本(上一个删除命令正常执行完了,才会执行下一个删除命令),放在后台慢慢跑。

    #!/usr/bin/env python
    # _*_ coding:utf8 _*_
    
    import os
    
    # 基本路径信息
    base_path = "/home/session-bak"
    postfix = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v']
    
    paths = []
    path_temp = ''
    
    # 组合路径
    for i in postfix:
        for j in postfix:
            path_temp = base_path + '/' + i + '/' + j
            paths.append(path_temp)
    
    # 初始状态
    stats = 0
    it = iter(paths)  # 建立迭代器
    
    while stats == 0: # 循环的条件: 上一个命令正常执行完,才能执行下一个命令
        try:
            path = it.next()  # 迭代下一个值
            stats = os.system("nice -n 19 rm -rf %s" % path)  # 当命令正常执行完,会返回0
        except StopIteration:
            print '删除成功'
            stats = 1

      

  • 相关阅读:
    洛谷P3258 [JLOI2014]松鼠的新家
    洛谷P1306 斐波那契公约数
    bzoj4247:挂饰
    [YTU]_2354 (H 实现复数类中的加运算符重载【C++运算符重载】)
    [YTU]_2440 (C++习题 复数类--重载运算符+,-,*,/)
    [YTu]_2441 (C++习题 复数类--重载运算符2+)
    [YTu]_2439(C++习题 复数类--重载运算符+)
    10.3 重载双目运算符
    10.2.1 关于vc++不支持把类的成员函数定义为类的友元函数的处理
    10.2 运算符重载函数作为类成员函数和友元函数
  • 原文地址:https://www.cnblogs.com/hjqjk/p/6698604.html
Copyright © 2011-2022 走看看