V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
myzincx
V2EX  ›  Linux

单机存储大量的小文件该如何选择?

  •  
  •   myzincx · 82 天前 · 3602 次点击
    这是一个创建于 82 天前的主题,其中的信息可能已经有所发展或是发生改变。

    需求:一个小时大概有 180w 个不超过 10kb 的小文件要存储在单机设备上(只提供单机),目前直接写文件会直接造成程序性能基本不可用

    想法: 1.目前有想过的是打包成一个大文件直接建立自有索引,但是这么做的话程序需要改动很多(主要是其他部门的),而且本部门人手有限,开发维护起来可能有困难。 2.也有查过一些文件存储框架,首先大部分框架是分布式的,我们只能提供单机,不知道这个会不会造成影响;其次,因为其他部门有个功能必须是对文件进行直接读取操作的(貌似 ceph 是可以当成一个挂载卷的这种,不太了解,如理解错误希望指出),不能够通过网络 api 调用操作(如 seaweedfs)。

    所以想请教下大家,有没有那种单机适合这种小文件大量读写的。 写多,读少,不删除。

    40 条回复    2020-09-14 17:16:03 +08:00
    opengps
        1
    opengps   82 天前
    单机的话,得规划下文件夹的创建,避免单个文件夹下太多文件导致的索引变慢
    另外如果 cpu 扛得住的话,可以考虑 base64 存数据库,合理设计表结构,比如分库分表配合
    myzincx
        2
    myzincx   82 天前
    @opengps 创建文件夹可以考虑,数据存数据库就不太可了,其他项目组需要扫描原始文件使用。感谢回答
    wzw
        3
    wzw   82 天前 via iPhone
    Ssdb 加 python/go 写个接口
    Mirana
        4
    Mirana   82 天前
    写多读少不删除 最好的 io pattern 是 append only 而且不需要 gc
    感觉 tfs 会好一点
    myzincx
        5
    myzincx   82 天前
    @Mirana tfs 还有在维护吗?
    myzincx
        6
    myzincx   82 天前
    @wzw 这种无法表现为数据卷的通过网路通信的不可用
    drehere
        7
    drehere   82 天前
    这个其实是跟 Linux 硬盘类型有关的,ext3 和 ext4 是不同的,主要要解决的就是 inode 的个数
    gfreezy
        8
    gfreezy   82 天前
    sqlite
    zjyl1994
        9
    zjyl1994   82 天前 via Android
    搞一个 btrfs 格式的磁盘试试?
    wangritian
        10
    wangritian   82 天前
    项目中写小文件的任务改成单文件追加,设计一个简单协议,对这个大文件分段,比如前 8 字节表示段数据大小,再扫描到\0 是该小文件的路径,其余是小文件数据,积累一定时间或数据量时新建一个大文件,然后调用一个外部程序按协议拆解前一个大文件,不知道这个方案是否可行
    hakono
        11
    hakono   82 天前
    虽然没用过,但也许可以考虑下无压缩 zip 。。。。
    记录下文件保存在哪个 zip 里就行了。。。。。

    不过无压缩 zip 适不适合 180w/h 写入就不知道了
    594duck
        12
    594duck   82 天前
    leveldb 和 rocksdb 适合干这活,之前公司他们就是这么弄的。

    但是要知道这二个 DB 是写优化的,写起来异常的猛 ,但是读不行。
    594duck
        13
    594duck   82 天前
    另外你一秒钟要写 5000 个文件,而且 IO 如此碎,一定要考虑 RAID10 了,RAID 卡的 Cache 一定要大,越大越好
    MeteorCat
        14
    MeteorCat   82 天前 via Android
    单机存储小文件方案不清楚,但是缺点我遇到过一个,那就是 inode 利用达到 100 %,直接使用 df -i 看到磁盘直接把 inode 爆了,这个是你使用单机存储大量文件必须要处理的问题
    kuro1
        15
    kuro1   82 天前
    ipfs 单机开启 badgerds,本质是 db
    kuro1
        16
    kuro1   82 天前
    关于第二点,可以使用 ipfs mount,关闭 gateway port
    Mirana
        17
    Mirana   82 天前
    @594duck 楼主不删文件,所以 rocksdb 这种 需要做 merge 的 db,写放大贼高,不太合适
    myzincx
        18
    myzincx   82 天前 via Android
    思考了一下,准备使用 fuse 在外面写一层接口,主要是实现 open write read 之类的必须函数,然后通过函数在内部调用其他数据库,实现对上层应用的透明,不知道大家认为可行否?
    myzincx
        19
    myzincx   82 天前 via Android
    其他数据库的话找个高吞吐量的就行,也可以用 Redis 做缓存,延后组成大文件落地。这样的话当其他项目要使用到其中的文件时,可以直接去数据库里查询到数据然后返回即可。
    jiangwenwenmodes
        20
    jiangwenwenmodes   82 天前 via Android
    s3 挺合适的
    xupefei
        21
    xupefei   82 天前 via iPhone
    ZFS 应该可以解决问题,
    livepps
        22
    livepps   82 天前
    dropbox 好像是文件都做成 4m 的块,大的切割成 4m,小的多个拼接成 4m,然后维护索引
    livepps
        23
    livepps   82 天前
    小文件太多,直接存硬盘,还是考虑拼接成大文件存储比较好,碎片也少。
    读取的时候分步:
    1. 其他文件读取文件的接口做个封装
    2. 每次调用,根据索引和文件长度,从 4m 快里面提取出数据拼接,创建临时文件。
    3. 然后再读取上面创建的临时文件。
    fancyhan
        24
    fancyhan   82 天前 via iPhone
    每秒大概 1500iops,你的后端撑不住么?还是没有固态硬盘
    crclz
        25
    crclz   82 天前
    数据库是最优解
    black11black
        26
    black11black   82 天前
    感觉你这个需求,因为是小文件,直接存 sql 里就行了吧。比如用 LOB 存二进制。

    因为感觉上只有两个需求,一个是存储,另一个是根据名称读取,似乎 sql 很完美
    love
        27
    love   82 天前 via Android
    @MeteorCat 有些文件系统无限 inode 的,比如 reiserfs,用 ext 存小文件是不行
    Mithril
        28
    Mithril   82 天前
    直接内存映射开个大文件,然后自己往里面写小文件并且建立索引。具体实现方法随便参考个文件系统就行。
    主要是避免让操作系统去干这个事。小文件量大了 inode 不够用,大概率你得去搞不同的文件系统,迁移性很成问题。按你这个单机的需求八成软件是要安装在客户那里的,让人家去换个 OS 和 FS 不太现实。你可以参考下 FaceBook 的 Haystack,或者其 Go 的实现 weed-fs 。
    Ceph 维护是个大坑,单机你就还是不要碰了。
    Thiece
        29
    Thiece   82 天前
    InfluxDB ?
    optional
        30
    optional   81 天前 via iPhone
    minio s3fs 挂载到本地
    zengming00
        31
    zengming00   81 天前
    存数据库是对的
    listenerri
        32
    listenerri   81 天前
    好像有大厂自己实现的专门存储小文件的文件系统
    ruanimal
        33
    ruanimal   81 天前
    leveldb + ssd 吧
    gotonull
        34
    gotonull   81 天前
    我们公司用的 rocksdb
    firstfire
        35
    firstfire   81 天前
    只要 10KB 大小的话,MongoDB 也可以存,还可以顺带的存储文件的元数据信息
    purplewall
        36
    purplewall   81 天前
    这些数据好像才 18GB,要不试试看挂载 ramfs 直接写到内存里,或者直接映射一块足够大的内存。
    ungrown
        37
    ungrown   80 天前
    你说的自定义 FUSE 思路可行,功能是简单的,但开发调试过程一定是痛苦的,这个没辙。
    所以在此之前,强烈建议你再试一些已经存在的工具、方法:
    ZFS 绝对值得一试,“终极文件系统”真不是凭空吹的牛逼;
    大量小文件打包成一个大文件的思路也值得一试,这事其实很多游戏都在干,就我自己玩过的,魔兽 3 、dota2,都如此。
    jones2000
        38
    jones2000   80 天前
    Hadoop + Hbase
    devinmagic
        39
    devinmagic   79 天前
    @MeteorCat 可以在格式化的使用-N 参数设置 inode 大小
    libook
        40
    libook   78 天前
    可以尝试存在数据库里管理,比如 MongoDB 对于 16M 以上的文件可以用 GridFS,对于 16M 以下的可以用 BinData,自己没用过,感兴趣可以简单做一下压测。

    https://docs.mongodb.com/manual/core/gridfs/
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1623 人在线   最高记录 5268   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 23:52 · PVG 07:52 · LAX 15:52 · JFK 18:52
    ♥ Do have faith in what you're doing.