一致性Hash简单介绍和使用
一致性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简单介绍和使用相关推荐
- 一致性hash 简单实现
一致性hash 简单实现 package com.jackiesteed.algorithms;import java.util.*;/*** 虚拟节点个数需要事先确定好, 而且不能修改.* 核心代码 ...
- Zookeeper的Paxos算法,(2P/3P/CAP/BASE)一致性协议简单介绍
2P/3P提交(为了保证事务的ACID) 2P 就是二段提交(RDBMS经常就这种机制,保证强一致性),3P就是三段提交: 2P提交 -- 1阶段:提交事务请求(投票阶段) ...
- 给面试官讲明白:一致性Hash的原理和实践
戳蓝字"CSDN云计算"关注我们哦! 来源 | 靳刚同学 作者 | 靳刚 "一致性hash的设计初衷是解决分布式缓存问题,它不仅能起到hash作用,还可以在服务器宕机时, ...
- dubbo学习过程、使用经验分享及实现原理简单介绍
一.前言 部门去年年中开始各种改造,第一步是模块服务化,这边初选dubbo试用在一些非重要模块上,慢慢引入到一些稍微重要的功能上,半年时间,学习过程及线上使用遇到的些问题在此总结下. 整理这篇文章差不 ...
- 一致性 Hash 算法的实际应用
前言 记得一年前分享过一篇<一致性 Hash 算法分析>,当时只是分析了这个算法的实现原理.解决了什么问题等. 但没有实际实现一个这样的算法,毕竟要加深印象还得自己撸一遍,于是本次就当前的 ...
- 不会一致性hash算法,劝你简历别写搞过负载均衡
这两天看到技术群里,有小伙伴在讨论一致性hash算法的问题,正愁没啥写的题目就来了,那就简单介绍下它的原理.下边我们以分布式缓存中经典场景举例,面试中也是经常提及的一些话题,看看什么是一致性hash算 ...
- 一致性hash算法_分布式寻址算法
一.分布式寻址算法简介 分布式寻址算法是很重要的内容,不了解这些算法,也就不能透彻的了解各种分布式中间件的原理.简单说一下这些高大上的寻址到底是个啥意思,比如在elasticsearch中,采用的是多 ...
- 一致性hash算法简介
一致性哈希算法在1997年由麻省理工学院提出的一种分布式哈希(DHT)实现算法,设计目标是为了解决因特网中的热点(Hot spot)问题,初衷和CARP十分类似.一致性哈希修正了CARP使用的简单哈希 ...
- 一致性 Hash 在负载均衡中的应用
点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:干掉 Navicat:这个 IDEA 的兄弟真香!个人原创100W+访问量博客:点击前往,查看更多 转自:Mar ...
最新文章
- ASP.NET的状态管理
- SQL CASE WHEN用法
- webpack创建html项目,从零开始其于webpack搭建bootstrap 4项目
- 【Java 虚拟机原理】垃圾回收算法 ( 标记-清除算法 | 复制算法 | 标记-整理算法 )
- ftp 服务器 性能,FTP 服务器性能 测试点
- python爬虫之路scrapy
- shell实现https登录
- vi-vim (十五):显示与设置选项
- VB 共享软件防破解设计技术初探(二)
- 认识 KEGG PATHWAY 数据库
- 深度学习分类问题中accuracy等评价指标的理解
- 安卓一键清理内存_雨点清理app下载-雨点清理下载 v1.0 安卓版
- DT算法(暗像元法)在C6.1中的改进:Aerosol Dark Target (10km 3km) Collection 6.1 Changes
- HDU 2022 海选女主角
- linux 4.8.4开机黑屏,修复多个细节 Linux Kernel 4.8.4发布
- 【爬虫】Selenium爬取动态网页的base64图片
- 跨境人必收藏!掘金新赛道,带你科学开启TikTok Shop英国市场
- BNUZ程协技术部2020寒假任务简单版(后端)
- 无意中发现我这个北漂的几张照片
- boost asio ——深入框架
热门文章
- mysql调优explain_MySql性能调优利器之Explain
- GUI库:PyQt5
- java过滤lsit重复_java 8 中获取List结合中过滤后的重复数据
- python撩妹代码_Python十行代码让你秒变撩妹达人!想学?
- recovery升级是显示进度条_注意!税控系统软件升级了,还有疑问看这里!
- python200行代码小游戏_200 行python 代码实现 2048 游戏
- 有权限的网页能分享内页?_有哪些舍不得分享的办公软件?
- linux sudo 命令权限,linux su和sudo命令的区别
- 织梦编程run=php,dedecms织梦怎么用runphp='yes'运行php
- Spark基础学习笔记05:搭建Spark Standalone模式的集群