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);
}
将BUFFER 转成字符串,buffer内为16进制的,转成string ,则调用Buffer.toString('hex');
获得16进制的字符串,然后见字符串转化为10进制的数字
转载请注明出处: http://sdxlp.cn/article/xiaowenjian.html