• 一致性Hash算法


    class KetamaNodeLocator
        {
            private Dictionary<long, RedisCluster> ketamaNodes;
            private HashAlgorithm hashAlg;
            private int numReps = 160;
            private long[] keys;
    
            public KetamaNodeLocator(List<RedisCluster> nodes)
            {
                ketamaNodes = new Dictionary<long, RedisCluster>();
    
                //对所有节点,生成nCopies个虚拟结点
                for (int j = 0; j < nodes.Count; j++)
                {
                    RedisCluster node = nodes[j];
                    int numReps = node.Weight;
    
                    //每四个虚拟结点为一组
                    for (int i = 0; i < numReps / 4; i++)
                    {
                        byte[] digest = ComputeMd5(
                            String.Format("{0}_{1}_{2}", node.RoleName, node.RouteValue, i));
    
                        /** Md5是一个16字节长度的数组,将16字节的数组每四个字节一组,
                         * 分别对应一个虚拟结点,这就是为什么上面把虚拟结点四个划分一组的原因*/
                        for (int h = 0; h < 4; h++)
                        {
    
                            long rv = ((long)(digest[3 + h * 4] & 0xFF) << 24)
                                       | ((long)(digest[2 + h * 4] & 0xFF) << 16)
                                       | ((long)(digest[1 + h * 4] & 0xFF) << 8)
                                       | ((long)digest[0 + h * 4] & 0xFF);
    
                            rv = rv & 0xffffffffL; /* Truncate to 32-bits */
                            ketamaNodes[rv] = node;
                        }
                    }
                }
    
                keys = ketamaNodes.Keys.OrderBy(p => p).ToArray();
            }
            public RedisCluster GetWorkerNode(string k)
            {
                byte[] digest = ComputeMd5(k);
                return GetNodeInner(Hash(digest, 0));
            }
    
            RedisCluster GetNodeInner(long hash)
            {
                if (ketamaNodes.Count == 0)
                    return null;
                long key = hash;
                int near = 0;
                int index = Array.BinarySearch(keys, hash);
                if (index < 0)
                {
                    near = (~index);
                    if (near == keys.Length)
                        near = 0;
                }
                else
                {
                    near = index;
                }
    
                return ketamaNodes[keys[near]];
            }
    
            public static long Hash(byte[] digest, int nTime)
            {
                long rv = ((long)(digest[3 + nTime * 4] & 0xFF) << 24)
                        | ((long)(digest[2 + nTime * 4] & 0xFF) << 16)
                        | ((long)(digest[1 + nTime * 4] & 0xFF) << 8)
                        | ((long)digest[0 + nTime * 4] & 0xFF);
    
                return rv & 0xffffffffL; /* Truncate to 32-bits */
            }
    
            public static byte[] ComputeMd5(string k)
            {
                MD5 md5 = new MD5CryptoServiceProvider();
    
                byte[] keyBytes = md5.ComputeHash(Encoding.UTF8.GetBytes(k));
                md5.Clear();
                return keyBytes;
            }
        }
    

      

  • 相关阅读:
    Nginx学习总结(一)
    zabbix3.4.8配置自动发现主机并监控
    Windows server 2012/2016系统安装zabbix3.2客户端
    CentOS7.6系统安装zabbix3.4.8客户端
    一个小爬虫的整体解决方案
    如何通过一个立方体搭建一栋楼
    用Scrapy框架开发的一个爬虫项目
    寻找替代imagemin更好的插件
    原生和es6复杂数组去重的方法
    javascript关于对象或者数组深克隆的写法
  • 原文地址:https://www.cnblogs.com/rainnight/p/4297345.html
Copyright © 2020-2023  润新知