简介
hdfs中的集中式缓存管理是一种显式缓存机制,允许用户指定hdfs要缓存的路径。namenode将与磁盘上具有所需块的数据节点通信,并指示它们将块缓存在堆外缓存中。
hdfs中的集中式缓存管理具有许多显著的优点。
- 显式固定可防止经常使用的数据从内存中逐出。当工作集的大小超过主内存的大小时,这一点尤其重要,这在许多hdfs工作负载中是常见的。
- 由于datanode缓存由namenode管理,因此应用程序可以在做出任务放置决策时查询缓存块位置集。将任务与缓存块副本一起定位可以提高读取性能。
- 当数据节点缓存了块时,客户机可以使用新的、更高效的、零拷贝读取api。由于缓存数据的校验和验证由datanode完成一次,因此在使用这个新api时,客户机实际上可以产生零开销。
- 集中缓存可以提高集群内存的总体利用率。当依赖于每个数据节点上的操作系统缓冲缓存时,重复读取一个块将导致该块的所有n个副本被拉入缓冲缓存。通过集中的缓存管理,用户只能显式地固定n个副本中的m个副本,从而节省n-m内存。
适用场景
- 集中式缓存管理对于重复访问的文件很有用。例如,hive中经常用于连接的小事实表是缓存的一个很好的候选者。另一方面,缓存一年报表查询的输入可能不太有用,因为历史数据可能只读取一次。
- 集中式缓存管理对于具有性能sla的混合工作负载也很有用。缓存高优先级工作负载的工作集可确保它不会与低优先级工作负载争用磁盘I/O。
架构
在这个架构中,namenode负责协调集群中所有堆外缓存的datanode。namenode定期从每个datanode接收一个缓存报告,该报告描述给定dn上缓存的所有块。namenode通过在datanode 心跳上搭载cache和uncache命令来管理datanode缓存。
namenode查询其缓存指令集,以确定应缓存哪些路径。缓存指令持久存储在fsimage和编辑日志中,可以通过java和命令行api添加、删除和修改。namenode还存储一组缓存池,这些缓存池是用于将缓存指令组合在一起以进行资源管理和强制执行权限的管理实体。
namenode定期重新扫描命名空间和活动缓存指令,以确定哪些块需要缓存或取消缓存,并将缓存工作分配给datanodes。重新扫描也可以由用户操作触发,如添加或删除缓存指令或删除缓存池。
注:
我们目前不缓存正在构造、损坏或不完整的块。如果cache指令覆盖symlink,则不缓存symlink目标。
缓存当前在文件或目录级别完成。块和子块缓存是未来工作的一项。
概念
缓存指令
cache指令定义了应该缓存的路径。路径可以是目录或文件。目录是非递归缓存的,这意味着只有目录的第一级列表中的文件。
指令还指定其他参数,如缓存复制因子和过期时间。
复制因子指定要缓存的块副本数。如果多个缓存指令指向同一个文件,则应用最大缓存复制因子。
到期时间在命令行中指定为生存时间(TTL),即未来的相对到期时间。缓存指令过期后,namenode在做出缓存决策时不再考虑它(不会删除到期的数据?)。
缓存池
缓存池是用于管理缓存指令组的管理实体。缓存池具有类似unix的权限,这些权限限制哪些用户和组可以访问该池。写入权限允许用户向池中添加和删除缓存指令。读取权限允许用户列出池中的缓存指令以及其他元数据。执行权限未使用。
缓存池也用于资源管理。池可以执行最大限制,这限制了池中的指令可以在集合中缓存的字节数。通常,池限制的总和将大致等于为集群上的HDFS缓存保留的聚合内存量。缓存池还跟踪许多统计信息,以帮助群集用户确定缓存的内容和应该缓存的内容。
缓存池也可以强制使用最大的时间。这限制了被添加到池中的指令的最大到期时间。
cacheadmin命令行界面
在命令行中,管理员和用户可以通过hdfs cacheadmin子命令与缓存池和指令交互。
缓存指令由唯一的、不重复的64位整数ID标识。即使稍后删除缓存指令,也不会重用ID。
缓存池由唯一的字符串名称标识。
cache指令命令
addDirective
添加缓存指令。
Usage: 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”表示永不过期的指令。如果未指定,则指令永不过期。 |
removeDirective
删除缓存指令。
Usage: hdfs cacheadmin -removeDirective <id>
< id>:要删除的缓存指令的ID。必须对指令池具有写权限才能将其删除。要查看cachedirective id的列表,请使用-listdirectories命令。
listDirectives
列出缓存指令.
Usage: hdfs cacheadmin -listDirectives [-stats] [-path <path>] [-pool <pool>]
< path>仅列出具有此路径的缓存指令。注意,如果在缓存池中有一个路径的cache指令,而我们没有该指令的读取权限,则不会列出该指令。
< pool>仅列出该池中的路径缓存指令。
-stats列出基于路径的缓存指令统计信息。
Cache pool命令
addPool
添加一个缓存池
Usage: hdfs cacheadmin -addPool <name> [-owner <owner>] [-group <group>] [-mode <mode>] [-limit <limit>] [-maxTtl <maxTtl>]
< name>新池的名称。
< owner>池所有者的用户名。默认为当前用户。
< group>池的组。默认为当前用户的主组名。
< mode>池的Unix样式权限。权限以八进制表示,例如0755。默认情况下,设置为0755。
< limit>可由该池中的指令缓存的最大字节数,总计。默认情况下,不设置限制。
< Max TLL>将被添加到池中的指令的最大允许生存时间。这可以指定为秒、分、小时和天,例如120s、30m、4h、2d。有效单位为[smhd]。默认情况下,没有设置最大值。值“never”指定没有限制。
modifyPool
修改现有缓存池的元数据。
Usage: hdfs cacheadmin -modifyPool <name> [-owner <owner>] [-group <group>] [-mode <mode>] [-limit <limit>] [-maxTtl <maxTtl>]
< name>要修改的池的名称。
< owner>池所有者的用户名。
< group>池组的组名。
< mode>池的Unix风格权限(八进制)。
< limit>可由该池缓存的最大字节数。
< Max TLL>将被添加到池中的指令的最大允许生存时间。
removePool
删除缓存池。这还会取消与池关联的路径的缓存。
Usage: hdfs cacheadmin -removePool <name>
< name>要删除的缓存池的名称。
listPools
显示有关一个或多个缓存池的信息,例如名称、所有者、组、权限等。
Usage: hdfs cacheadmin -listPools [-stats] [<name>]
-stats显示其他缓存池统计信息。
< Name >如果指定,只列出指定的缓存池。
help
获取有关命令的详细帮助。
Usage: hdfs cacheadmin -help <command-name>
< command name>要获取详细帮助的命令。如果未指定命令,请打印所有命令的详细帮助。
配置
本地库
为了将块文件锁定到内存中,datanode依赖于在windows上的libhadoop.so或hadoop.dll中找到的本机jni代码。如果使用hdfs集中式缓存管理,请确保启用jni。
配置属性
Required
请确保配置以下各项:
- dfs.datanode.max.locked.memory内存
这决定了DATOPEN将用于缓存的最大内存量。在类unix系统中,还需要增加datanode用户的“锁定内存大小”ulimit(ulimit-l)以匹配此参数(请参阅下面有关操作系统限制的部分)。设置此值时,请记住,您还需要内存中的空间来存储其他内容,例如datanode和应用程序jvm堆以及操作系统页面缓存。
此设置与延迟持久写入功能共享。数据节点将确保延迟持久化写入和集中缓存管理使用的组合内存不超过dfs.data node.max.locked.memory中配置的数量。
Optional
以下属性不是必需的,但可以指定用于调整:
- dfs.namenode.path.based.cache.refresh.interval.ms
namenode将使用此值作为后续路径缓存重新扫描之间的毫秒数。这将计算要缓存的块以及每个包含应缓存该块的副本的数据节点。
默认情况下,此参数设置为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%。
操作系统限制
如果出现错误: “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的直接等价物。
参考链接:https://hadoop.apache.org/docs/r3.1.2/hadoop-project-dist/hadoop-hdfs/CentralizedCacheManagement.html
来源:CSDN
作者:波哥在路上
链接:https://blog.csdn.net/weixin_43618070/article/details/102831732