FastDFS合并存储策略

FastDFS提供了合并存储功能的实现,所有的配置都在tracker.conf文件之中,具体摘录如下:
trunk功能启动与配置:通过tracker.conf文件启动与配置,个配置项如下:
use_trunk_file = false#是否启用trunk存储
slot_min_size = 256#trunk文件最小分配单元
slot_max_size = 16MB#trunk内部存储的最大文件,超过该值会被独立存储
trunk_file_size = 64MB#trunk文件大小
trunk_create_file_advance = false#是否预先创建trunk文件
trunk_create_file_time_base = 02:00#预先创建trunk文件的基准时间
trunk_create_file_interval = 86400#预先创建trunk文件的时间间隔
trunk_create_file_space_threshold = 20G#trunk创建文件的最大空闲空间
trunk_init_check_occupying = false#启动时是否检查每个空闲空间列表项已经被使用
trunk_init_reload_from_binlog = false#是否纯粹从trunk-binlog重建空闲空间列表
trunk_compress_binlog_min_interval = 0#对trunk-binlog进行压缩的时间间隔


合并存储文件命名与文件结构
    我们知道向FastDFS上传文件成功时,服务器返回该文件的存取ID叫做file_id,当没有启动合并存储时该file_id和磁盘上实际存储的文件一一对应,当采用合并存储时就不再一一对应而是多个file_id对应的文件被存储成一个大文件。
注:下面将采用合并存储后的大文件统称为Trunk文件,没有合并存储的文件统称为源文件;
区分三个概念:
    1)Trunk文件:storage服务器磁盘上存储的实际文件,默认大小为64MB
    2)合并存储文件的file_id:表示服务器启用合并存储后,每次上传返回给客户端的file_id,注意此时该file_id与磁盘上的文件没有一一对应关系;
    3)没有合并存储的file_id:表示服务器未启用合并存储时,Upload时返回的file_id
    Trunk文件文件名格式:fdfs_storage1/data/00/00/000001 文件名从1开始递增,类型为int;

1、在启动合并存储时服务返回给客户端的file_id也会有所变化

具体如下:

1) 没有合并存储时file_id:group1/M00/00/00/CmQPRlP0T4-AA9_ECDsoXi21HR0.tar.gzCmQPRlP0T4-AA9_ECDsoXi21HR0.tar.gz
这个文件名中,除了.tar.gz 为文件后缀,CmQPRlP0T4-AA9_ECDsoXi21HR0 这部分是一个base64编码缓冲区,组成如下:
storage_id(ip的数值型)
timestamp(创建时间)
file_size(若原始值为32位则前面加入一个随机值填充,最终为64位)
crc32(文件内容的检验码)

2)合并存储时file_id:group1/M00/00/00/CgAEbFQWWbyIPCu1AAAFr1bq36EAAAAAQAAAAAAAAXH82.conf
采用合并的文件ID更长,因为其中需要加入保存的大文件id以及偏移量,具体包括了如下信息:
file_size:占用大文件的空间(注意按照最小slot-256字节进行对齐)
mtime:文件修改时间
crc32:文件内容的crc32码
formatted_ext_name:文件扩展名
alloc_size:文件大小与size相等
id:大文件ID如000001
offset:文件内容在trunk文件中的偏移量
size:文件大小


2、Trunk文件内部结构
    trunk内部是由多个小文件组成,每个小文件都会有一个trunkHeader(可认为是元数据),以及紧跟在其后的真实数据,结构如下:
|||——————————————————— 24bytes——————-—————————|||
|—1byte   —|—4bytes    —|—4bytes —|—4bytes—|—4bytes —|—7bytes                      —|
|—filetype—|—alloc_size—|—filesize—|—crc32  —|—mtime —|—formatted_ext_name—|
|||——————file_data filesize bytes——————————————————————|||
|———————file_data————————————————————————————|
    每个Trunk-Header从上图可以看到,占用了72字节。

合并存储空闲空间管理
1、概述
    Trunk文件为64MB(默认),因此每次创建一次Trunk文件总是会产生空余空间,比如为存储一个10MB文件,创建一个Trunk文件,那么就会剩下接近54MB的空间(TrunkHeader 会24字节,后面为了方便叙述暂时忽略其所占空间),下次要想再次存储10MB文件时就不需要创建新的文件,存储在已经创建的Trunk文件中即可。另外当删除一个存储的文件时,也会产生空余空间。
    在Storage内部会为每个store_path构造一颗以空闲块大小作为关键字的空闲平衡树,相同大小的空闲块保存在链表之中。每当需要存储一个文件时会首先到空闲平衡树中查找大于并且最接近的空闲块,然后试着从该空闲块中分割出多余的部分作为一个新的空闲块,加入到空闲平衡树中。例如:要求存储文件为300KB,通过空闲平衡树找到一个350KB的空闲块,那么就会将350KB的空闲块分裂成两块,前面300KB返回用于存储,后面50KB则继续放置到空闲平衡树之中。
    假若此时找不到可满足的空闲块,那么就会创建一个新的trunk文件64MB,将其加入到空闲平衡树之中,再次执行上面的查找操作(此时总是能够满足了)。

2、TrunkServer
    假若所有的Storage都具有分配空闲空间的能力(upload文件时自主决定存储到哪个TrunkFile之中),那么可能会由于同步延迟导致数据冲突,例如:Storage-A:Upload一个文件A.txt 100KB,将其保存到000001这个TrunkFile的开头,与此同时,Storage-B也接受Upload一个文件B.txt 200KB,将其保存在000001这个TrunkFile文件的开头,当Storage-B收到Storage-A的同步信息时,他无法将A.txt 保存在000001这个trunk文件的开头,因此这个位置已经被B.txt占用。
   为了处理这种冲突,引入了TrunkServer概念,只有TrunkServer才有权限分配空闲空间,决定文件应该保存到哪个TrunkFile的什么位置。TrunkServer由Tracker指定,并且在心跳信息中通知所有的Storage。
    引入TrunkServer之后,一次Upload请求,Storage的处理流程图如下: 

3、TrunkFile同步
    开启了合并存储服务后,除了原本的源文件同步之外,TrunkServer还多了TrunkBinlog的同步(非TrunkServer没有TrunkBinlog同步)。源文件的同步与没有开启合并存储时过程完全一样,都是从binlog触发同步文件。
    TrunkBinlog记录了TrunkServer所有分配与回收空闲块的操作,由TrunkServer同步给同组中的其他Storage。TrunkServer为同组中的其他Storage各创建一个同步线程,每秒将TrunkBinlog的变化同步出去。同组的Storage接收到TrunkBinlog只是保存到文件中,不做其他任何操作。
TrunkBinlog文件文件记录如下:
1410750754 A 0 0 0 1 0 67108864
1410750754 D 0 0 0 1 0 67108864
各字段含义如下:
时间戳
操作类型(A:增加,D:删除)
store_path_index
sub_path_high
sub_path_low
file.id(TrunkFile文件名,比如000001)
offset(在TrunkFile文件中的偏移量)
size(占用的大小,按照slot对齐)

4、空闲平衡树重建
    当作为TrunkServer的Storage启动时可以从TrunkBinlog文件中中加载所有的空闲块分配与加入操作,这个过程就可以实现空闲平衡书的重建。
    当长期运行时,随着空闲块的不断删除添加会导致TrunkBinlog文件很大,那么加载时间会很长,FastDFS引入了检查点文件storage_trunk.dat,每次TrunkServer进程退出时会将当前内存里的空闲平衡树导出为storage_trunk.dat文件,该文件的第一行为TrunkBinlog的offset,也就是该检查点文件负责到这个offset为止的TrunkBinlog。也就是说下次TrunkServer启动的时候,先加载storage_trunk.dat文件,然后继续加载这个offset之后的TrunkBinlog文件内容。   

下面为TrunkServer初始化的流程图:




5、TrunkBinlog压缩
    上文提到的storage_trunk.dat既是检查点文件,其实也是一个压缩文件,因为从内存中将整个空闲平衡树直接导出,没有了中间步骤,因此文件就很小。这种方式虽然实现了TrunkServer自身重启时快速加载空闲平衡树的目的,但是并没有实际上缩小TrunkBinlog文件的大小。假如这台TrunkServer宕机后,Tracker会选择另外一台机器作为新的TrunkServer,这台新的TrunkServer就必须从很庞大的TrunkBinlog中加载空闲平衡树,由于TrunkBinlog文件很大,这将是一个很漫长的过程。
    为了减少TrunkBinlog,可以选择压缩文件,在TrunkServer初始化完成后,或者退出时,可以将storage_trunk.dat与其负责偏移量之后的TrunkBinlog进行合并,产生一个新的TrunkBinlog。由于此时的TrunkBinlog已经从头到尾整个修改了,就需要将该文件完成的同步给同组内的其他Storage,为了达到该目的,FastDFS使用了如下方法:
      1)TrunkServer将TrunkBinlog同步给组内其他Storage时会将同步的最后状态记录到一个mark文件之中,比如同步给A,则记录到A.mark文件(其中包括最后同步成功的TrunkBinlog偏移量)。
      2)TrunkServer在将storage_trunk.dat与TrunkBinlog合并之后,就将本地记录TrunkBinlog最后同步状态的所有mark文件删除,如一组有A、B、C,其中A为TrunkServer,则A此时删除B.mark、C.mark。
      3)当下次TrunkServer要同步TrunkBinlog到B、C时,发现找不到B.mark、C.mark文件,就会自动从头转换成从头开始同步文件。
      4)当TrunkServer判断需要从头开始同步TrunkBinlog,由于担心B、C已经有旧的文件,因此就需要向B、C发送一个删除旧的TrunkBinlog的命令。
      5)发送删除命令成功之后,就可以从头开始将TrunkBinlog同步给B、C了。
大家发现了么,这里的删除TrunkBinlog文件,会有一个时间窗口,就是删除B、C的TrunkBinlog文件之后,与将TrunkBinlog同步给他们之前,假如TrunkBinlog宕机了,那么组内的B、C都会没有TrunkBinlog可使用。
流程图如下:



Tracker-Leader选择TrunkServer
1、描述
      在一个FastDFS集群之中,在开启合并存储时,为了分配空间引入了一个TrunkServer角色,该TrunkServer是该Group中的一个Storage,只是该Storage要负责为该组内的所有Upload操作分配空间。为了避免不同Tracker为该Group选择了不同的TrunkServer,此时引入了Tracker-Leader角色,也就是TrunkServer最终是由Tracker-Leader来选择的,然后通知给该组内的所有Storage。

2、 Tracker -Leader选择TrunkServer时机
    1)当组内的一个Storage状态变成Active时,并且该组还没有指定TrunkServer,在tracker_mem_active_store_server函数中触发。
    2)某个Tracker在经过选择,被设置成Leader时,则为当前还没有指定TrunkServer的组选择TrunkServer,在relationship_select_leader函数中触发。
    3)在定期指定的任务tracker_mem_check_alive函数中,默认该函数100秒指定一次。会尝试着为每个当前还没有指定TrunkServer的组选择TrunkServer。对已经指定的组检查其TrunkServer是否还处于活动状态(根据TrunkServer与Tracker的最后心跳时间计算),若不处于活动状态,则会尝试着给该组选择一个新的TrunkServer。在tracker_mem_check_alive函数中触发。
 
3、Tracker-Leader选择TrunkServer的过程
    该过程由tracker_mem_find_trunk_server函数负责,具体操作步骤如下:
    1)依次向组内当前状态为ACTIVE的Storage发送TRUNK_GET_BINLOG_SIZE命令的消息,来查询每个Storage当前保存的Trunk-Binlog的文件大小。来找到Trunk-Binlog文件最大的Storage。
    2)若该Group的最后一个TrunkServer与要设置的新的TrunkServer并非同一个,则像该新的TrunkServer发送TRUNK_DELETE_BINLOG_MARKS命令,让其删除trunk-binlog同步的状态mark文件。(既然这个TrunkServer是新的,那么就要清除同步trunk-binlog的状态,使其从头同步trunk-binlog给组内的其他Storage)。
    3)变更该组的TrunkServer,并将修改写入到storage_groups_new.dat文件之中,更新该组的最后TrunkServer设置,设置TrunkServer已经变更标志,该标志使得在与Storage的心跳中通知对方TrunkServer已经变更。



本页内容版权归属为原作者,如有侵犯您的权益,请通知我们删除。
论机器人的环境感知与智主运动 –兼谈基于微分几何的人工智能 标签(空格分隔): 人工智能 计算机视觉 自主移动 微分流形 Ricci流 版权声明:本文为作者原创文章,未经作者允许不得转载。 前言 人工智能是分主观与客观的,是硬币的两个方面, 客观智能是世界的本质描述,是物理的是数学的, 主观智能是来自于客观智能,是哲学的是宗教的。 抛开物理与数学只讲方法是走不远的,如无本之木、无源之水, 单讲物理与数学只会得到一个静默纷扰的世界,无乐无诗无书无画。 序言 什么是智能,这是一个令人思绪飞扬的问题,本文的内容

理解镜像、容器和存储驱动 - 2016-07-23 19:07:52

理解镜像、容器和存储驱动 为了更有效地使用存储驱动,你必须理解Docker如何创建和存储镜像。接下来,需要理解容器是如何使用这些镜像的。最后,你需要一个对镜像和容器操作者都需要的技术简介。   镜像和图层layers 每一个Docker镜像都参考了一系列的只读层,这些层代表着文件系统的区别。层级是从底层开始,逐一建立组成容器的root文件系统。下面的图显示了Ubuntu镜像有4层: Docker的存储驱动是负责堆放这些层级并且提供一个统一的视图。 当你创建一个新的容器,你会在底层栈上加入一个新的、稀疏的、
Flume简介 Flume安装 1. 解压 flume安装包到 /itcast/ 目录下 tar -zxvf /*flume安装包*/ /itcast/ 2. 修改 flume配置文件: 2.1 flume-env.sh 修改文件名称: mv flume-env.sh.template flume-env.sh 添加 java_home ,保证 flume 所使用的jdk和hdfs是一样的(可以使用 echo JAVA_HOME 查看当前机器所使用的javaHome所在路径) 2.2 编写agent配置文
注:本文为自用,随时更新。 一.系统环境 Windows7、Ecplise 4.4.0,Hadoop2.7.2 Hadoop安装教程请看: Hadoop2.7.2安装教程 此处需要注意的是:你的hadoop运行在远程的虚拟机上,但是你的windows上也需要有hadoop的运行环境,这样eclipse才能进行远程调试,所按照上面教程安装完虚拟机上的hadoop,还需要下载同样版本的Hadoop加压到windows上即可,还需要配置相应的环境变量,拷贝winutil.exe.hadoop.dll等文件到ha
2、spark wordCount程序深度剖析 标签: spark 一、Eclipse(scala IDE)开发local和cluster (一). 配置开发环境 要在本地安装好java和scala。  由于spark1.6需要scala 2.10.X版本的。推荐 2.10.4,java版本最好是1.8。所以提前我们要需要安装好java和scala并在环境变量中配置好。 下载scala IDE for eclipse安装 连接: http://scala-ide.org/download/sdk.html
1、spark 部署 标签: spark 0 apache spark项目架构 spark SQL -- spark streaming -- MLlib -- GraphX 0.1 hadoop快速搭建,主要利用hdfs存储框架 下载hadoop-2.6.0,解压,到etc/hadoop/目录下 0.2 快速配置文件 cat core-site.xml configuration property name fs.defaultFS /name value hdfs://worker1:9000 /va

Devstack单节点环境实战配置 - 2016-07-23 14:07:05

本实验是在VMware12下建立虚机的一个测试环境。 1 前期准备工作 真机环境win10 Linux版本 centos-everything-7.0 VMware版本 VMwareworkstations12 虚机配置如下: 8G内存 2核cpu(开启虚拟化) 网络配置为桥接模式 /boot 500M(一定要分大点不然之后会遇到问题) swap分区4G 其余的空间全部分给/分区 配置yum源,你可以保持装机自带的centos自带官方yum源,或者使用国内的给的镜像,本次试验中用的国外镜像并且使用fast
Openstack自动化部署工具, 主要用于生产环境. 一. 环境准备 这里用的是Openstack 9.0版本. Fuel Documentation 下载 Fuel for OpenStack镜像文件 , 用于安装Feul Master. 安装 Xshell , 用于远程连接. 安装 xftp , 用于从Windows主机向虚拟机传输文件. 二. 安装fuel_master节点 1. VirtualBox网络配置 管理-全局设定-网络-仅主机(Host-Only)网络 新建三张新的网卡: Host-O
本篇主要阐述通过DeveStack 去部署Openstack(mitaka),对大多数来说安装部署Openstack 来说是个痛苦的过程,尤其是 OpenStack和它依赖的一些组件在快速发展中,经常出现这个版本组件对不上那个版本 dashboard等情况。如果只是看看或者初期玩玩 OpenStack的话,使用DevStack也是个不错的办法。DevStack采用了自动化源码部署的方式,适用于开发环境的部署和Openstack开发者,单节点,小环境;这里采用的操作系统为Ubuntu14.04。 一、操作系
操作过程: 第一步删除phoenix中系统的表格信息,主要为SYSTEM.CATALOG,第二步删除Hbase中的表格信息。 操作步骤: (1)查询phoenix系统表 SYSTEM.CATALOG 内容是所有表格的信息,系统表和自建表 SYSTEM.FUNCTION 内容是所有函数信息,系统函数和自定义函数 SYSTEM.SEQUENCE 我也不知道 SYSTEM.STATS 内容是所有表格的最后状态信息 (2)查询SYSTEM.CATALOG表结构 (3)我要删除的表格 DELETE from SYS