本文介绍了HDFS的短路读演进、安全的短路读以及小米在安全短路读的优化。
上篇文章回顾: HDFS Decommission问题分析
背景
Hadoop的一个重要思想就是移动计算,而不是移动数据。我们更愿意尽可能将计算移动到数据所在节点。因此,HDFS中经常出现客户端和数据在一个节点上,当客户端读取一个数据块时,就会出现本地读取。例如HBase场景,ResionServer写数据一般在HDFS中都会存储三备份副本并且肯定会往本地节点写一备份,当ResionServer读取该数据时也会优先选择同一节点的数据进行读取。
短路读的演进
1、网络读
最初,HDFS中本地读取的处理方式和远程读取相同,也是通过网络读来实现。客户端通过TCP套接字连接到DataNode,并通过DataTransferProtocol协议传输数据(如下图):
这种方式简单,但有明显的问题:
DataNode必须为每个正在读取数据块的客户端保留一个线程和一个TCP套接字。内核中会有TCP协议的开销,以及DataTransferProtocol协议的开销,因此这里有很大的优化空间。
2、HDFS-2246 不安全短路读
短路读关键思想是因为客户端和数据块在同一节点上,所以DataNode不需要出现在读取数据路径中。而客户端本身可以直接从本地磁盘读取数据。这样会使读取性能得到很大的提高。在HDFS-2246中实现的短路读是DataNode将所有数据块路径的权限开放给客户端,客户端直接通过本地磁盘路径来读取数据,见下图:
但这种方式引入了很多问题:
(1)系统管理员必须更改DataNode数据目录的权限,以允许客户端打开相关文件。将能够使用短路读的用户专门列入白名单,不允许其他用户使用。通常,这些用户也必须放在特殊的Unix组中。
(2)这些权限更改会引入了一个安全漏洞,具有读取DataNode节点上数据块文件权限的用户可以任意读取路径上所有数据块,而不仅仅是他们所需访问的数据块,这好像让用户变成了超级用户,对于少数用户来说可能是可以接受的,例如HBase用户。但总的来说,它会带来很大安全隐患。
3、HDFS-347 安全短路读
HDFS-2246的主要问题是向客户端打开了DataNode的数据目录,而我们真正需要读取的只是一部分数据块文件。Unix有一种机制是可以做到这一点,称为文件描述符传递。HDFS-347使用这种机制来实现安全短路读。DataNode不是将目录传递给客户端,而是打开块文件和元数据文件,并将它们的文件描述符通过domain socket传递给客户端(如图3):