1. 异构存储概述
异构存储可以根据各个存储介质读写特性的不同发挥各自的优势。针对冷数据,采用容量大的、读写性能不高的介质存储,比如最普通的磁盘;对于热数据,可以采用SSD(固态硬盘,读写速度快,容量小)的方式进行存储。
2. 异构存储的原理
·DataNode通过心跳汇报自身数据存储目录的StorageType给NameNode
·随后NameNode进行汇总并更新集群内各个节点的存储资源情况
·待复制文件根据自身设定的存储策略信息向NameNode请求拥有此类型存储介质的DataNode作为候选节点
3. 异构存储的类型
根据存储速度,从快到慢:
·RAM_DISK (true)
·SSD (false)
·DISK (false)
·ARCHIVE (false)(一种高密度的存储方式,一般用于冷数据的存储)
true或者false代表此类存储类型是否为transient,即转瞬即逝的。在HDFS中,如果没有主动声明数据目录存储类 型,默认都是DISK类型。
4. 异构存储的配置
配置属性dfs.datanode.data.dir可以对本地对应存储目录进行设置,同时带上一个存储类型标签,声明此目录用的是哪种类型的存储介质:
eg: [SSD]file:///grid/dn/ssd0
如果目录前没有带任何标签,则默认是DISK类型
输入hdfs storagepolicies -help将得到三大操作命令:
[-listPolicies] //列出目前现有的存储策略
[-setStoragePolicy -path <path> -policy <policy>] // 对目标文件/目录设置存储策略
[-getStoragePolicy -path <path>] //获取给定路径的存储策略
5. 异构存储的不足之处
目前HDFS上还不能对文件目录存储策略变更做出自动的数据迁移。需要用户在执行了相应策略setStoragePolicy之后,额外执行hdfs-mover命令做文件目录的扫描,进行数据块的迁移。这里所指的文件目录存储策略变更有以下两类情况:
·原先未设置StoragePolicy,后来进行了设置
·原先设置了A策略,后来又设置了B策略
数据迁移命令:
hdfs mover [-p <files/dirs> | -f <local file>] //hdfs mover数据迁移命令
-p <files/dirs> //需要被迁移的HDFS文件/目录的路径
-f <local file> //需要被迁移的HDFS文件/目录对应的本地文件系统路径
其中一个参数针对HDFS的文件目录,另一个参数针对本地的文件。
6. 块存储策略的类型
各策略名称如下:
·HOT
·COLD
·WARN
·ALL_SSD
·ONE_SSD
·LAZY_PERSIST
默认情况下,HDFS把集群中的数据都看成是经常访问的数据,即采用HOT策略。
7. 内存存储(LAZY_PERSIST)的含义
HDFS内存存储与HDFS缓存:都用机器的内存作为存储数据的载体
HDFS缓存需要用户主动设置目标待缓存的文件、目录,需要使用HDFS缓存管理命令
HDFS内存存储策略:LAZY_PERSIST则直接将内存作为数据存放的载体,可以这么理解,此时节点的内存也充当了一块“磁盘”
8. 内存存储(LAZY_PERSIST)原理
在内存存储新数据的同时,持久化距离当前时刻最远的数据。LRU : 最近最少使用算法
LAZY_PERSIST内存存储,在数据存储的同时会有另外一批数据被异步地持久化,所以这里一定会涉及多个服务对象的合作。这些服务对象的指挥者是FsDatasetImpl,它是一个管理DataNode所有磁盘读写的管家
在FsDatasetImpl中,与内存存储相关的服务对象有3个:
RamDiskReplicaLruTracker:是副本跟踪类,此类中维护了所有已持久化、未持久化的副本以及总副本数信息。所以当一个副本被最终存储到内存中后,相应的会有副本所属队列信息的变更。当节点不足时,会将最近最少被访问的副本块移除。
LazyWriter:这是一个线程服务,此线程会不断地从数据块列表中取出数据块,将数据块加入到异步持久化线程池RamDiskAsyncLazyPersistService中去执行
RamDiskAsyncLazyPersistService:此对象是异步持久化线程服务,针对每一个磁盘设置一个对应的线程池,需要持久化到给定磁盘的数据块会被提交到对应的线程池中去。每个线程池的最大线程数为1。
9. 内存存储(LAZY_PERSIST)的配置
①配置虚拟内存盘:
在Linux中,有一种将内存模拟为一块盘的技术,叫做虚拟内存盘(RAM disk)。这是一种模拟的盘,实际数据都是存放在内存中的。虚拟内存盘可以在某些特定的内存式存储文件系统下结合使用,比如tmpfs,ramfs。通过这个技术,就可以将机器内存利用起来,作为一块独立的虚拟盘供DataNode使用。
以tmpfs为例,默认情况下tmpfs被挂载到/dev/shm,并且大小是32GB,也就是说此目录下的数据实质上是存在于内存中的。需要将其挂在到特定的目录,以及对内存的使用大小进行有效的控制时,可以使用以下命令:
sudo mount -t tmpfs -o size=16g tmpfs /mnt/dn-tmpfs/
将tmpfs挂载到目录/mnt/dn-tmpfs,并且限制内存使用大小为16GB。最后,建议在/etc/fstab文件中将这层关系写入,这可以让机器在重启之后自动创建好挂载关系。
将机器中已经完成好的虚拟内存盘配置到dfs.datanode.dir中,其次还要带上RAM_DISK标签。
<name>dfs.datanode.dir</name>
<value>/grid/0,/grid/1,/grid/2,[RAM_DISK]/mnt/dn-tmpfs</value>
②设置具体的文件策略类型
a.确保HDFS异构存储策略没有被关闭,配置项:dfs.storage.policy.enabled
b.确认dfs.datanode.max.locked.memory是否设置了足够大的内存值,是否已是DataNode能承受的最大内存大小。设置过小会导致内存中总的可存储的数据块变少,但如果超过DataNode能承受的最大内存大小的话,部分内存块会被直接移出。
c.对目标文件目录设置StoragePolicy为LAZY_PERSIST的内存存储策略
①命令行方式:
hdfs storagepolicies -setStoragePolicy -path <path> -policy LAZY_PERSIST
②调用对应的程序方法,比如调用暴露在外部的create方法,但是得带上参数 CreateFlag.LAZY_PERSIST,如下所示:
FSDataOutPutStream fos = fs.create(path,FsPermission.getFileDefault(),EnumSet.of(CreateFlag.CREATE,Create-Flag.LAZ Y_PERSIST),bufferLength,replicationFactor,blockSize,null)
③通过FileSystem的setStorage-Policy方法:
fs.setStoragePolicy(path,”LAZY_PERSIST”)
这种方式的优点在于可以用程序动态的设置目标路径的存储方式
10. 总结
HDFS异构存储功能是解决冷热数据存储问题的一把利器。HDFS的内存存储方式的难点在于它如何对数据进行持久化,其中还涉及LRU(最近最少使用)算法。而HDFS异构存储的重点在于理解此套机制的整体实现原理,通过对DataNode上的数据目录以及HDFS上的目标路径打标签的方式来进行数据的存储选择。