您的位置:首页 > 其它

浅谈一致性Hash原理及应用

tiexueyangbiao 2019-01-22 17:25 736 查看 https://www.cnblogs.com/xialih

  在讲一致性Hash之前我们先来讨论一个问题。

  问题:现在有亿级用户,每日产生千万级订单,如何将订单进行分片分表?

  小A:我们可以按照手机号的尾数进行分片,同一个尾数的手机号写入同一片/同一表中。

  大佬:我希望通过会员ID来查询这个会员的所有订单信息,按照手机号分片/分表的话,前提是需要该用户的手机号保持不变,并且在查询订单列表时需要提前查询该用户的手机号,利用手机号尾数不太合理。

  小B:按照大佬的思路,我们需要找出一个唯一不变的属性来进行分片/分表。

  大佬:迷之微笑~

  小B:(信心十足)会员在我们这边保持不变的就是会员ID(int),我们可以通过会员ID的尾数进行分片/分表

  小C:尽然我们可以用会员ID尾数进行分片/分表,那就用取模的方式来进行分片/分表,通过取模的方式可以达到很好的平衡性。示意图如下:

   

1 using System;
2 using System.Collections.Generic;
3 using System.Data.HashFunction;
4 using System.Data.HashFunction.xxHash;
5 using System.Linq;
6
7 namespace HashTest
8 {
9     public class ConsistentHash
10     {
11         /// <summary>
12         /// 虚拟节点数
13         /// </summary>
14         private static readonly int VirturalNodeNum = 10;
15
16         /// <summary>
17         /// 服务器IP
18         /// </summary>
19         private static readonly string[] Nodes = { "192.168.1.1", "192.168.1.2", "192.168.1.3"};
20
21         /// <summary>
22         /// 按照一致性Hash进行分组
23         /// </summary>
24         private static readonly IDictionary<uint, string> ConsistentHashNodes = new Dictionary<uint, string>();
25
26         private static uint[] _nodeKeys = null;
27
28         public static void ComputeNode()
29         {
30             foreach (var node in Nodes)
31             {
32                 AddNode(node);
33             }
34         }
35
36         private static void AddNode(string node)
37         {
38             for (int i = 0; i < VirturalNodeNum; i++)
39             {
40                 var key = node + ":" + i;
41                 var hashValue = ComputeHash(key);
42                 if (!ConsistentHashNodes.ContainsKey(hashValue))
43                 {
44                     ConsistentHashNodes.Add(hashValue, node);
45                 }
46             }
47
48             _nodeKeys = ConsistentHashNodes.Keys.ToArray();
49         }
50
51         private static uint ComputeHash(string virturalNode)
52         {
53             var hashFunction = xxHashFactory.Instance.Create();
54             var hashValue = hashFunction.ComputeHash(virturalNode);
55             return BitConverter.ToUInt32(hashValue.Hash, 0);
56         }
57
58         public static string Get(string item)
59         {
60             var hashValue = ComputeHash(item);
61             var index = GetClockwiseNearestNode(hashValue);
62             return ConsistentHashNodes[_nodeKeys[index]];
63         }
64
65         private static int GetClockwiseNearestNode(uint hash)
66         {
67             int begin = 0;
68             int end = _nodeKeys.Length - 1;
69
70             if (_nodeKeys[end] < hash || _nodeKeys[0] > hash)
71             {
72                 return 0;
73             }
74
75             while ((end - begin) > 1)
76             {
77                 var mid = (end + begin) / 2;
78                 if (_nodeKeys[mid] >= hash) end = mid;
79                 else begin = mid;
80             }
81
82             return end;
83         }
84     }
85 }
View Code  

标签: