kademlia java_分布式哈希表原理与实现(Python版和Java版)
1 //只寫了初始化數據結構、節點加入、節點查詢2 //沒有寫節點的移除,數據的存儲
3
4 IPAddressList.txt5 211.138.116.246
6 128.001.223.111
7 176.002.222.123
8 223.104.160.069
9 112.017.247.082
10 203.069.010.164
11
12
13
14 ?packageDisturbedHashTable;15
16 importjava.io.IOException;17 //測試類
18 public classMainTest {19 public static void main (String[] args) throwsIOException{20 ChordDHT dht = new ChordDHT(6, "F:\\VSCodeProjects\\JavaProjects\\DisturbedHashTable\\IPAddressList.txt");21 dht.printNode();22
23 //測試加入
24 Node node = new Node(6, "242.108.11.31");25 Node curNode = dht.getNode(32);26 dht.joinToRing(curNode, node, 6);27
28 var tmp =node.getSuccessor();29 System.out.printf("\n%d ", node.getIdentifier());30 while(tmp !=node){31 System.out.printf("%d ", tmp.getIdentifier());32 tmp =tmp.getSuccessor();33 }34
35 }36 }37
38 //Chord類
39 packageDisturbedHashTable;40
41 importjava.io.IOException;42 importjava.nio.charset.StandardCharsets;43 importjava.nio.file.Path;44 importjava.util.HashMap;45 importjava.util.Scanner;46
47 /**
48 * 基本信息:49 * 1. Chord 是一個環狀結構50 * 2. 每個節點、鍵值都被映射成了 m 位的標識符51 * 3. 支持查找、插入、移除節點操作52 * 4. 每個節點負責存儲標識符為 (i-1, i] 5. 每個節點都有一個 fingerTable53 *54 * 實現想法:55 * 1. 利用雙向循環鏈表作為環狀結構 (X) 不用鏈表,鏈表不能隨機訪問,用一個 HashMap56 * 2. 標識符空間設置位 6 位57 * 3. 哈希函數將各個節點的IP地址映射成為 6 位的標識符58 * 4. 每個節點還有一個鏈表存儲其負責的標識符和 fingerTable59 *60 */
61
62 public classChordDHT{63 //節點集合,鍵值是其標識符
64 private HashMapnodeSet;65 /**
66 * 構造函數接收兩個參數:67 * m 標識符空間位數68 * srcfile 節點IP地址列表文件69 *70 */
71 public ChordDHT(int m, String srcfile) throwsIOException{72 this.nodeSet = new HashMap();73 Scanner inFile = newScanner(Path.of(srcfile), StandardCharsets.UTF_8);74 Node firstNode = null;75
76 while(inFile.hasNext() == true){ //加入初始節點
77 String ip =inFile.nextLine();78 Node node = newNode(m, ip);79 if(firstNode == null) firstNode =node;80 this.joinToRing(firstNode, node, m);81 }82 inFile.close();83
84 }85
86
87 /**
88 * 處理新節點的加入89 * 除了改變前驅后繼關系,還可能存在key的遷移,90 * 因為這可能會改變某個節點負責的標識符范圍91 *@paramcurNode 當前節點 (受理加入請求的節點)92 *@paramid 請求加入的節點93 *@paramm 標識符空間位數94 *@return是否加入成功95 */
96 public boolean joinToRing(Node curNode, Node id, intm){97
98 //環不為空時 找到id的直接后繼, 并設置相應的域
99 if(this.nodeSet.isEmpty() == false){100 var successor = this.searchNode(curNode, id, m);101 var predecessor =successor.getPredecessor();102 id.setPredecessor(predecessor);103 id.setSuccessor(successor);104 successor.setPredecessor(id);105 predecessor.setSuccessor(id);106 }107 //將節點放入環中, 包含了環為空的情況
108 this.nodeSet.put(id.getIdentifier(), id);109
110 //節點加入后,可能會改變一部分節點的fingerTable
111 for(var node: this.nodeSet.values()){112 this.updateFingerTable(node, m);113 }114 return true;115 }116
117 public void updateFingerTable(Node node, intm){118 for(int i = 0; i < m; i++){ //對表的每一個條目
119 var aIdentifier = ((int)Math.pow(2, i) + node.getIdentifier()) % (int)Math.pow(2, m);120
121 //找到為此標識符負責的節點
122 for(var item: this.nodeSet.values()){123 if(item.inStorageBound(aIdentifier, m) == true){124 node.getFingerTable().put((int)Math.pow(2, i), item);125 break;126 }127 }128 }129 }130
131
132 public Node searchNode(Node curNode, Node id, intm){133 //System.out.println("test searchNode");
134 Node result = null;135 //出口136 //負責id標識符的節點必是id的后繼節點
137 if(curNode.inStorageBound(id.getIdentifier(), m) == true){138 result =curNode;139 }140
141 //遞歸情況
142 else{143 var dis = (id.getIdentifier() - curNode.getIdentifier() + (int)Math.pow(2, m)) % (int)Math.pow(2, m);144 //找到最大的 k 使得 2^k <= dis
145 var maxk = 0;146 while((int)Math.pow(2, maxk) <= dis) maxk++;147 maxk--;148 result = searchNode(curNode.getFingerTable().get((int)Math.pow(2, maxk)), id, m);149 }150 returnresult;151 }152
153 public boolean isIn(intkey){154 returnnodeSet.containsKey(key);155 }156
157 public Node getNode(intkey){158 returnnodeSet.get(key);159 }160
161 public voidprintNode(){162 for(var node: this.nodeSet.values()){163 System.out.printf("identifier is %d, pre is %d, suc is %d\n",164 node.getIdentifier(), node.getPredecessor().getIdentifier(),165 node.getSuccessor().getIdentifier());166 }167 }168 }169
170 //節點類
171 packageDisturbedHashTable;172
173 importjava.sql.Time;174 importjava.util.HashMap;175 importjava.util.Iterator;176 importjava.util.LinkedList;177 importjava.util.Random;178
179 public classNode {180 private intidentifier;181 private HashMap fingerTable; //鍵值為 1,2,4,8,16……
182 private HashMap keyList; //存儲其負責的標識符,String 是 key
183 private Node predecessor; //前驅
184 private Node successor; //后繼
185
186 public Node(intm, String ip){187 //將ip地址映射成m位標識符,生成m個表項目
188 this.identifier =hashFunc(m, ip);189 this.keyList = new HashMap();190 this.fingerTable = new HashMap();191 for(int i = 0; i < m; i++){192 this.fingerTable.put((int)Math.pow(2, i), this);193 }194 this.predecessor = this;195 this.successor = this;196 }197
198 private int hashFunc(intm, String ip){199 Random rd = newRandom(System.currentTimeMillis());200 int result = 0;//rd.nextInt(999999);//增加隨機數,減少碰撞概率
201 for(int i = 0; i < ip.length(); i++){202 if(ip.charAt(i) <= '9' && ip.charAt(i) >= '0') {203 result = (result + (int)ip.charAt(i)) % (int)Math.pow(2, m);204 }205 }206 return result % (int)Math.pow(2, m);207 }208
209 public HashMapgetFingerTable(){210 return this.fingerTable;211 }212
213
214
215 //負責標識符的范圍
216 /**
217 * 這里可能有三種可能:218 * 1. 前驅節點標識符更大(如,23 ---> 1)219 * 2. 前驅節點標識符更小(如,23 ---> 27)220 * 3. 前驅節點標識符一樣大(環中只有一個節點時)221 */
222 public boolean inStorageBound(int aIdentifier, intm){223 var lower = this.predecessor.identifier;224 var upper = this.identifier;225
226 //第一種情況
227 if(lower >upper){228 if(aIdentifier > lower && aIdentifier < (int)Math.pow(2, m)){229 return true;230 }231 if(aIdentifier
236 //第二種情況
237 if(aIdentifier > lower && aIdentifier <=upper){238 return true;239 }240
241 //第三種情況242 //由于只有一個節點,所以它負責所有的標識符
243 if(lower ==upper){244 return true;245 }246
247 return false;248
249 }250
251 public intgetIdentifier(){252 return this.identifier;253 }254
255 publicNode getPredecessor(){256 return this.predecessor;257 }258
259 publicNode getSuccessor(){260 return this.successor;261 }262
263 public booleansetPredecessor(Node node){264 this.predecessor =node;265 return true;266 }267
268 public booleansetSuccessor(Node node){269 this.successor =node;270 return true;271 }272
273 }
總結
以上是生活随笔為你收集整理的kademlia java_分布式哈希表原理与实现(Python版和Java版)的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: java程序math包没有_java.m
- 下一篇: java多个mapreduce_一个简单
