tc_consistent_hash.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /**
  2. * Tencent is pleased to support the open source community by making Tars available.
  3. *
  4. * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
  5. *
  6. * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
  7. * in compliance with the License. You may obtain a copy of the License at
  8. *
  9. * https://opensource.org/licenses/BSD-3-Clause
  10. *
  11. * Unless required by applicable law or agreed to in writing, software distributed
  12. * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  13. * CONDITIONS OF ANY KIND, either express or implied. See the License for the
  14. * specific language governing permissions and limitations under the License.
  15. */
  16. #ifndef __CONSISTENT_HASH__
  17. #define __CONSISTENT_HASH__
  18. #include "util/tc_md5.h"
  19. using namespace std;
  20. namespace tars
  21. {
  22. /////////////////////////////////////////////////
  23. /**
  24. * @file tc_consistent_hash.h
  25. * @brief 一致性hash算法类.
  26. * @brief Consistency hash algorithm class.
  27. */
  28. /////////////////////////////////////////////////
  29. struct node_T
  30. {
  31. /**
  32. *节点hash值
  33. *node hash value
  34. */
  35. unsigned int iHashCode;
  36. /**
  37. *节点下标
  38. *node subscript
  39. */
  40. unsigned int iIndex;
  41. };
  42. /**
  43. * @brief 一致性hash算法类
  44. * @brief Consistency hash algorithm class.
  45. */
  46. class TC_ConsistentHash
  47. {
  48. public:
  49. /**
  50. * @brief 构造函数
  51. * @brief Constructor
  52. */
  53. TC_ConsistentHash()
  54. {
  55. }
  56. /**
  57. * @brief 节点比较.
  58. * @brief Node comparison.
  59. *
  60. * @param m1 node_T类型的对象,比较节点之一
  61. * @param m1 node_T type object, one of the compared nodes
  62. * @param m2 node_T类型的对象,比较节点之一
  63. * @param m2 node_T type object, one of the compared nodes
  64. * @return less or not 比较结果,less返回ture,否则返回false
  65. * @return less or not. The result. If the result is 'less', returns true, else returns false.
  66. */
  67. static bool less_hash(const node_T & m1, const node_T & m2)
  68. {
  69. return m1.iHashCode < m2.iHashCode;
  70. }
  71. /**
  72. * @brief 增加节点.
  73. * @brief the added node
  74. *
  75. * @param node 节点名称
  76. * @param node node name
  77. * @param index 节点的下标值
  78. * @param index the node subscript
  79. * @return 节点的hash值
  80. * @return node hash value
  81. */
  82. unsigned addNode(const string & node, unsigned int index)
  83. {
  84. node_T stItem;
  85. stItem.iHashCode = hash_md5(TC_MD5::md5bin(node));
  86. stItem.iIndex = index;
  87. vHashList.push_back(stItem);
  88. sort(vHashList.begin(), vHashList.end(), less_hash);
  89. return stItem.iHashCode;
  90. }
  91. /**
  92. * @brief 删除节点.
  93. * @brief Delete the node.
  94. *
  95. * @param node 节点名称
  96. * @param node node name
  97. * @return 0 : 删除成功 -1 : 没有对应节点
  98. * @return 0 : delete successfully -1 : no corresponding nodes
  99. */
  100. int removeNode(const string & node)
  101. {
  102. unsigned iHashCode = hash_md5(TC_MD5::md5bin(node));
  103. vector<node_T>::iterator it;
  104. for(it=vHashList.begin() ; it!=vHashList.end(); it++)
  105. {
  106. if(it->iHashCode == iHashCode)
  107. {
  108. vHashList.erase(it);
  109. return 0;
  110. }
  111. }
  112. return -1;
  113. }
  114. /**
  115. * @brief 获取某key对应到的节点node的下标.
  116. * @brief Get the node subscript which corresponds to a certain key.
  117. *
  118. * @param key key名称
  119. * @param key key name
  120. * @param iIndex 对应到的节点下标
  121. * @param iIndex the corresponding node subscript
  122. * @return 0:获取成功 -1:没有被添加的节点
  123. * @return 0:obtain successfully -1:no added nodes
  124. */
  125. int getIndex(const string & key, unsigned int & iIndex)
  126. {
  127. unsigned iCode = hash_md5(TC_MD5::md5bin(key));
  128. if(vHashList.size() == 0)
  129. {
  130. iIndex = 0;
  131. return -1;
  132. }
  133. unsigned low = 0;
  134. unsigned high = vHashList.size();
  135. if(iCode <= vHashList[0].iHashCode || iCode > vHashList[high-1].iHashCode)
  136. {
  137. iIndex = vHashList[0].iIndex;
  138. return 0;
  139. }
  140. while (low < high - 1)
  141. {
  142. unsigned mid = (low + high) / 2;
  143. if (vHashList[mid].iHashCode > iCode)
  144. {
  145. high = mid;
  146. }
  147. else
  148. {
  149. low = mid;
  150. }
  151. }
  152. iIndex = vHashList[low+1].iIndex;
  153. return 0;
  154. }
  155. protected:
  156. /**
  157. * @brief 计算md5值的hash,分布范围在 0 -- 2^32-1.
  158. * @brief Calculate the hash of the MD5 value, and the distribution range is 0--2^32-1.
  159. *
  160. * @param sMd5 md5值
  161. * @param sNd5 md5 value
  162. * @return hash值
  163. * @return hash value
  164. */
  165. unsigned int hash_md5(const string & sMd5)
  166. {
  167. char *p = (char *) sMd5.c_str();
  168. return (*(int*)(p)) ^ (*(int*)(p+4)) ^ (*(int*)(p+8)) ^ (*(int*)(p+12));
  169. }
  170. vector<node_T> vHashList;
  171. };
  172. }
  173. #endif