Hadoop-组件-HDFS-源码学习-数据读写-读文件-短路读
一、概述
二、理论笔记
三、实现
在 DFSClient 中,使用 ShortCircuitReplica 类封装可以进行短路读取的副本。ShortCircuitReplica 对象中包含了短路读取副本的数据块文件输入流、校验文件输入流、短路读取副本在共享内存中的槽位 (slot) 以及副本的引用次数等信息。
![ShortCircuitReplica](https://note3.oss-cn-hangzhou.aliyuncs.com/source/%E6%88%AA%E5%B1%8F2023-01-15%2018.53.54.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,text_d3d3Lnp4Y2hvbWUuY29tCg==,size_36,g_center,color_FFFFFF,shadow_100,t_100,g_se,x_30,y_30)
DFSClient 会持有一个 ShortCircuitCache 对象缓存并管理所有的 ShortCircuitReplica 对象,DFSClient 从 ShortCircuitCache 获得了 ShortCircuitReplica 的引用之后,就可以构造 BlockReaderLocal 对象进行本地读取操作了。
3.1. 短路读共享内存
当 DFSClient 和 Datanode 在同一台机器上时,需要一个共享内存段来维护所有短路读取副本的状态,共享内存段中会有很多个槽位,每个槽位都记录了一个短路读取副本的信息: 例如当前副本是否有效、锚(anchor) 的次数等
什么是锚🤔️~
当 Datanode 将一个数据块副本缓存到内存中时,会将这个数据块副本设置为可锚(anchorable)状态,也就是在共享内存中该副本对应的槽位上设置可锚状态位
请参考 Slot 类实现小节中的分析
当一个副本被设置为可锚状态之后,DFSClient 的 BlockReaderLocal 对象读取该副本时就不再需要校验操作,并且输入流可以通过零拷贝模式读取这个副本。每当客户端进行这两种读取操作时,都需要在副本对应的槽位上添加一个锚计数,只有副本的锚计数为零时,Datanode 才可以从缓存中删除这个副本。可以看到,共享内存以及槽位机制很好地在 Datanode 进程和 DFSClient 进程间同步了副本的状态,保证了 Datanode 缓存操作以及 DFSClient 读取副本操作的正确性。
3.1.1. 申请共享内存
DFSClient 在执行任何短路读取操作之前,需要先申请一段共享内存保存短路读取副本的状态。DFSClient 会调用DataTransferProtocol.requestShortCircuitShm() 方法向 Datanode 发起申请共享内存的请求,Datanode 的DataXceiver.requestShortCircuitShm() 方法会响应这个请求
3.1.2. 申请文件描述符
DFSClient 只有构造了 ShortCircuitReplica 对象才可以执行短路读取操作。DFSClient 在构造 ShortCircuitReplica 对象前,需要先调用 DataTransferProtocol.requestShortCircuitFds()方法向 Datanode 申请数据块文件以及校验和文件的文件描述符,并且同步共享内存中 Slot 对象的状态。客户端在调用 requestShortCircuitFds() 方法前,会在 DFSClient 侧的共享内存中为数据块申请一个槽位并构造 Slot对象,之后在调用 requestShortCircuitFds() 方法时传入该槽位的信息,Datanode 的 DataXceiver.requestShortCircuitFds0方法会响应这个请求。