如何从一个大文件中分离小文件

简介: 互联网应用经常需要存储用户上传的图片,比如facebook相册。facebook目前存储了2600亿张照片,总大小为20PB,每张照片约为80KB。用户每周新增照片数量为10亿。(总大小60TB),平均每秒新增3500张照片(3500次写请求),读操作峰值可以达到每秒百万次

背景

互联网应用经常需要存储用户上传的图片,比如facebook相册。

facebook目前存储了2600亿张照片,总大小为20PB,每张照片约为80KB。用户每周新增照片数量为10亿。(总大小60TB),平均每秒新增3500张照片(3500次写请求),读操作峰值可以达到每秒百万次。

考虑到一台标配的服务器的硬盘是10TB,理论上可以存 10TB/80KB=1.3亿张左右的照片。

然而linux服务器的文件索引的设计最多只支持500w左右的文件数,如果超过500w,性能会大幅下降。

在普通的linux文件系统中,读取一个文件包括三次磁盘io:首先读取目录元数据到内存,其次把文件中的inode节点装载到内存,最后读取实际的文件内容。由于小文件个数太多,无法将所有的目录以及文件的inode信息缓存到内存,因此磁盘IO次数很难达到每个图片读取只需要一次磁盘IO的理想状态。

因此,facebook的图片存储系统haystack设计采用的思路是: 多个逻辑图片文件共享一个物理文件。

1个物理文件的大小=32MB。因此linux服务器中的文件个数在 10TB/32MB=1024*1024/32=327680..远远小于linux服务器的文件索引的阈值。

照片文件在物理文件中的存放为依次的顺序存放。每个照片文件的存放规格如下:

- 1字节的标记位。0代表接下来的照片仍然可用,1代表接下来的照片已经被删除,2代表该物理文件接下来已经没有图片了。

- 4字节的size。标记照片的大小x。

- x字节,照片文件本身。
实现

首先,文件已经到手,现在的目标是,根据规则,将文件的所有图片解出。

思路:...没有思路 读取,然后循环,然后写入即可。

代码:

var fs = require('fs');

var d = fs.readFileSync('rf.data');
var b = new Buffer(d);
var c = 0;
for(var i=0;i<b.length;){
    var start = i;
    var flag = b.slice(start,start+1);//获得标志位
    flag = getR(flag);
    if(flag == 0){
        var size = getR(b.slice(start+1,start+5));
        //将图片输出
        fs.writeFile(c+'.jpg',b.slice(start+5,start+6+size),function(){
            console.log('图片写入完成')
        });
        i = i + 1 + 4 + size;
        c++;
    }else if(flag == 1){
        var size =getR( b.slice(start+1,start+5));
        i = i + 1 + 4 + size;
    }else if(flag == 2){
        i = b.length;
    }
}

function getR ( buf ){
    return parseInt(buf.toString('hex'),16);
}

额,对于我个人的难点在于 16进制转 10进制..

  1. 首先将BUFFER 转成字符串,buffer内为16进制的,转成string ,则调用Buffer.toString('hex');
//其中buffer的 toString 还支持以下几个类型encode
utf8
hex
ascii
binary
base64
utf-16le
  1. 然后获得16进制的字符串,然后见字符串转化为10进制的数字
var str = 'ff';
parseInt(str,16);
//以下转化
var a = 'ff';//字符串
parseInt(a,16);//255
var a = 0xff;
a.toString(10);//"255"
//如果想把16进制转化为10进制
var a = 0xff;
parseInt(a)
parseInt(a.toString(16))
相关文章
|
算法 前端开发 UED
封装一个快速生成目录树的全局脚本
封装一个快速生成目录树的全局脚本
85 0
|
1月前
实现文件目录结构功能
实现文件目录结构功能
18 1
|
2月前
|
PyTorch TensorFlow API
大模型中 .safetensors 文件、.ckpt文件、.gguf和.pth以及.bin文件区别、加载和保存以及转换方式
本文讨论了大模型中不同文件格式如`.safetensors`、`.ckpt`、`.gguf`、`.pth`和`.bin`的区别、用途以及如何在TensorFlow、PyTorch和ONNX等框架之间进行加载、保存和转换。
573 2
|
7月前
|
存储 Web App开发 Windows
LabVIEW使用VI Snippets存储和共享重用代码段
LabVIEW使用VI Snippets存储和共享重用代码段
54 0
|
7月前
如何批量复制多个文件到多个目录中(批量复制文件,多对多文件高效操作的方法)
该文介绍了如何使用一个工具进行文件批量复制的操作。首先,提供了百度网盘和蓝奏云的链接,附有提取码,以获取所需工具。接着,展示了一个包含三个文件夹和两张图片的示例。操作步骤包括:打开工具,使用Ctrl+5进入批量复制模块,选择图片并拖拽至复制区域,然后选择目标文件夹(在这里是三个命名的空文件夹),点击“开始复制”,等待过程完成。工具提供复制选项供用户按需选择,且支持保存操作路径以备后续使用。完成后,目标文件夹将包含复制的图片,整个过程简便快捷。
|
C++
19.【c++基础篇.三个文件实现】
19.【c++基础篇.三个文件实现】
79 0
导出项目目录树结构
在cmd中切换到自己所需要导出项目树结构的根目录下,在win中可以使用cd来切换文件夹
169 0
|
缓存 Linux 索引
文件相关概念
文件相关概念
138 0
文件相关概念
|
存储 缓存 网络安全
DVC 使用案例(二):共享数据与模型文件
与 Git 一样,DVC 允许在分布式环境进行协作。 我们可以轻松地将所有数据文件、目录以及匹配的源代码完全一样地导入任何机器。 您需要做的就是为您的 DVC 项目设置远程存储库,并将数据推送到那里,以便其他人可以访问它。 目前 DVC 支持 Amazon S3、Microsoft Azure Blob Storage、Google Drive、Google Cloud Storage、SSH、HDFS 和其他远程存储地址,并且该列表还在持续增长。 (一个完整的列表和配置说明,请参阅 dvc remote add。)
|
存储 设计模式 算法
【代码结构设计】文件夹的树状结构
如何利用设计模式优雅的抽象文件夹树状操作
317 0