HDFS中的集中缓存管理
- 概述
- 用例
- 建筑
- 概念
- 缓存指令
- 缓存池
- cacheadmin命令行界面
- 缓存指令命令
- addDirective
- removeDirective
- removeDirectives
- listDirectives
- 缓存池命令
- addPool
- modifyPool
- removePool
- listPools
- 救命
- 组态
- 本地图书馆
- 配置属性
- 需要
- 可选的
概述
HDFS中的集中式缓存管理是一种显式缓存机制,允许用户指定HDFS缓存的路径。NameNode将与磁盘上具有所需块的DataNode进行通信,并指示它们将块缓存在堆外缓存中。
HDFS中的集中式缓存管理具有许多显着优势。
- 显式锁定可防止经常使用的数据从内存中逐出。当工作集的大小超过主存储器的大小时,这尤其重要,这对于许多HDFS工作负载来说是常见的。
- 由于DataNode缓存由NameNode管理,因此应用程序可以在进行任务放置决策时查询缓存块位置集。将任务与高速缓存的块副本共同定位可提高读取性能。
- 当块被DataNode缓存时,客户端可以使用新的,更高效的零拷贝读取API。由于缓存数据的校验和验证由DataNode完成一次,因此在使用此新API时,客户端可能会产生基本上零开销。
- 集中式缓存可以提高整体集群内存利用率。当依赖于每个DataNode上的OS缓冲区高速缓存时,重复读取块将导致块的所有n个副本被拉入缓冲区高速缓存。借助集中式高速缓存管理, a user can explicitly pin only m of the n replicas, saving n-m memory.
用例
集中式缓存管理对于重复访问的文件非常有用。例如,Hive中经常用于连接的小事实表是缓存的一个很好的候选者。另一方面,缓存一年报告查询的输入可能不太有用,因为历史数据可能只读取一次。
集中式缓存管理对于具有性能SLA的混合工作负载也很有用。缓存高优先级工作负载的工作集可确保它不会争用具有低优先级工作负载的磁盘I / O.
架构
在此体系结构中,NameNode负责协调集群中的所有DataNode堆外缓存。NameNode定期从每个DataNode 接收缓存报告,该报告描述在给定DN上缓存的所有块。NameNode通过在DataNode心跳上搭载缓存和非缓存命令来管理DataNode缓存。
NameNode查询其缓存指令集以确定应缓存哪些路径。缓存指令持久存储在fsimage和edit日志中,可以通过Java和命令行API添加,删除和修改。NameNode还存储一组缓存池,这些缓存池是用于将缓存指令组合在一起以进行资源管理和强制执行权限的管理实体。
NameNode定期重新扫描命名空间和活动缓存指令,以确定需要缓存或缓存哪些块,并将缓存工作分配给DataNode。还可以通过添加或删除缓存指令或删除缓存池等用户操作来触发重新扫描。
我们目前不会缓存正在构建,损坏或不完整的块。如果缓存指令涵盖符号链接,则不缓存符号链接目标。
缓存目前在文件或目录级别上完成。块和子块缓存是未来工作的一个项目。
概念
缓存指令
一个缓存指令定义应该缓存的路径。路径可以是目录或文件。目录以非递归方式缓存,仅表示目录的第一级列表中的文件。
指令还指定其他参数,例如缓存复制因子和到期时间。复制因子指定要缓存的块副本数。如果多个缓存指令引用同一文件,则应用最大缓存复制因子。
到期时间在命令行中指定为生存时间(TTL),即将来的相对到期时间。缓存指令到期后,NameNode在进行缓存决策时不再考虑它。
缓存池
一个高速缓存池是用来管理缓存指令组的管理实体。缓存池具有类似UNIX的权限,这些权限限制哪些用户和组可以访问池。写入权限允许用户向池中添加和删除缓存指令。读取权限允许用户列出池中的缓存指令以及其他元数据。执行权限未使用。
缓存池还用于资源管理。池可以强制执行最大限制,这限制了池中指令可以聚合聚合的字节数。通常,池限制的总和将近似等于为群集上的HDFS缓存保留的聚合内存量。缓存池还会跟踪大量统计信息,以帮助群集用户确定缓存的内容和缓存内容。
池也可以实施最长的生存时间。这限制了添加到池中的指令的最大到期时间。
cacheadmin命令行接口
在命令行上,管理员和用户可以通过hdfs cacheadmin subcommand 与缓存池和指令进行交互。
缓存指令由唯一的,不重复的64位整数ID标识。即使稍后删除了缓存指令,也不会重用ID。
缓存池由唯一的字符串名称标识。
缓存指令命令
addDirective
用法:hdfs cacheadmin -addDirective -path <path> -pool <pool-name> [-force] [-replication <replication>] [-ttl <生存时间>]
添加新的缓存指令。
| |
<path> | 缓存的路径。路径可以是目录或文件。 |
<pool-name> | 要添加指令的池。您必须具有缓存池的写权限才能添加新指令。 |
-force | 跳过检查缓存池资源限制。 |
<replication> | 要使用的缓存复制因子。默认为1。 |
<time-to-live> | 指令有效期多长。可以在几分钟,几小时和几天内指定,例如30米,4小时,2天。有效单位是[smhd]。“never”表示永不过期的指令。如果未指定,则指令永不过期。 |
removeDirective
Usage: hdfs cacheadmin -removeDirective <id>
删除缓存指令。
| |
<id> | 要删除的缓存指令的id。您必须对指令池具有写权限才能将其删除。要查看缓存ID列表,请使用-listDirectives命令。 |
removeDirectives
用法:hdfs cacheadmin -removeDirectives <path>
删除具有指定路径的每个缓存指令。
| |
<path> | 要删除的缓存指令的路径。您必须对指令池具有写权限才能将其删除。要查看缓存指令列表,请使用-listDirectives命令。 |
listDirectives
用法:hdfs cacheadmin -listDirectives [-stats] [-path <path>] [-pool <pool>]
列出缓存指令。
| |
<path> | 仅列出具有此路径的缓存指令。请注意,如果缓存池中存在我们没有读访问权限的路径的缓存指令,则不会列出该指令。 |
<pool> | 仅列出该池中的路径缓存指令。 |
-stats | 列出基于路径的缓存指令统计信息。 |
缓存池命令
addPool
用法:hdfs cacheadmin -addPool <name> [-owner <owner>] [-group <group>] [-mode <mode>] [-limit <limit>] [-maxTtl <maxTtl>]
添加新的缓存池。
| |
<name> | 新池的名称。 |
<owner> | 池所有者的用户名。默认为当前用户。 |
<group> | 集团的游泳池。默认为当前用户的主要组名称。 |
<mode> | 池的UNIX样式权限。权限以八进制指定,例如0755.默认情况下,此值设置为0755。 |
<limit> | 聚合中此池中指令可以缓存的最大字节数。默认情况下,不设置限制。 |
<maxTtl> | 添加到池中的指令允许的最长生存时间。这可以以秒,分钟,小时和天来指定,例如120秒,30米,4小时,2天。有效单位是[smhd]。默认情况下,不设置最大值。值“never”指定没有限制。 |
modifyPool
用法:hdfs cacheadmin -modifyPool <name> [-owner <owner>] [-group <group>] [-mode <mode>] [-limit <limit>] [-maxTtl <maxTtl>]
修改现有缓存池的元数据。
| |
<name> | 要修改的池的名称。 |
<owner> | 池所有者的用户名。 |
<group> | 池组的组名。 |
<mode> | 八进制池的Unix风格权限。 |
<limit> | 此池可以缓存的最大字节数。 |
<maxTtl> | 添加到池中的指令允许的最长生存时间。 |
removePool
用法:hdfs cacheadmin -removePool <name>
删除缓存池。这也解除了与池相关的路径。
| |
<name> | 要删除的缓存池的名称。 |
listPools
用法:hdfs cacheadmin -listPools [-stats] [<name>]
显示有关一个或多个缓存池的信息,例如名称,所有者,组,权限等。
| |
-stats | 显示其他缓存池统计信息。 |
<name> | 如果已指定,则仅列出指定的缓存池。 |
help
用法:hdfs cacheadmin -help <command-name>
获取有关命令的详细帮助。
| |
<command-name> | 获取详细帮助的命令。如果未指定命令,请打印所有命令的详细帮助。 |
组态
本地图书馆
为了将块文件锁定到内存中,DataNode依赖于Windows上的libhadoop.so或hadoop.dll中的本机JNI代码。如果使用HDFS集中式缓存管理,请务必启用JNI。
配置属性
需要
请务必配置以下内容:
- dfs.datanode.max.locked.memory 这决定了DataNode用于缓存的最大内存量。在类Unix系统上,还需要增加DataNode用户的“锁定内存大小”ulimit(ulimit -l)以匹配此参数(请参阅下面的操作系统限制部分)。设置此值时,请记住内存中还需要其他内容空间,例如DataNode和应用程序JVM堆以及操作系统页面缓存。
此设置与Lazy Persist Writes功能共享。数据节点将确保Lazy Persist Writes和Centralized Cache Management使用的组合内存不超过dfs.datanode.max.locked.memory中配置的数量。
可选的
以下属性不是必需的,但可以指定用于调整:
- dfs.namenode.path.based.cache.refresh.interval.ms
NameNode将使用此值作为后续路径缓存重新扫描之间的毫秒数。这将计算要缓存的块以及包含应该缓存它的块的副本的每个DataNode。
默认情况下,此参数设置为30000,即30秒。 - dfs.datanode.fsdatasetcache.max.threads.per.volume
DataNode将此值用作每个卷用于缓存新数据的最大线程数。
默认情况下,此参数设置为4。 - dfs.cachereport.intervalMsec
DataNode将使用此值作为将其缓存状态的完整报告发送到NameNode之间的毫秒数。
默认情况下,此参数设置为10000,即10秒。 - dfs.namenode.path.based.cache.block.map.allocation.percent
我们将分配给缓存块映射的Java堆的百分比。缓存块映射是使用链式散列的哈希映射。如果缓存块的数量很大,则可以更慢地访问较小的映射; 较大的地图会消耗更多的内存。默认值为0.25%。 - dfs.namenode.caching.enabled
此参数可用于在NameNode中启用/禁用集中式缓存。禁用集中式缓存时,NameNode不会处理缓存报告或存储有关群集上的块缓存位置的信息。请注意,NameNode将继续将基于路径的缓存位置存储在文件系统元数据中,即使在启用缓存之前它也不会对此信息起作用。此参数的默认值为true(即启用集中式缓存)。
操作系统限制
如果您收到错误“Cannot start datanode because the configured max locked memory size… is more than the datanode’s available RLIMIT_MEMLOCK ulimit,” ,这意味着操作系统对您可以锁定的内存量施加的下限比您的已配置。要解决此问题,您必须调整DataNode运行的ulimit -l值。通常,此值在/etc/security/limits.conf中配置。但是,它取决于您使用的操作系统和分发版本。
当您可以从shell 运行ulimit -l并获得比使用dfs.datanode.max.locked.memory配置的值更高的值或字符串“unlimited” 时,您将知道已正确配置此值。表明没有限制。请注意,ulimit -l通常以KB为单位输出内存锁限制,但必须以字节为单位指定dfs.datanode.max.locked.memory。
此信息不适用于Windows上的部署。Windows没有直接等效的 ulimit -l。