一致性哈希算法测试(C#)

C# 浅显易懂搞明白,哈希一致性算法的原理与实现, 有图有真相 原理:根据特定的字符串比如5台服务器ip的数组,按照一定放大倍数比如4000倍,哈希映射出20000个哈希值,他们的关系存到ketamaNides数组中,每台服务器,对应相同等份的4000个哈希值, 现在有一批量字符串数据,比如10000条要存进来,如何决定它存到哪台服务器呢? 这个hash值和根据服务器ip映射出来的hash值,可以比较大小, 根据ketamaNodes找到距离最近的一个服务器ip映射出来的hash值,进而知道该服务器名称, 重点是根据hash定义,不管它是什么字 阅读详情

10个Memcached节点,填充100000数据的测试结果如下:

 

192.168.1.199:11211 => 13046
192.168.1.191:11211 => 18230
192.168.1.197:11211 => 6382
192.168.1.194:11211 => 5242
192.168.1.193:11211 => 25554
192.168.1.190:11211 => 1124
192.168.1.196:11211 => 4074
192.168.1.198:11211 => 466
192.168.1.192:11211 => 24652
192.168.1.195:11211 => 1230


Add Server => 192.168.1.200:11211

192.168.1.199:11211 => 13046
192.168.1.191:11211 => 18230
192.168.1.197:11211 => 6382
192.168.1.194:11211 => 5242
192.168.1.193:11211 => 25554
192.168.1.190:11211 => 1124
192.168.1.196:11211 => 4074
192.168.1.198:11211 => 466
192.168.1.200:11211 => 273
192.168.1.192:11211 => 24379
192.168.1.195:11211 => 1230


Delete Server => 192.168.1.193:11211

192.168.1.199:11211 => 13046
192.168.1.191:11211 => 18230
192.168.1.197:11211 => 6382
192.168.1.194:11211 => 5242
192.168.1.190:11211 => 1124
192.168.1.196:11211 => 4074
192.168.1.198:11211 => 466
192.168.1.200:11211 => 273
192.168.1.192:11211 => 24379
192.168.1.195:11211 => 26784

 

单独Memcached节点不要存放太多的数据,一旦出现问题,会出现太多的缓存失效,所以如果发现某个Memcached节点存放了太多的数据,也许应该考虑将数据平衡到其它Memcached节点。

 

//程序代码如下:


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

namespace ConsoleApplication1
{
    static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Hashtable htServers = new Hashtable();

            htServers.Add("192.168.1.190:11211", 0);
            htServers.Add("192.168.1.191:11211", 0);
            htServers.Add("192.168.1.192:11211", 0);
            htServers.Add("192.168.1.193:11211", 0);
            htServers.Add("192.168.1.194:11211", 0);
            htServers.Add("192.168.1.195:11211", 0);
            htServers.Add("192.168.1.196:11211", 0);
            htServers.Add("192.168.1.197:11211", 0);
            htServers.Add("192.168.1.198:11211", 0);
            htServers.Add("192.168.1.199:11211", 0);

            ConsistentHashing ch = new ConsistentHashing(htServers);

            for (int i = 0; i < 100000; ++i)//填充数据
            {
                KeyValuePair<uint, string> Temp = ch.Locate(i.ToString());
                int iCounter = Convert.ToInt32(htServers[Temp.Value]);
                htServers[Temp.Value] = iCounter + 1;//计数器
            }

            IDictionaryEnumerator Iterator0 = htServers.GetEnumerator();
            while (Iterator0.MoveNext())
            {
                Console.WriteLine("{0} => {1}", Iterator0.Key, Iterator0.Value);
            }

            string strAddServer = "192.168.1.200:11211";

            htServers.Add(strAddServer, 0);
            ch.AddServer(strAddServer);

            Console.WriteLine("");
            Console.WriteLine("Add Server => " + strAddServer);
            Console.ReadLine();

            htServers["192.168.1.190:11211"] = 0;
            htServers["192.168.1.191:11211"] = 0;
            htServers["192.168.1.192:11211"] = 0;
            htServers["192.168.1.193:11211"] = 0;
            htServers["192.168.1.194:11211"] = 0;
            htServers["192.168.1.195:11211"] = 0;
            htServers["192.168.1.196:11211"] = 0;
            htServers["192.168.1.197:11211"] = 0;
            htServers["192.168.1.198:11211"] = 0;
            htServers["192.168.1.199:11211"] = 0;
            htServers[strAddServer] = 0;

             for (int i = 0; i < 100000; ++i)
            {
                KeyValuePair<uint, string> Temp = ch.Locate(i.ToString());
                int iCounter = Convert.ToInt32(htServers[Temp.Value]);
                htServers[Temp.Value] = iCounter + 1;
            }

            IDictionaryEnumerator Iterator1 = htServers.GetEnumerator();
            while (Iterator1.MoveNext())
            {
                Console.WriteLine("{0} => {1}", Iterator1.Key, Iterator1.Value);
            }

            string strDeleteServer = "192.168.1.193:11211";

            htServers.Remove(strDeleteServer);
            ch.DeleteServer(strDeleteServer);

            Console.WriteLine("");
            Console.WriteLine("Delete Server => " + strDeleteServer);
            Console.ReadLine();

            htServers["192.168.1.190:11211"] = 0;
            htServers["192.168.1.191:11211"] = 0;
            htServers["192.168.1.192:11211"] = 0;
            //htServers["192.168.1.193:11211"] = 0;
            htServers["192.168.1.194:11211"] = 0;
            htServers["192.168.1.195:11211"] = 0;
            htServers["192.168.1.196:11211"] = 0;
            htServers["192.168.1.197:11211"] = 0;
            htServers["192.168.1.198:11211"] = 0;
            htServers["192.168.1.199:11211"] = 0;
            htServers[strAddServer] = 0;

            for (int i = 0; i < 100000; ++i)
            {
                KeyValuePair<uint, string> Temp = ch.Locate(i.ToString());
                int iCounter = Convert.ToInt32(htServers[Temp.Value]);
                htServers[Temp.Value] = iCounter + 1;
            }

            IDictionaryEnumerator Iterator2 = htServers.GetEnumerator();
            while (Iterator2.MoveNext())
            {
                Console.WriteLine("{0} => {1}", Iterator2.Key, Iterator2.Value);
            }

            Console.ReadLine();
        }
    }

    /// <summary>
    /// 一致性 Hash 算法
    /// </summary>
    class ConsistentHashing
    {
        List<KeyValuePair<uint, string>> _serList = new List<KeyValuePair<uint, string>>();

        public ConsistentHashing(string[] serList)
        {
            if (serList == null || serList.Length == 0)
                return;

            foreach (var ser in serList)
            {
                uint uiKey = Hash(ser);
                _serList.Add(new KeyValuePair<uint, string>(uiKey, ser));
            }
            _serList.Sort((x, y) => x.Key > y.Key ? 1 : (x.Key == y.Key ? 0 : -1));
        }

        public ConsistentHashing(Hashtable htServers)
        {
            IDictionaryEnumerator Iterator = htServers.GetEnumerator();
            while (Iterator.MoveNext())
            {
                uint uiKey = Hash(Iterator.Key.ToString());
                _serList.Add(new KeyValuePair<uint, string>(uiKey, Iterator.Key.ToString()));
            }
            _serList.Sort((x, y) => x.Key > y.Key ? 1 : (x.Key == y.Key ? 0 : -1));
        }

        public void AddServer(string strServer)
        {
            uint uiKey = Hash(strServer);
            _serList.Add(new KeyValuePair<uint, string>(uiKey, strServer));
            _serList.Sort((x, y) => x.Key > y.Key ? 1 : (x.Key == y.Key ? 0 : -1));
        }

        public void DeleteServer(string strServer)
        {
            uint uiKey = Hash(strServer);
            _serList.Remove(new KeyValuePair<uint, string>(uiKey, strServer));
            _serList.Sort((x, y) => x.Key > y.Key ? 1 : (x.Key == y.Key ? 0 : -1));
        }

        /// <summary>
        /// Hash 具体的节点
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public KeyValuePair<uint, string> Locate(string key)
        {
            if (string.IsNullOrEmpty(key))
                return _serList[0];

            var hash = Hash(key);
            var index = _serList.BinarySearch(new KeyValuePair<uint, string>(hash, null), new KeyValuePairComparer());
            if (index >= 0)
                return _serList[index];
            else
            {
                var nIndex = ~index;
                if (nIndex >= _serList.Count)
                    return _serList[0];
                else
                    return _serList[nIndex];
            }
        }
        /// <summary>
        /// 得到字符串的HASH
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        private static uint Hash(string key)
        {
            return BitConverter.ToUInt32(new ModifiedFNV1_32().ComputeHash(Encoding.UTF8.GetBytes(key)), 0);
        }

        /// <summary>
        /// KeyValuePair 比较器实现
        /// 只比对 Key 部分大小
        /// </summary>
        class KeyValuePairComparer
            : IComparer<KeyValuePair<uint, string>>
        {

            #region IComparer<KeyValuePair<uint,string>> 成员
            public int Compare(KeyValuePair<uint, string> x, KeyValuePair<uint, string> y)
            {
                int i = x.Key > y.Key ? 1 : (x.Key == y.Key ? 0 : -1);
                return i;
            }
            #endregion
        }
        #region HASH函数相关
        /// <summary>
        /// 修改版FNV1_32 哈希函数
        /// </summary>
        /// <remarks>
        /// FNV1_32 哈希函数
        /// Fowler-Noll-Vo hash, variant 1, 32-bit version.
        /// http://www.isthe.com/chongo/tech/comp/fnv/
        /// 修改版FNV1_32 哈希函数
        /// Modified Fowler-Noll-Vo hash, 32-bit version.
        /// http://home.comcast.net/~bretm/hash/6.html
        /// </remarks>
        class ModifiedFNV1_32 : HashAlgorithm
        {
            private static readonly uint FNV_prime = 16777619;
            private static readonly uint offset_basis = 2166136261;

            protected uint hash;

            public ModifiedFNV1_32()
            {
                HashSizeValue = 32;
            }

            public override void Initialize()
            {
                hash = offset_basis;
            }

            protected override void HashCore(byte[] array, int ibStart, int cbSize)
            {
                int length = ibStart + cbSize;
                for (int i = ibStart; i < length; i++)
                {
                    hash = (hash * FNV_prime) ^ array[i];
                }
            }

            protected override byte[] HashFinal()
            {
                hash += hash << 13;
                hash ^= hash >> 7;
                hash += hash << 3;
                hash ^= hash >> 17;
                hash += hash << 5;
                return BitConverter.GetBytes(hash);
            }
        }
        #endregion
    }
}

实现一致性哈希算法 一致性哈希算法(Consistent Hashing)是一种常用的分布式哈希算法,用于将数据均匀地分布到多个节点上。它首先计算数据键的哈希值,然后从哈希环上找到大于等于该哈希值的第一个节点。,然后遍历所有节点,并为每个节点生成3个虚拟节点。本文将详细介绍如何使用C#编写一致性哈希算法的实现,包括哈希函数的选择、节点的管理以及数据的路由。方法中,我们使用MD5哈希函数计算输入字符串的哈希值,并将其转换为整数作为节点在哈希环中的位置。用于保存哈希环上的节点信息,其中键表示哈希值,值表示节点名称。 阅读详情

相关推荐

C#实现Consistent Hashing算法 - 完整源代码

具体来说,Consistent Hashing算法可以将多个节点映射到一个环上,每个节点在环上都有一个唯一的位置,而数据则通过哈希函数映射到环上。此外,当系统需要添加或删除节点时,仅需对部分数据进行重分布,而不用重新分配所有数据,因此可以提高系统的可扩展性。本例中采用了哈希表和排序字典来存储节点的位置,对于节点的添加和删除操作,只需更新被影响的部分数据,而不用重新分布所有数据,因此具有较好的可扩展性。下面是测试代码,我们可以通过添加或删除节点来模拟系统扩展或收缩的过程,然后查看数据的分布情况。

DarcyCode的博客 166

一致性Hash算法(KetamaHash)的c#实现

       最近在研究"一致性HASH算法"(Consistent Hashing),用于解决memcached集群中当服务器出现增减变动时对散列值的影响。后来 在JAVAEYE上的一篇文章中,找到了其中的 KetamaHash 算法的JAVA实现(一种基于虚拟结点的HASH算法),于是为了加深理解,对照 JAVA版本,用C#重写了一个。放到这里,如果大家感兴趣的话, 可以下载测试一下,如果发现...

weixin_34102807的博客 274

三分钟看懂一致性哈希算法

另外,这个时候如果只算出三个哈希值,那再跟数据的哈希值比较的时候,很容易分得不均衡,因此就引入了虚拟节点的概念,通过把三个节点加上ID后缀等方式,每个节点算出n个哈希值,均匀的放在哈希环上,这样对于数据算出的哈希值,能够比较散列的分布(详见下面代码中的replica)最关键的区别就是,对节点和数据,都做一次哈希运算,然后比较节点和数据的哈希值,数据取和节点最相近的节点做为存放节点。这样就保证当节点增加或者减少的时候,影响的数据最少。一致性哈希算法,作为分布式计算的数据分配参考,比传统的取模,划段都好很多。

专注基础架构领域 779

探索c#之一致性Hash详解

  阅读目录: 使用场景 算法原理 虚拟节点 代码示例 使用场景 以Redis为例,当系统需要缓存的内容超过单机内存大小时,例如要缓存100G数据,单机内存仅有16G时。这时候就需要考虑进行缓存数据分片,也即是把100G的数据拆分成多块小于单机内存的数据。例如以10G为单位,拆分10份,存储到多台机器节点上。 但是数据怎么个分法更合理呢? 、 f(key)%n 这里配置n...

weixin_34406796的博客 231

C#实现分布式Ketama哈希算法

Ketama哈希算法是一种基于一致性哈希算法的改进版本,其核心思想是通过将多个节点映射到一个环上,在环上均匀分布各个节点,从而保证负载均衡。与简单的一致性哈希算法不同的是,Ketama哈希算法将一个节点在环上对应的位置分成多个虚拟节点,使得每个节点对应多个位置,从而保证均匀性。Ketama哈希算法是一种优秀的哈希算法,它能够在节点数量变化时保持大多数的键值映射不变,因此被广泛应用于分布式系统中。这里需要注意的是,在第1步中生成虚拟节点的数量越多,算法的负载均衡性就越好,但也会增加计算和存储开销。

PixelShadeZ的博客 179

C# 哈希算法集合类库

C# 哈希算法集合类库。集成了很多种哈希算法。方便使用。

C#中的MD5摘要算法与哈希算法

MD5(Message Digest Algorithm 5)是一种广泛使用的密码散列函数,可以产生一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。MD5算法于1991年由Ronald Rivest设计,是被广泛使用的摘要算法之一。MD5算法将输入的消息(任意长)转换成一个固定长度的散列值。在转换过程中,算法会使用一系列的加密操作,如循环移位和异或运算,以生成最终的散列值。

qq_35320456的博客 2296

一致性Hash简单实现

简单模拟实现一致性Hash,透过虚拟节点映射至实际结点,解决一致性Hash的单调性和平衡性问题。

3台服务器扩展到100台,如何避免数据大迁移?一致性哈希给你答案

一致性哈希是分布式系统中解决数据迁移问题的优雅方案。当系统从3台服务器扩展到100台时,传统取模方法会导致几乎所有数据重新分配,而一致性哈希通过环形结构将服务器和数据映射到环上,使数据仅需在相邻节点间迁移。通过引入虚拟节点优化负载均衡,每个服务器创建多个虚拟节点(通常150-200个)实现更均匀分布。该算法广泛应用于Redis、Cassandra等分布式系统,显著减少服务器增减时的数据迁移量(理论迁移量≈1/N)。C#实现示例展示了其高效性,测试显示移除1/3节点时仅迁移25.5%数据,远优于传统方法的全量

DL Forge 577

OpenCvSharp 图像拼接 OpenCV感知哈希算法进行图片相似度对比

利用OpenCvSharp实现感知哈希算法进行图片相似度对比及Stitcher类图像拼接生成全景图像 vs2015环境

kaggle-NeurIPS - Open Polymer Prediction 2025-0.069

本文摘要: 本研究基于多任务学习框架,开发了聚合物物理化学性质预测模型,能够根据SMILES字符串同步预测玻璃化转变温度(Tg)、分数游离体积(FFV)等5种关键性质。针对数据缺失率高、样本不均衡等挑战,采用"先补充后扩充"策略整合多源数据,并融合RDKit分子描述符、ChemBERTa语义特征和自编码器特征构建多维度表征。模型采用硬参数共享架构,结合动态加权损失函数和早停机制,在验证集上表现出色,其中密度预测R²达0.92。研究为聚合物性能的高通量预测提供了有效解决方案,对材料智能设计具有重要参考价值。

2302_78976920的博客 783

C#怎么实现一致性哈希算法_C#如何分配分布式缓存【算法】

必须预分配虚拟节点(比如每个物理节点映射 100 个 vNode),否则节点数少时分布严重不均推荐用 SHA256 或 MurmurHash3(非 GetHashCode)——后者易冲突且跨进程不一致环用 SortedDictionary<long, string> 实现,键是哈希值,值是节点标识(如 "redis-01:6379")GetNodeFor 方法必须处理哈希值“绕环”问题查 key 对应节点时,先算出 keyHash,再在环中找第一个 ≥ keyHash 的节点;

2401_88227372的博客 237

麦克斯韦电磁场理论

1)从知识先后上说:麦克斯韦方程组为理解光的传播、反射、折射等现象提供了理论基础。不理解基础,怎么能理解上层建筑。2)从如何学懂上说,把基础学习的越牢,越深刻,后续学习上层建筑就会水到渠成一些,不会越学越多疑问。而是越学越少疑问。

weixin_55255438的博客 2825

一致性哈希算法(c#版)

  最近在研究"一致性HASH算法"(Consistent Hashing),用于解决memcached集群中当服务器出现增减变动时对散列值的影响。后来 在JAVAEYE上的一篇文章中,找到了其中的 KetamaHash 算法的JAVA实现(一种基于虚拟结点的HASH算法),于是为了加深理解,对照 JAVA版本,用C#重写了一个。放到这里,如果大家感兴趣的话, 可以下载测试一下,如果发现写法有问题...

weixin_33834075的博客 220

用5毫欧采样电阻实现高精度电流检测?数字可调电源控制板的硬件设计陷阱

本文深入探讨了在数字可调电源控制板设计中,如何利用5毫欧采样电阻实现高精度电流检测。从微小信号放大电路设计、采样电阻布局与热管理,到电源切换与电池管理电路优化,提供了全面的硬件设计解决方案和实用技巧,帮助工程师规避常见设计陷阱,提升系统性能。

wdx0123456的博客 1030

团子杂记:SAP收入确认工具RAR(Revenue Recognition&Reporting)在新收入准则下的应用

SAP收入确认工具RAR知识分享

Lucas1211的博客 4284

技术周总结08.12-08.18周日(C#开发环境搭建 & Linux命令)

C#开发环境搭建 & linux常用命令解析

xinkuaile的专栏 1338

带挂牵引车前向运动模型推导及仿真实现

牵引车-半挂车的车辆结构与普通的车辆相比增加了一个半挂车,它们之间通过鞍座相连接,为了分析半挂牵引车运动过程中的位姿和状态,本文将基于车辆的机械结构建立对应的运动学模型,该模型基于以下假设: 车辆行驶过程中,道路平坦且无凸凹; 车辆低速行驶,且运行过程中车身无侧倾和俯仰运动; 车辆行驶过程中,轮胎无形变,无侧向滑动,且无侧向力; 牵引车和半挂车均满足阿克曼转向几何原理; 牵引车与半挂车不会发现折叠。

jianmo的博客 3182

C# 创建一个分布式文件存储系统需要怎么设计??

构建一个分布式文件存储系统是一项复杂的工程任务,涉及到分布式系统理论、网络编程、数据一致性等多个领域的知识。在C#环境下,可以充分利用.NET框架提供的高性能网络和并发处理能力来打造这样一个系统。同时,也需要关注行业标准和最佳实践,确保系统设计既满足业务需求,又能适应未来的发展变化。

560

深入探索 ClickHouse:性能优化之道

在大数据处理的广袤天地里,ClickHouse 宛如一颗璀璨的明星,以其卓越的性能为海量数据的存储与查询提供了强大助力。但要想让 ClickHouse 发挥出极致效能,性能优化至关重要。今天,就让我们一同深入探寻 ClickHouse 的性能优化之路。

arnold66的专栏 1547

手把手教你学simulink(16.10)-- 基于Simulink的IIR滤波器(Infinite Impulse Response Filter)项目

基于Simulink的IIR滤波器(Infinite Impulse Response Filter)项目的详细实例介绍。这个项目将重点放在IIR滤波器的设计、实现和仿真上,帮助你理解和应用IIR滤波器在信号处理中的作用。

MHD0815的博客 706

一致性哈希算法(consistent hashing)样例+測试。

一个简单的consistent hashing的样例,非常easy理解。 首先有一个设备类,定义了机器名和ip: public class Cache { public String name; public String ipAddress; } 然后是基本的实现: public class Shard<T> { //hash 算法并非保证绝对的平衡...

weixin_30550271的博客 81

2024顶级提示工程工具:提升效率的12个神器

LlamaIndex虽然本身不是直接的提示词编辑工具,但其整个设计都围绕着如何有效地将外部知识融入LLM的提示词。它提供了结构化的方式来管理“上下文窗口”——即哪些私有数据应该被包含在提示词中。通过优化索引结构和检索策略,可以确保提示词中包含最相关、最高质量的上下文信息,从而大幅提升LLM基于私有数据回答问题的准确性和相关性。同时,LlamaIndex允许开发者针对不同的查询类型和数据特点定制提示词模板,这使得提示词的复用和优化更加系统化。

AIGC应用创新大全的博客 1098
下一篇: Hbase测试&打补丁(HBASE-5415.patch)
哥是技术人
博客等级 码龄25年 11粉丝 26原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值