参考:
https://www.cnblogs.com/zhangningbo/p/4146398.html
http://hadoop.apache.org/docs/r3.1.1/hadoop-project-dist/hadoop-hdfs/CentralizedCacheManagement.html
https://blog.csdn.net/androidlushangderen/article/details/51469877
目录
- 概述
- 使用场景
- 整体架构
- 基本概念
- 缓存指令(Cache directive)
- 缓存池(Cache pool)
- cacheadmin命令行接口
- 命令使用帮助
- 缓存指令命令
- addDirective:添加一个新的缓存指令
- listDirectives:列出缓存指令
- modifyDirective:修改缓存指令
- removeDirective:删除一条缓存指令
- removeDirectives:删除特定路径的每一条缓存指令
- 缓存池命令
- addPool:添加一个新的缓存池
- listPools :显示一个或多个缓存池的信息
- modifyPool:修改已存在缓存池的元数据信息
- removePoo:删除缓存池。
- 配置
- Native Libraries支持
- 配置属性
- 必选配置
- 可选配置
- OS限制
概述
HDFS中的集中化缓存管理是一个显式的缓存机制,该机制允许用户通过HDFS来缓存指定的路径。Namenode将会与在磁盘上有请求Block的DataNodes进行通信,并指示它们将这些block缓存到堆外缓存中。
HDFS的集中化缓存管理有很多的重大优势:
- 显式的固定能够防止频繁使用的数据被从内存中清除。当工作集的大小超过主内存的大小时,这一点尤为重要,这在许多HDFS工作负载中都很常见。
- 由于datanode的缓存由namenode管理,所以应用程序在做task放置决策时可以查询缓存块的位置集。将task与缓存块副本放在同一位置可提高读操作的性能。
- 当块已经被DataNode缓存时,客户端就可以使用一个新的更高效的零拷贝读取API。因为缓存数据的checksum校验只需由DataNode执行一次,因此在使用这种新的API时,客户端基本上不会有开销。
- 集中化的缓存可以提高集群整体的内存利用率。当依赖于每个DataNode上的OS buffer 缓存时,重复读取一个block将导致该block的所有n个副本被拉入buffer缓存。通过集中化缓存管理,用户可以显示的固定那个副本中的m个到内存中,从而节省n-m的内存。
使用场景
集中化缓存管理对于频繁使用的文件非常有用。例如,hive中的一个较小的fact表(常用于join操作)就是一个非常好的缓存对象。另一方面,对于一个年度报表查询的输入数据做缓存很可能就没有多大作用了,因为历史数据通常只会被读取一次。
集中化缓存管理对于有性能SLAs的混合负载也很有用。缓存高优先级工作负载的工作集可以确保它不会与低优先级工作负载竞争磁盘I/O。
整体架构
在这个架构中,NameNode负责协调所有DataNode的堆外缓存。NameNode会周期性的接收来自每个DataNode的缓存报告,报告中会描述指定DN的所有缓存的block。NameNode通过借助于DN心跳上的cache和uncache命令来管理DN的缓存。
NameNode通过查询自己的缓存指令(cache directives)集来决定缓存哪些路径。缓存指令会被持久化到fsimage和editlog中,通过JAVA和命令行 API可以添加、删除、修改缓存指令。NameNode同时还会存储一组缓存池(cache pool),这些缓存池是用以将缓存指令组合在一起以进行资源管理和强制权限的管理实体。
目前不会缓存那些处于construction, corrupt状态或其他不完整的block。如果一条缓存指令包含了一个符号链接,那么该符号链接不会被缓存。
目前只支持文件和目录级的缓存。
基本概念
缓存指令(Cache directive)
缓存指令定义了一个需要被缓存的路径。路径可以是文件或者目录。目录的缓存是非递归的,而是只会缓存目录中的第一级的文件。
指令同时会指定一些其他的参数,如缓存的副本因子以及有效期。副本因子指定了要缓存的块的副本数,如果有多个指令指向了同一个文件,那么就使用最大的缓存副本因子。
有效期是在命令行中指定的,就像TTL一样。未来会引入相对有效期。缓存指令过期之后,NameNode在进行缓存决策时就不会考虑了。
缓存池(Cache pool)
缓存池是一个用以管理缓存指令组的管理实体。缓存池有类UNIX的权限,可以限制哪些用户和组可以访问缓冲池。写权限允许用户将缓存指令添加到缓存池中或从缓存池中删除。读权限允许用户列出缓存池中的缓存指令,以及其他元数据。执行权限是不可用的。
缓存池也可以用以资源管理。它可以强制设置一个最大限制值,可以限制池中指令可以在聚合中缓存的字节数。通常,缓存池限制值之和约等于集群中为HDFS做缓存而保留的总内存量。缓存池也可以追踪许多统计信息以帮助集群用户决定应该缓存什么。
缓存池也可以强制设置一个TTL。该值限制了被添加到缓存池的指令的最大有效期。
cacheadmin命令行接口
在命令行上,管理员和用户可以通过hdfs cacheadmin子命令与缓存池和缓存命令交互。
缓存指令由一个唯一的无重复的64位整数ID标识。ID不会被重复使用,即使缓存指令被删除了。
缓存池由一个唯一的字符串名称标识。
命令使用帮助
$ hdfs cacheadmin
Usage: bin/hdfs cacheadmin [COMMAND]
[-addDirective -path <path> -pool <pool-name> [-force] [-replication <replication>] [-ttl <time-to-live>]]
[-modifyDirective -id <id> [-path <path>] [-force] [-replication <replication>] [-pool <pool-name>] [-ttl <time-to-live>]]
[-listDirectives [-stats] [-path <path>] [-pool <pool>] [-id <id>]]
[-removeDirective <id>]
[-removeDirectives -path <path>]
[-addPool <name> [-owner <owner>] [-group <group>] [-mode <mode>] [-limit <limit>] [-defaultReplication <defaultReplication>] [-maxTtl <maxTtl>]]
[-modifyPool <name> [-owner <owner>] [-group <group>] [-mode <mode>] [-limit <limit>] [-defaultReplication <defaultReplication>] [-maxTtl <maxTtl>]]
[-removePool <name>]
[-listPools [-stats] [<name>]]
[-help <command-name>]
以上命令中除最后一个-help帮助命令之外,其余9个命令都是与缓存操作相关的命令。分为2大类,前5个是CacheDirective相关的,之后4个是CachePool相关的。
缓存指令命令
addDirective:添加一个新的缓存指令
hdfs cacheadmin -addDirective -path <path> -pool <pool-name> [-force] [-replication <replication>] [-ttl <time-to-live>]
参数 | 含义 |
---|---|
<path> | 要缓存的路径,该路径可以是文件夹或文件 |
<pool-name> | 要加入缓存指令的缓存池,必须对缓存池有写权限才能添加新的缓存指令。 |
-force | 不检查缓存池的资源限制 |
<replication> | 要使用的缓存副本因子,默认为1 |
<time-to-live> | 缓存指令的有效时长。可以按照分钟,小时,天来指定,如30m,4h,2d。有效单位为[smhd]。“never”表示永不过期的指令。如果未指定该值,则缓存指令就不会过期。 |
使用示例
#添加缓存池
$ hdfs cacheadmin -addPool CachePool1 -mode 750 -maxTtl 5h -limit 500000000
Successfully added cache pool CachePool1.
$ hdfs cacheadmin -listPools
Found 1 result.
NAME OWNER GROUP MODE LIMIT MAXTTL DEFAULT_REPLICATION
CachePool1 hadoop hadoop rwxr-x--- 500000000 000:05:00:00.000 1
#添加缓存指令
$ hdfs cacheadmin -addDirective -path /tmp -pool CachePool1 -replication 2 -ttl 1h
Added cache directive 1
listDirectives:列出缓存指令
hdfs cacheadmin -listDirectives [-stats] [-path <path>] [-pool <pool>]
参数 | 含义 |
---|---|
<path> | 只列出带有该路径的缓存指令。注意,如果路径path在缓存池中有一条我们没有读权限的缓存指令,那么它就不会被列出来。 |
<pool> | 只列出该缓存池内的缓存指令。 |
-stats | 列出基于path的缓存指令统计信息。 |
使用示例
$ hdfs cacheadmin -listDirectives
Found 1 entry
ID POOL REPL EXPIRY PATH
1 CachePool1 2 2019-07-25T18:47:46+0800 /tmp
modifyDirective:修改缓存指令
hdfs cacheadmin -modifyDirective -id <id> [-path <path>] [-force] [-replication <replication>] [-pool <pool-name>] [-ttl <time-to-live>]
参数 | 含义 |
---|---|
<id> | 指定要修改的指令Id(必选) |
<path> | 要缓存的路径,该路径可以是文件夹或文件(可选) |
<pool-name> | 要加入缓存指令的缓存池。必须对缓存池有写权限才能添加新的缓存指令。(可选) |
-force | 不检查缓存池的资源限制 |
<replication> | 要使用的缓存副本因子,默认为1(可选) |
<time-to-live> | 缓存指令的有效时长。可以按照分钟,小时,天来指定,如30m,4h,2d。有效单位为[smhd]。“never”表示永不过期的指令。如果未指定该值,则缓存指令就不会过期。 |
使用示例
$ hdfs cacheadmin -listDirectives
Found 1 entry
ID POOL REPL EXPIRY PATH
4 CachePool1 2 2019-07-25T19:43:02+0800 /tmp
$ hdfs cacheadmin -modifyDirective -id 4 -path /data -ttl 5h
Modified cache directive 4
$ hdfs cacheadmin -listDirectives
Found 1 entry
ID POOL REPL EXPIRY PATH
4 CachePool1 2 2019-07-25T23:43:55+0800 /data
removeDirective:删除一条缓存指令
hdfs cacheadmin -removeDirective <id>
参数 | 含义 |
---|---|
<id> | 要删除的缓存指令的ID。必须对该指令的缓存池拥有写权限,才能删除它。要查看详细的缓存指令列表,可以使用-listDirective |
使用示例
$ hdfs cacheadmin -listDirectives
Found 2 entries
ID POOL REPL EXPIRY PATH
1 CachePool1 2 2019-07-25T18:47:46+0800 /tmp
2 CachePool1 2 2019-07-25T18:53:51+0800 /data
#删除缓存池
$ hdfs cacheadmin -removeDirective 1
Removed cached directive 1
$ hdfs cacheadmin -listDirectives
Found 1 entry
ID POOL REPL EXPIRY PATH
2 CachePool1 2 2019-07-25T18:53:51+0800 /data
removeDirectives:删除特定路径的每一条缓存指令
hdfs cacheadmin -removeDirectives -path <path>
参数 | 含义 |
---|---|
<path> | 要删除的缓存指令的路径。你必须对该指令的缓存池拥有写权限,才能删除它。要查看详细的缓存指令列表,可以使用-listDirective |
使用示例
$ hdfs cacheadmin -addDirective -path /data -pool CachePool1 -replication 2 -ttl 5h
Added cache directive 3
# 缓存指令的最大有效时长不能超过缓存池的最大有效时长
$ hdfs cacheadmin -addDirective -path /data -pool CachePool1 -replication 2 -ttl 7h
InvalidRequestException: Expiration 000:07:00:00.000 exceeds the max relative expiration time of 18000000 ms.
$ hdfs cacheadmin -listDirectives
Found 2 entries
ID POOL REPL EXPIRY PATH
2 CachePool1 2 2019-07-25T18:53:51+0800 /data
3 CachePool1 2 2019-07-25T22:57:53+0800 /data
$ hdfs cacheadmin -removeDirectives -path /data
Removed cache directive 2
Removed cache directive 3
Removed every cache directive with path /data
$ hdfs cacheadmin -listDirectives
Found 0 entries
缓存池命令
addPool:添加一个新的缓存池
hdfs cacheadmin -addPool <name> [-owner <owner>] [-group <group>] [-mode <mode>] [-limit <limit>] [-maxTtl <maxTtl>]
参数 | 含义 |
---|---|
<name> | 新缓存池的名称 |
<owner> | 该缓存池所有者的名称,默认为当前用户。 |
<group> | 缓存池所属的组,默认为当前用户的主要组名。 |
<mode> | 以UNIX风格表示的该缓存池的权限,权限以八进制数表示,如0755.默认值为0755. |
<limit> | 此池中指令可缓存的最大字节数(聚合),默认情况下,不设置限制。 |
<maxTtl> | 添加到该缓存池的指令的最大生存时间,该值以秒,分,时,天的格式来表示,如120s,30m,4h,2d。有效单位为[smhd]。默认不设最大值,“never”表示没有限制。 |
使用示例
$ hdfs cacheadmin -addPool testCachePool -mode 750 -maxTtl 2h -limit 5000000
Successfully added cache pool testCachePool.
listPools :显示一个或多个缓存池的信息,如name,owner,group,permission等
hdfs cacheadmin -listPools [-stats] [<name>]
参数 | 含义 |
---|---|
-stats | 显示额外的缓存池统计信息 |
<name> | 若指定,则仅列出该缓存池的信息 |
使用示例
$ hdfs cacheadmin -listPools
Found 1 result.
NAME OWNER GROUP MODE LIMIT MAXTTL DEFAULT_REPLICATION
testCachePool hadoop hadoop rwxr-x--- 5000000 000:02:00:00.000 1
$ hdfs cacheadmin -listPools -stats
Found 1 result.
NAME OWNER GROUP MODE LIMIT MAXTTL DEFAULT_REPLICATION BYTES_NEEDED BYTES_CACHED BYTES_OVERLIMIT FILES_NEEDED FILES_CACHED
testCachePool hadoop hadoop rwxr-x--- 5000000 000:02:00:00.000
modifyPool:修改已存在缓存池的元数据信息
hdfs cacheadmin -modifyPool <name> [-owner <owner>] [-group <group>] [-mode <mode>] [-limit <limit>] [-maxTtl <maxTtl>]
参数 | 含义 |
---|---|
<name> | 要修改的缓存池的名称。 |
<owner> | 该缓存池所有者的名称 |
<group> | 缓存池所属的组 |
<mode> | 以UNIX风格表示的该缓存池的权限,权限以八进制数表示 |
<limit> | 在该缓存池内要缓存的最大字节数。 |
<maxTtl> | 添加到该缓存池的指令的最大生存时间。 |
使用示例
$ hdfs cacheadmin -modifyPool testCachePool -group admin -mode 700 -limit 1000000 -defaultReplication 3 -maxTtl 5h
Successfully modified cache pool testCachePool to have group name admin and mode rwx------ and limit 1000000 and replication 3
replication max time-to-live 5h
$ hdfs cacheadmin -listPools
Found 1 result.
NAME OWNER GROUP MODE LIMIT MAXTTL DEFAULT_REPLICATION
testCachePool hadoop admin rwx------ 1000000 000:05:00:00.000
removePoo:删除缓存池。同时会uncache与该缓冲池关联的路径。
hdfs cacheadmin -removePool <name>
参数 | 含义 |
---|---|
<name> | 要删除的缓存池名称 |
使用示例
$ hdfs cacheadmin -removePool testCachePool
Successfully removed cache pool testCachePool.
配置
Native Libraries支持
为了把块文件锁定在内存,DataNode需要依赖本地JNI代码(Linux系统为libhadoop.so,Windows系统为hadoop.dll)。如果需要使用HDFS集中化缓存管理,确保启用了JNI。
配置属性
必选配置
确保下面的配置一定要配置
- dfs.datanode.max.locked.memory
该配置指定了一个DataNode用以缓存的最大内存量(以字节表示)。在类Unix系统上,还需要增加datanode用户的“locked-in-memory size ”ulimit(ulimit-l)以匹配此参数(请参见下面有关OS限制的部分)。设置此值时,请记住,您还需要内存中的空间来存放其他内容,例如数据节点和应用程序JVM堆以及操作系统页缓存。
此设置与Lazy Persist Writes功能共享。数据节点将确保Lazy Persist Writes和集中缓存管理使用的总共内存不超过在 dfs.datanode.max.locked.memory 中配置的数量。
可选配置
下面的配置不是必须要配置的,但是可用以调优
属性名称 | 默认值 | 含义 |
---|---|---|
dfs.namenode.path.based.cache.refresh.interval.ms | 300000 | NameNode使用该参数作为两次子路径缓存扫描之间的时间间隔,单位为毫秒。该参数计算要缓存的块和每个包含一个该块应当缓存的副本的DataNode。该参数默认是300000,即5分钟。 |
dfs.datanode.fsdatasetcache.max.threads.per.volume | 4 | DataNode使用该参数作为缓存新数据时每个卷要用的最大线程数。 |
dfs.cachereport.intervalMsec | 10000 | DataNode使用该参数作为两次发送缓存状态报告给NameNode之间的时间间隔。单位为毫秒。默认10000ms,即10s。 |
dfs.namenode.path.based.cache.block.map.allocation.percent | 0.25 | 分配给已缓存块映射的Java堆内存的百分比。它是一个hash map,使用链式hash。如果缓存块的数目很大,那么map越小,访问速度越慢;map越大,消耗的内存越多。 |
OS限制
如果遇到错误“Cannot start datanode because the configured max locked memory size… is more than the datanode’s available RLIMIT_MEMLOCK ulimit,”,就意味着操作系统对用户可以锁定的内存使用量强加了一个限制,该限制值比配设置的值要低。要修复这个问题,必须调整以使的“ulimit -l”的值与DataNode运行需要的内存值匹配。通常,该值是在/etc/security/limits.conf文件中配置。然而,它也会因用户所用的操心系统和分发版的不同而变化。
当在shell中运行“ulimit -l”命令得到一个比属性dfs.datanode.max.locked.memory设置的更高的值,或者是字符串“ulimited”(表示没有限制)时,表示已经正确配置了该值。值得注意的是,ulimit -l命令通常以KB为单位输出内存锁定限制值,而 dfs.datanode.max.locked.memory 的值必须以字节为单位指定。
这些信息不适用于Windows环境。Windows没有和“ulimit -l”相对应的命令。