惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园_首页
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
P
Proofpoint News Feed
G
Google Developers Blog
B
Blog
Engineering at Meta
Engineering at Meta
阮一峰的网络日志
阮一峰的网络日志
The Register - Security
The Register - Security
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 叶小钗
The Cloudflare Blog
The Hacker News
The Hacker News
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
CXSECURITY Database RSS Feed - CXSecurity.com
雷峰网
雷峰网
F
Fortinet All Blogs
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
H
Hackread – Cybersecurity News, Data Breaches, AI and More
酷 壳 – CoolShell
酷 壳 – CoolShell
Last Week in AI
Last Week in AI
T
Threat Research - Cisco Blogs
A
About on SuperTechFans
量子位
Recorded Future
Recorded Future
博客园 - 三生石上(FineUI控件)
H
Help Net Security
Help Net Security
Help Net Security
P
Palo Alto Networks Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
T
Troy Hunt's Blog
W
WeLiveSecurity
V
Vulnerabilities – Threatpost
T
The Exploit Database - CXSecurity.com
Know Your Adversary
Know Your Adversary
Apple Machine Learning Research
Apple Machine Learning Research
Scott Helme
Scott Helme
N
News | PayPal Newsroom
AWS News Blog
AWS News Blog
D
DataBreaches.Net
Blog — PlanetScale
Blog — PlanetScale
MongoDB | Blog
MongoDB | Blog
B
Blog RSS Feed
腾讯CDC
J
Java Code Geeks
Microsoft Azure Blog
Microsoft Azure Blog
TaoSecurity Blog
TaoSecurity Blog
GbyAI
GbyAI
Y
Y Combinator Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
D
Docker

博客园 - 飘渺峰

.net Parallel并行使用注意事项 析构函数和Dispose方法的区别 查看SQLServer的最大连接数 Hash算法-CityHash算法 Hash算法 Sunday算法--C#版 KMP算法--C#版 BoyerMoore(BM)算法--C# HostFileChangeMonitor [转]软件项目管理总体流程设计 全排列和组合算法 生活 负载均衡算法--C#版 结束进程的方法forceStopPackage 【转】OAUTH协议简介 SQL Server FOR XML PATH 语句的应用 nlog轻量级日志组件 反射加载程序集的几个方法的区别 windows 下TCP最大连接数
一致性Hash算法
飘渺峰 · 2015-02-22 · via 博客园 - 飘渺峰
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;
        }
    }