xchaoinfo
V2EX  ›  数据库

怎么存储千万级别的图片文件, 在保证尽可能节省空间的前提下,还能方便读写

  •  
  •   xchaoinfo · Jun 3, 2020 · 8305 views
    This topic created in 2350 days ago, the information mentioned may be changed or developed.

    之前的图片都是一个个小文件放在文件夹中, 这样的问题是, 需要的存储空间比较大, 图片迁移也不方便, 而且对 I/O 的消耗非常大. 目前考虑使用数据库来存储, 方案有 lmdb sqlite 请问各位 V 友, 有其他好的方案吗? 能支持多线程读写最好.

    74 replies  •  2020-06-11 04:48:50 +08:00
    cco
    cco
    Jun 3, 2020
    1
    Hbase 也是可以的。。
    hankai17
    hankai17
    Jun 3, 2020
    2
    小文件 io 流量大吗?
    wujieyuan
    wujieyuan
    Jun 3, 2020
    3
    数据库也是文件存储啊,二进制存到数据库不仅费 io 还费 cpu, 文件应该是利用率最高的存储方式了吧
    Jirajine
    Jirajine
    Jun 3, 2020 via Android
    4
    minio
    maemual
    maemual
    Jun 3, 2020❤️3
    5
    seaweedfs
    msg7086
    msg7086
    Jun 3, 2020
    6
    文件系统就是一个效率很高的数据库了。
    你说的这些难道不需要同等的存储空间?不需要消耗那么多 I/O ?
    reus
    reus
    Jun 3, 2020 via Android❤️4
    7
    既然你会考虑 sqlite,我建议你放弃这个想法,信操作系统。
    djoiwhud
    djoiwhud
    Jun 3, 2020 via Android
    8
    你不考虑一下 oss 服务?我只在学生时代见过在 db 中保存图片的。
    xchaoinfo
    xchaoinfo
    OP
    Jun 3, 2020
    9
    @hankai17 访问量不大, 准确的说, 这个图片是用于做机器学习训练用的, 并不是提供给外网服务的.
    xchaoinfo
    xchaoinfo
    OP
    Jun 3, 2020
    10
    @wujieyuan @reus @msg7086 考虑 sqlite 是想要把图片分批保存到 sqlite 中, 这样迁移的时候, 就复制一个 sqlite 的文件就好了, 主要是为了迁移方便, 图片主要是为了做 训练使用.
    xingyuc
    xingyuc
    Jun 3, 2020
    11
    按照不同分类大小创建文件夹,然后文件名是 md5,每次上传先找一下有没有一样的……
    luckyrayyy
    luckyrayyy
    Jun 3, 2020
    12
    minio
    wujieyuan
    wujieyuan
    Jun 3, 2020
    13
    @xchaoinfo 文件系统已经是效率最高的存储方式了, 你说的只是小文件复制慢的问题, 这个完全可以在转移的时候批量压缩再复制, 你想把他们在运行期间就集中在一个数据库文件中, 性能损失更大
    rockyou12
    rockyou12
    Jun 3, 2020
    14
    如果你方问慢,很可能是你没做好分文件夹、硬盘分区、文件命名这些,或者是你硬件遇到瓶颈。把图片放进数据来读写一般并不能提高 io……
    Dragonish3600
    Dragonish3600
    Jun 3, 2020
    15
    用 zfs 开压缩啊
    Mithril
    Mithril
    Jun 3, 2020❤️1
    16
    数据库不是设计来保存二进制的。保存文件已经是最经济的办法了。
    觉得零碎文件不够优化的话,你可以自己写。
    直接开一个大文件,然后把你的图片顺序写进去。另外用数据库保存图片的 offset 和大小。读取的时候直接 memory map 到对应位置。
    不过这样相当于你自己实现了部分文件系统的功能,可以感官上减少一定存储空间,并且用 HDD 的话可以较少碎片提高一定性能。
    实际上用处不大。。。
    hakono
    hakono
    Jun 3, 2020❤️12
    17
    各位别瞎误导 LZ,硬盘分区中的文件系统的确是高效,但对于楼主这种大量零碎文件的存储的场景,直接塞硬盘的文件系统里是非常糟糕的做法。要不然你以为各个大厂都有自己专用的小文件 FS 是为了什么,吃饱了撑的吗

    之前自己开发了一个漫画管理库服务,图片做 hash,然后按照 hash 值 /ab/cd/efdghijk.jpg 的路径保存图片,才区区塞了 20w+张图片,就感觉管理维护起来是个灾难了,然后乖乖用 C 写了个最简单粗暴原始的 FileSystem,立刻性能上了 N 个台阶

    LZ 不想自己写的话,可以使用开源的一些 FS
    https://cloud.tencent.com/developer/news/137215
    PopRain
    PopRain
    Jun 3, 2020
    18
    看文件大小了,不是特别小的文件(小于 4K), 还是放在目录里面高效; 放数据库,备份时、万一文件损坏你会哭死。。。。
    realpg
    realpg
    Jun 3, 2020
    19
    如果文件确实很小,建议自己开发一个专用文件系统,hash 结构 树结构的

    结合你的调用方式,是按批量调用无所谓顺序(机器学习训练材料),还是什么其他的调用方式去优化访问性能

    要不 很多大厂有开源的碎文件 FS 可以试试
    aloxaf
    aloxaf
    Jun 3, 2020❤️1
    20
    脸书针对这个问题发过一篇论文提出了 haystack 文件系统,很符合你的需求,SeaweedFS 是它的开源实现。
    keepeye
    keepeye
    Jun 3, 2020
    21
    https://github.com/sjqzhang/go-fastdfs
    支持文件合并存储,但要通过接口存取
    sivacohan
    sivacohan
    Jun 3, 2020
    22
    6 、7 年之前,我们处理这种情况是放 leveldb
    msg7086
    msg7086
    Jun 3, 2020
    23
    @hakono 各个大厂的小文件 FS 难道不是为了做大型集群?
    楼主要是打算搞起一柜子存储服务器放个几百 TB 的图,那用小文件 FS 是挺好的。
    如果只是单机的话,ReiserFS 或者 Reiser4 不能胜任吗?

    @xchaoinfo 如果要考虑这种单文件迁移的话,可以看看 tar 包或者无压缩 zip 包,因为没有压缩所以串流起来很方便,可以直接定位便宜然后读数据。
    rrfeng
    rrfeng
    Jun 3, 2020 via Android
    24
    tfs 之类的。
    hdfs 也行。

    文件系统主要是 inode 过多性能就好不到哪里去…
    hankai17
    hankai17
    Jun 3, 2020
    25
    不是服务外网 nginx + 小文件模块 足够了
    yincrow
    yincrow
    Jun 3, 2020
    26
    参考手机中微信的图片目录,文件 hash,切割 hash 值,分段创建层级目录
    37Y37
    37Y37
    Jun 3, 2020
    27
    对象存储很合适啊,类似于阿里的 OSS,网易的 NOS,七牛云之类的
    sherwin008
    sherwin008
    Jun 3, 2020
    28
    adobe bridge 可以吗?我一个非计算机领域人的建议
    matrix67
    matrix67
    Jun 3, 2020
    30
    @matrix67 #29 B 站生产就是用毛剑的 bfs 的。
    cjq8z
    cjq8z
    Jun 3, 2020 via Android
    31
    windows server 系统有重复数据删除功能,能够解决你图片占用空间太多问题。再启用 ntfs 压缩功能,提高文件读取速度。
    XiaoxiaoPu
    XiaoxiaoPu
    Jun 3, 2020
    32
    楼上已经提到了 LevelDB,再加一个 RocksDB 吧,支持多线程访问,不支持多进程
    tiedan
    tiedan
    Jun 3, 2020
    33
    hdfs
    ping2
    ping2
    Jun 3, 2020
    34
    其实看有多大了, 4K 大小的话, 直接放内存就好. 千万级也就是几十 GB 直接放内存 /dev/shm/ 就好.

    成本其实还可以接受的.

    落盘同步一下就好了. 根本不用开发, 性能超强, ... 唯一限制就是钱.

    当然下一步是高性能 SSD, XFS 参数调一下其实也还可以接受的.

    如果不接受这个成本, 还要追求性能, 建议是考虑 OSS, 内网调用的性能还可以的.

    再追求更高的性价比才会需要考虑用专门的文件系统或者特定的数据库方案. 除非真的能省很多钱, 不然不建议. 装一台 64GB 的机器省也就是几千不超过一万. 真没有必要搞的太复杂. 专门的文件系统确实好, 但水也深.
    stgmsa
    stgmsa
    Jun 3, 2020
    35
    负责千亿级图床源站的路过,每天源站流量大约 30 亿图片请求。存储是 cassandra,前面挡了一层 12TB 的 nginx file cache 。
    但其实 hbase,甚至文件系统 都可以。
    你要求的量级,可选更是多。

    主要还是要看你有多大访问量(性能),存多久(存储扩展),有没有运维需求和 sla 要求(数据和服务可靠性)。
    love
    love
    Jun 3, 2020 via Android
    36
    我几百万小图存在文件,感觉还行。之前用 ext4 空间没用完 inode 就耗尽了后来换了 inode 无限的 reiserfs 。
    someonedeng
    someonedeng
    Jun 3, 2020
    37
    记得 b 站开源了个不错的 fs
    akira
    akira
    Jun 3, 2020
    38
    对象存储服务啊。。minio 试试看吧 最近在看这个
    CODEWEA
    CODEWEA
    Jun 3, 2020
    39
    数据库就不是 io 了? 而且数据库存储字节化的图片对 io 的操作只多不少。
    ping2
    ping2
    Jun 3, 2020
    40
    @love ext4 inode 数量创建时可以设的, 默认的几百万文件就耗尽的话, 你可能只有 100GB 大小吧?
    cz5424
    cz5424
    Jun 3, 2020
    41
    楼主换个 ssd 吧,提高 io,完事
    wangyzj
    wangyzj
    Jun 3, 2020
    42
    ceph,hdfs
    mosliu
    mosliu
    Jun 3, 2020
    43
    不建议存 db
    hdfs 存海量小文件也不太合适。
    感觉 ceph fastdfs 之类的好点
    或者 minio
    GrayXu
    GrayXu
    Jun 3, 2020
    44
    强力推荐 ceph
    yuyuko
    yuyuko
    Jun 4, 2020 via iPhone
    45
    @stgmsa 你们有对存储做优化吗?
    msg7086
    msg7086
    Jun 4, 2020 via Android
    46
    @ping2 ext4 小文件本来就没有太大优势,不如直接上 reiserfs 了。
    4linuxfun
    4linuxfun
    Jun 4, 2020
    47
    为啥没人推荐 fastdfs 了?我感觉够轻量。以前用 hdfs 存小图片,内存占用比较大,服务重启恢复时间长,自从用了 fastdfs,在也不用担心内存被吃爆、服务重启慢问题了。
    yty2012g
    yty2012g
    Jun 4, 2020
    48
    @jackrelative #8 我居然有幸在工作的时候见过用 blob 类型把图片存 DB 的
    venster
    venster
    Jun 4, 2020 via iPhone
    49
    @yty2012g 以前公司的 OA 系统,所有的附件都直接存数据库,接手维护时简直疯了。
    wbrobot
    wbrobot
    Jun 4, 2020
    50
    唉,凸显年龄了,豆瓣以前有解决方案叫 beansdb 类似 file 的 memcache,后面好像没人维护根据 leveldb 改写了?后面没接着用不知道
    wbrobot
    wbrobot
    Jun 4, 2020
    51
    @wbrobot 看了一下,没错,他们用 go 改写了一版 叫 gobeansdb https://github.com/douban/gobeansdb
    ohao
    ohao
    Jun 4, 2020❤️2
    52
    我有一个图床,量是亿级规模了, 应该算有发言权的

    这个问题还是取决于你的规划
    比如目前规模,每天的数据增长量,未来一个周期的数据量
    以及是热数据还是冷数据
    你使用数据库存储就是下下策了

    你这种最推荐的是组存储集群 1 源数据+1 副本实现容灾
    集群的存储系统有很多 像 Ceph , GlusterFS 这些都可以

    然后就是软件 , 可以使用
    FastDFS + NGINX
    taobao 开源的 TFS + NGINX
    等等 都开源

    NGINX+imglib 类的库, 可以实现图片常见的操作, 比如改变大小,加水印,翻转 黑白 切割等等操作
    这个处理完成后给 CDN 缓存服务器,意味着后端只需要处理一次图片
    处理完成后请求都在缓存服务器中 不在耗后端性能
    当出现性能请求突发, 需要做的就是加 CDN 缓存服务器提高吞吐能力

    如果考虑成本单机存储也可以
    硬盘使用 SATA 的 8 块 16 块 组 HW 容灾, 文件系统使用 XFS, (XFS 对小文件优化性能有明显的提升)
    在选择前面说的软件搭配
    ming7435
    ming7435
    Jun 4, 2020
    53
    我们目前存在 mongodb 中的,还是单实例,目前已经存储有 3000+kw 图片
    lenqu
    lenqu
    Jun 4, 2020
    54
    我个人认为 Hbase 不错,之前当文件数据库使
    swulling
    swulling
    Jun 4, 2020 via iPhone
    55
    小文件存储你可以理解为 kv,单机推荐用 rocksdb
    jones2000
    jones2000
    Jun 4, 2020
    56
    @ohao 对于机器老化需要更替新机器,一般是如果操作的。 比如公司要求 2-3 年需要把老的机器淘汰掉替换成新的机器和新的硬盘。
    stgmsa
    stgmsa
    Jun 4, 2020
    57
    @yuyuko 没有,meta 和 blob 一起存的。如果一定要问有优化么?那就是 后来上传的图片 key 和 meta 都在 ES 里存了一份。
    规模
    存储 22* 8T * 400 台 * 2 机房
    前端机 40 台 E5-2630v2 +128G,(其实从负载看 20 台就足够了)
    缓存 4 * DC S3510 600 G * 12 台
    shicheng1993
    shicheng1993
    Jun 4, 2020
    58
    可以考虑 swift 对象存储
    hallDrawnel
    hallDrawnel
    Jun 4, 2020
    59
    B 站 CTO 写过一个小文件 FS,忘记叫什么了,就是专门用来存各种小图片的。
    yuyuko
    yuyuko
    Jun 4, 2020 via iPhone
    60
    @stgmsa 我们要做冷数据引擎,针对 hdd smr 做优化来降本。。。以为你们这个量会做优化的。。。你们不做优化的话,成本。。。机架费用就不少吧。。。。
    594duck
    594duck
    Jun 4, 2020
    61
    @hakono 兄弟说话到位的,现在 V2EX 上一堆年轻的战狼程序 员。 你的思路是非常对的。七牛啥的都是按这个思路做的。
    aliyun75
    aliyun75
    Jun 4, 2020
    62
    @xchaoinfo 推荐你阿里云的低频访问类型的 OSS,符合你要求的高读写和多线程读写,我这里还能给你提供优惠,有需求联系我 VX:一三一零一二三四五三九
    stgmsa
    stgmsa
    Jun 4, 2020
    63
    @yuyuko 什么 ? SMR ? 你确定 ? 打算用消费级的硬盘吗 ?
    是你 还是 你们运维 和采购 拍 奶子做的决定?
    不管是谁只要出问题不是你背锅就行。

    如果在国内公司写代码,连硬盘选型采购 都要一个程序员推动的话,还是劝尽早解脱(如果你在 Facebook 这种公司做 SWE,当我没说)。
    我们现在有成本优化方案。不过是通过不断迁移在用数据,淘汰老数据下架来完成的。目前就在做。

    不过说实话,千万级别的图片
    100000000(按 1E 算) * 100 ( 100k 一张) / 1000 (到这是 MB ) / 1000 (到这是 GB ) / 1000 (到这是 TB ) = 10 TB...

    存储大概就是 2-4 台 1U 的小机机 ?
    stgmsa
    stgmsa
    Jun 4, 2020
    64
    @yuyuko 上面提到的 key 信息入 ES 就是为迁移数据做准备的。
    另外作为公共服务,优化存储成本是比较坑爹的事情,业务不像你想的那么配合 那么好推动(当然存储成本甩到业务线这个事就能好办很多)

    前端机我接手之前是 160 台,通过替换缓存+k8s 署了一部分 pod 来抗量,干到 40 台 。
    然而存储一般不会轻易去优化。一来周期会很长,二来沟通人力成本很高。一般存储上架就是一步到位顶 3 年的量的。

    不过从运维角度来讲,如果你采用了不合规的硬件(也包括软件,网络 blablabla ),导致业务受影响了。这个锅可不是一般人能背得起的。轻则开除,重一点 你的直属领导 甚至总监级一起背锅滚蛋。
    不让你赔偿损失就不错了(参考下广告展示多少图,你图床高峰期宕机 1 个小时试试?)

    之前就有同事因为这个被开过(他还没过试用期呢)。优化成本固然没有错。我也是资瓷的。但是一定不要无底线的优化 (你需要清楚的知道自己到底在做什么,而不是一味地追求好数据 好绩效 而玩火)
    stgmsa
    stgmsa
    Jun 4, 2020
    65
    @yuyuko 上面提到的 ceph glusterfs,mongo,hdfs hbase 公司各个业务线都有使用的场景。
    但是…… 不建议从 0 开始就上。

    举个例子,openstack 的虚机数据 和 io 都落在了 ceph 集群上,ceph 吃的裸盘,裸盘上面有 cache tier (好像也是 600G 的 dcs3500 3510 sata ssd,没办法,公司买了太多 消化不完),曾经出现过很多次 因为集群里 某块盘挂了 导致 整个虚拟机集群 io hang 住的情况(基础运维能力太渣的话,技术方案再怎么牛逼也不好用)

    mongo 早些年间(大概是 2015 年?)出现过业务写的太疯狂 导致一个 mongo 吃掉了一整台物理机的资源 影响其他用户的(现在这种情况应该是没有了)

    如果你们的支撑团队牛逼,我想他们会给你一个合理的方案的(比如你们的基础运维团队,在了解到你想用 fs 来搞的时候 会告诉你 XFS 还是 ext4,inode 要不要搞小一点,是走 lvm 还是直接干 ),你的 dba 团队也会根据你的 场景来告诉你 是走 hdfs 还是 走 mongo 就能搞定,还是吃个螃蟹,memorykey + optane 的解决方案。

    多问问他们,他们可能是你这个系统后续 要持续打交道的人。。(他们也不想半夜接到你电话爬起来开电脑不是)
    binux
    binux
    Jun 4, 2020 via Android
    66
    那么多不推荐用 db 的到头来推荐一个为小文件优化过的 fs 。。。
    我说名字就那么重要吗?它是实现成 fs 和还是 db 有区别吗?
    stgmsa
    stgmsa
    Jun 4, 2020
    67
    另外 也不是推荐跟我们一样 用 cassandra 。
    ceph glusterfs 普通的 fs,seaweed 的实现方案产品, 甚至 mongo,mysql 分个库 分个表
    都能实现你的需求。
    主要是 …… 这些东西 哪个你们最熟 出问题了能玩的转
    hankai17
    hankai17
    Jun 4, 2020
    68
    @stgmsa 咨询一下有用过 ats 吗?
    vavava
    vavava
    Jun 4, 2020
    69
    BerkeleyDB,然而维护可能麻烦些,不做频繁删除的话还好
    stgmsa
    stgmsa
    Jun 4, 2020
    70
    @hankai17 apache 那个缓存么? 没用过 ……
    newmlp
    newmlp
    Jun 4, 2020
    71
    相信文件系统就是干这个的,存数据库里纯粹脱了裤子放屁,还有合并成大文件方法也是一样,本质上文件系统也是 offset 磁盘上的物理磁道,
    P0P
    P0P
    Jun 5, 2020
    72
    @newmlp 文件系统维护小文件 metadata 开销很大的,自己合并成大文件,然后记录 offset 的话相当于把 metadata 的维护压力放到用户端来做了
    pythonee
    pythonee
    Jun 9, 2020
    73
    # 好场景

    如果你能说明更加具体的业务场景,读写逻辑,估计 v 站的大神能给出更具体的方案
    yuyuko
    yuyuko
    Jun 11, 2020 via iPhone
    74
    @stgmsa dropbox 就是用的 smr,我们这里已经准备开始搞了,国内三家电商之一。。。。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   4068 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 125ms · UTC 06:57 · PVG 14:57 · LAX 22:57 · JFK 01:57
    ♥ Do have faith in what you're doing.