一致性hash算法[C#]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace DevelopmentBasicSkill.Hash
{
    /// <summary>
    /// hash算法
    /// </summary>
    public class HashAlgorithm
    {
        //采用MD5 hash算法先构建16个字节的key
        public static byte[] getConsistentKeybyMd5(string host)
        {
            using (var md5 = new MD5CryptoServiceProvider())
            {
                return md5.ComputeHash(Encoding.UTF8.GetBytes(host));
            }
        }

        //4个字节一组=32位
        public static long getHashCode(byte[] arrConsistentKey, int rowpos)
        {
            if (arrConsistentKey == null)
            {
                return 0;
            }
            if (arrConsistentKey.Length != 16)
            {
                return 0;
            }
            if (rowpos < 0 || rowpos > 4)
            {
                return 0;
            }
            long result = ((long)(arrConsistentKey[3 + rowpos * 4] & 0xff) << 24)
                | ((long)(arrConsistentKey[2 + rowpos * 4] & 0xff) << 16)
                | ((long)(arrConsistentKey[1 + rowpos * 4] & 0xff) << 8)
                | ((long)(arrConsistentKey[0 + rowpos * 4] & 0xff) << 0);

            //32位的环
            return result & 0xffffffff;
        }
    }
}

2. ConsistentHash.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DevelopmentBasicSkill.Hash
{
    /// <summary>
    /// 一致性hash算法(包含虚拟节点)
    /// </summary>
    public class ConsistentHash
    {
        /// <summary>
        /// 节点,key映射
        /// </summary>
        private SortedList<long, string> nodeMap = new SortedList<long, string>();

        /// <summary>
        /// 虚拟节点重复个数
        /// </summary>
        private int VirtualNodeCount;

        /// <summary>
        /// 节点列表
        /// </summary>
        private List<string> NodeList;

        public ConsistentHash(List<string> nodelist, int virtualNodeCount)
        {
            VirtualNodeCount = virtualNodeCount;
            NodeList = nodelist;
            init();
        }

        private void init()
        {
            foreach (var node in NodeList)
            {
                //分四组,md5产生16个字节的key,可构建4个int类型的hashcode
                //16*8=4*4*8
                int runCount = VirtualNodeCount / 4;
                for (int i = 0; i < runCount; i++)
                {
                    //16个字节的数据key
                    byte[] hashkey = HashAlgorithm.getConsistentKeybyMd5(node + i);
                    for (int j = 0; j < 4; j++)
                    {
                        nodeMap.Add(HashAlgorithm.getHashCode(hashkey, j), node);
                    }
                }
            }
        }

        /// <summary>
        /// 根据关键字取得host服务器
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public String getHostBykey(string key)
        {
            long consistentkey = HashAlgorithm.getHashCode(HashAlgorithm.getConsistentKeybyMd5(key), 0);
            if (nodeMap.Keys.Contains(consistentkey))
            {
                return nodeMap[consistentkey];
            }
            var result = nodeMap.FirstOrDefault(p => p.Key > consistentkey);
            if (result.Key > 0)
            {
                return result.Value;
            }
            return nodeMap.FirstOrDefault().Value;
        }

    }
}

3.main

using DevelopmentBasicSkill.Hash;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Console_Test
{
    class Program
    {
        static void Main(string[] args)
        {
            //BasicSkillTest.Test();
            //byte[] bts = new byte[] { 1, 2, 3, 4 };
            //Console.WriteLine((long)(bts[3] & 0xff));
            //long num = (long)(bts[3] & 0xff)<<24;

            //Console.WriteLine(num);

            List<string> lstNode = new List<string>();
            lstNode.AddRange(new string[] { "192.168.0.1", "192.168.0.2", "192.168.0.3", "192.168.0.4", "192.168.0.5" });
            ConsistentHash consisHash = new ConsistentHash(lstNode, 160);
            for (int i = 0; i < 1000; i++)
            {
                string word = Guid.NewGuid().ToString();
                Console.WriteLine(i + "\t" + word + ":" + consisHash.getHostBykey(word));
            }

            Console.Read();

        }
    }
}
posted @ 2014-02-19 21:54  少南,无恒  阅读(362)  评论(0编辑  收藏  举报