之间讲过分布式哈希表DHTs,主要运用在这一层。每个节点都会有自己的身份,即NodeID。根据网络距离和延迟情况生成一个Routing Table(路由表),根据对等节点拥有的数据生成DHTs分布式哈希表,该表的key是文件内容的hash值,value是对应存储该数据的节点NodeID。
节点在加入ipfs网络时,会通过种子节点接收到很多其它对等节点信息,本机会连接这些节点,根据ping的时间和节点距离形成路由表。路由表有多个k桶组成,k桶是按本机节点的NodeID位数分布的,比如: 我的节点是01011,k桶的值是5(k=5),那么k桶由近及远的分布是k1:01010;k2:01000、01001;k3:01110、01111、01100、01101;k4:00开头的节点。
然后k桶中的节点再通过ping的延迟时间分为3层,三层分别是20毫秒、60毫秒和高延迟。
节点存数据时,直接将数据存在本地节点ipfs存储库中。设定数据的hash值是key,同时广播给其它离key相近的节点,告诉他们,我保存了key的数据。其它节点就会保存这条信息,形成DHT表,内容是key/value存储,key是数据hash值,value是存储该信息的节点。
所以当某个节点检索key的数据时,首先会在自己的blockstore中查找,如果没有将会在离key最近的k桶中查询,里面的节点会在自己的DHT表中查询,如果存在key的value,则反馈回去,如果没有,会给出离key最近的节点。
IPFS的DSHT结构会根据所存数据的大小值进行区分:小的值(等于或小于1KB)直接存储在DHT上,更大的值,DHT只存储值索引,这个索引就是一个对等节点的NodeId,该对等节点可以提供对该类型值的具体服务,DSHT的接口位于libP2P模块中,如下:
type IPFSRouting interface{
FindPeer (node NodeId)
//gets a particular peer’s network address
//获取特定的节点网络地址
SetValue (key[]bytes, value []bytes)
//stores a small meta data value in DHT
//通过DHT表存储较小的元文件
GetValue (key[]bytes)
//retrieves small meta data value from DHT
//从DHT表中检索元文件
ProvideValue (key Multihash)
//announces this node can serve a large value
//广播该节点可以提供元文件对应的数据
FindValuePeers (key Multihash, min int)
//gets a number of peers serving a large value
//获取提供数据的节点信息
}