背景:
一致性Hash用于分布式缓存系统,将Key值映射到详细机器Ip上,而且添加和删除1台机器的数据移动量较小,对现网影响较小

实现:
1 Hash环:将节点的Hash值映射到一个Hash环中。每一个Key顺时针第一个找到的节点。就是这个Key被路由到的机器
2 "虚拟节点":将节点虚拟成多个"虚拟节点"分布在Hash环上,使得分布更均匀。扩缩容影响较小

代码实例:

/** @ 一致性Hash模拟測试* @ 结论:模拟4台机器扩容1台。遍历Key[0,999983]- 一致性Hash需移动181161个Key,约占18%(1/5左右,符合预期效果)- 取模Hash需移动799984个Key,约占80%* @ 2014.05.30 */#include <stdint.h>
#include <iostream>
#include <string.h>
#include <sstream>
#include <map>
#include <vector>
using namespace std;#define HASH_MOD (999983) template <class T>
string ToStr(const T &t)
{stringstream stream;stream << t;return stream.str();
}uint32_t APHash(string &sKey)
{char *key = (char*)sKey.c_str();unsigned int hash = 0;for (int i=0; *key; i++){if ((i & 1) == 0) {hash ^= ((hash<<7)^(*key++)^(hash>>3));} else {hash ^= (~((hash<<11)^(*key++)^(hash>>5)));}}return hash%HASH_MOD;
}class CMyConHash
{
public:/* 加入一台机器(IP) */void AddIp(const string &sIp) {// 每一个IP分配128个虚拟节点,原因:结合APHash实验结果分布较均匀for (int i = 0; i < 128; i ++){string sCode = sIp + ToStr(i) + "#Hash";uint32_t uVirKey = APHash(sCode);mapVirKey2Ip[uVirKey] = sIp;mapIp2VirKey[sIp].push_back(uVirKey);}}/* 删除一台机器(IP) */void DelIp(const string &sIp) {if (mapIp2VirKey.count(sIp) == 0) { cout << "DelIp Err: mapIp2VirKey Don`t Has Ip=" << sIp << endl;return;}vector<uint32_t> vecVirKey = mapIp2VirKey[sIp];for (int i = 0; i < vecVirKey.size(); i ++){uint32_t uVirKey = vecVirKey[i];if (mapVirKey2Ip[uVirKey] == sIp) {// 得推断下。有可能2个IP虚拟节点相等后覆盖了mapVirKey2Ip.erase(uVirKey);}}mapIp2VirKey.erase(sIp);}/* 路由:给每一个Key找到负责的机器(IP) */int FindIp(uint32_t uKey, string &sIp){if (mapVirKey2Ip.size() == 0) {cout << "FindIp Err: mapVirKey2Ip.size() == 0" << endl;return -1;}bool bFind = false;uint32_t uVirKey;map<uint32_t, string>::iterator iter;// 遍历std::map是按Key大小顺序输出(差别std::tr1::unordered_map)for(iter = mapVirKey2Ip.begin(); iter != mapVirKey2Ip.end(); iter ++){uVirKey = iter->first;if (uVirKey > uKey%HASH_MOD) {sIp = iter->second; bFind = true;break;}}if (!bFind) {// 找不到比Key小的虚拟节点,故使用最小的虚拟节点(环)iter = mapVirKey2Ip.begin();uVirKey = iter->first;sIp = iter->second; }//cout << "FindIp Suc:" << uKey%HASH_MOD << "=>" << uVirKey << "," << sIp << endl;return 0;}/* 打印各个IP负责的Key区域大小。影响因素:1 Hash函数 2 虚拟节点个数 *//* 4台机器的情况,相对还是较均匀:Ip=202.168.14.241,Cnt=251649Ip=202.168.14.242,Cnt=257902Ip=202.168.14.243,Cnt=245945Ip=202.168.14.244,Cnt=235516 */void EchoIpState(){map<string, uint32_t> mapIpCnt; map<uint32_t, string>::iterator iter = mapVirKey2Ip.end(); iter --;uint32_t uPreKey = iter->first;string sPreIp = iter->second;do {iter --;uint32_t uVirKey = iter->first;string sIp = iter->second;if (mapIpCnt.count(sPreIp) == 0) {mapIpCnt[sPreIp] = uPreKey-uVirKey;} else {mapIpCnt[sPreIp] += uPreKey-uVirKey;} uPreKey = uVirKey;sPreIp = sIp;} while (iter != mapVirKey2Ip.begin()); cout << "Ip Size=" << mapIpCnt.size() << endl;map<string, uint32_t>::iterator iter1;for(iter1 = mapIpCnt.begin(); iter1 != mapIpCnt.end(); iter1 ++){cout << "Ip=" << iter1->first << ",Cnt=" << iter1->second << endl;}}
private:map< uint32_t, string > mapVirKey2Ip;map< string, vector<uint32_t> > mapIp2VirKey;
};class CMyModHash
{
public: void AddIp(const string &sIp) {vecIpList.push_back(sIp);}void FindIp(uint32_t uKey, string &sIp){sIp = vecIpList[uKey%vecIpList.size()];}void EchoIpState(){cout << "Ip Cnt=" << vecIpList.size() << endl;}
private: vector<string> vecIpList;
};int main()
{CMyConHash oMyHash;// CMyModHash oMyHash;// 模拟初始化4台机器oMyHash.AddIp("202.168.14.241"); oMyHash.AddIp("202.168.14.242"); oMyHash.AddIp("202.168.14.243"); oMyHash.AddIp("202.168.14.244"); oMyHash.EchoIpState();// 保存下各个Key路由的机器 string sIp, arrKeyIp[HASH_MOD];for (uint32_t key = 0; key < HASH_MOD; key ++){oMyHash.FindIp(key, sIp);arrKeyIp[key] = sIp;}// 模拟加入1台机器oMyHash.AddIp("202.168.14.245"); oMyHash.EchoIpState();// 推断多少Key相应数据须要移动机器uint32_t uCnt = 0;for (uint32_t key = 0; key < HASH_MOD; key ++){oMyHash.FindIp(key, sIp);if (arrKeyIp[key] != sIp) {uCnt ++;}}cout << "Key Sum=" << HASH_MOD << " , Need To Move:" << uCnt << endl;return 0;
}

一致性Hash简单介绍和使用相关推荐

  1. 一致性hash 简单实现

    一致性hash 简单实现 package com.jackiesteed.algorithms;import java.util.*;/*** 虚拟节点个数需要事先确定好, 而且不能修改.* 核心代码 ...

  2. Zookeeper的Paxos算法,(2P/3P/CAP/BASE)一致性协议简单介绍

    2P/3P提交(为了保证事务的ACID) 2P 就是二段提交(RDBMS经常就这种机制,保证强一致性),3P就是三段提交: 2P提交 -- 1阶段:提交事务请求(投票阶段)               ...

  3. 给面试官讲明白:一致性Hash的原理和实践

    戳蓝字"CSDN云计算"关注我们哦! 来源 | 靳刚同学 作者 | 靳刚 "一致性hash的设计初衷是解决分布式缓存问题,它不仅能起到hash作用,还可以在服务器宕机时, ...

  4. dubbo学习过程、使用经验分享及实现原理简单介绍

    一.前言 部门去年年中开始各种改造,第一步是模块服务化,这边初选dubbo试用在一些非重要模块上,慢慢引入到一些稍微重要的功能上,半年时间,学习过程及线上使用遇到的些问题在此总结下. 整理这篇文章差不 ...

  5. 一致性 Hash 算法的实际应用

    前言 记得一年前分享过一篇<一致性 Hash 算法分析>,当时只是分析了这个算法的实现原理.解决了什么问题等. 但没有实际实现一个这样的算法,毕竟要加深印象还得自己撸一遍,于是本次就当前的 ...

  6. 不会一致性hash算法,劝你简历别写搞过负载均衡

    这两天看到技术群里,有小伙伴在讨论一致性hash算法的问题,正愁没啥写的题目就来了,那就简单介绍下它的原理.下边我们以分布式缓存中经典场景举例,面试中也是经常提及的一些话题,看看什么是一致性hash算 ...

  7. 一致性hash算法_分布式寻址算法

    一.分布式寻址算法简介 分布式寻址算法是很重要的内容,不了解这些算法,也就不能透彻的了解各种分布式中间件的原理.简单说一下这些高大上的寻址到底是个啥意思,比如在elasticsearch中,采用的是多 ...

  8. 一致性hash算法简介

    一致性哈希算法在1997年由麻省理工学院提出的一种分布式哈希(DHT)实现算法,设计目标是为了解决因特网中的热点(Hot spot)问题,初衷和CARP十分类似.一致性哈希修正了CARP使用的简单哈希 ...

  9. 一致性 Hash 在负载均衡中的应用

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:干掉 Navicat:这个 IDEA 的兄弟真香!个人原创100W+访问量博客:点击前往,查看更多 转自:Mar ...

最新文章

  1. ASP.NET的状态管理
  2. SQL CASE WHEN用法
  3. webpack创建html项目,从零开始其于webpack搭建bootstrap 4项目
  4. 【Java 虚拟机原理】垃圾回收算法 ( 标记-清除算法 | 复制算法 | 标记-整理算法 )
  5. ftp 服务器 性能,FTP 服务器性能 测试点
  6. python爬虫之路scrapy
  7. shell实现https登录
  8. vi-vim (十五):显示与设置选项
  9. VB 共享软件防破解设计技术初探(二)
  10. 认识 KEGG PATHWAY 数据库
  11. 深度学习分类问题中accuracy等评价指标的理解
  12. 安卓一键清理内存_雨点清理app下载-雨点清理下载 v1.0 安卓版
  13. DT算法(暗像元法)在C6.1中的改进:Aerosol Dark Target (10km 3km) Collection 6.1 Changes
  14. HDU 2022 海选女主角
  15. linux 4.8.4开机黑屏,修复多个细节 Linux Kernel 4.8.4发布
  16. 【爬虫】Selenium爬取动态网页的base64图片
  17. 跨境人必收藏!掘金新赛道,带你科学开启TikTok Shop英国市场
  18. BNUZ程协技术部2020寒假任务简单版(后端)
  19. 无意中发现我这个北漂的几张照片
  20. boost asio ——深入框架

热门文章

  1. mysql调优explain_MySql性能调优利器之Explain
  2. GUI库:PyQt5
  3. java过滤lsit重复_java 8 中获取List结合中过滤后的重复数据
  4. python撩妹代码_Python十行代码让你秒变撩妹达人!想学?
  5. recovery升级是显示进度条_注意!税控系统软件升级了,还有疑问看这里!
  6. python200行代码小游戏_200 行python 代码实现 2048 游戏
  7. 有权限的网页能分享内页?_有哪些舍不得分享的办公软件?
  8. linux sudo 命令权限,linux su和sudo命令的区别
  9. 织梦编程run=php,dedecms织梦怎么用runphp='yes'运行php
  10. Spark基础学习笔记05:搭建Spark Standalone模式的集群