一致性哈希算法 mysql_一致性哈希算法 CARP 原理解析, 附 Golang 实现
一致性哈希算法 CARP 原理解析, 附 Golang 实现
在后端服务开发的过程中, 遇到了这样一个问题: 需要在 mysql 前面部署 redis 做一层缓存, 要求 redis 是集群部署, 并且每台 redis 节点只缓存总数据量的 1/N, N 为 redis 的个数.
看到这里大家都能想到到一个方法是使用 hash(key)%N 来选取 redis 进行 value 的存取, 这种方式当然可以很均匀的将数据分配到 N 个 redis 服务上, 并且实现起来也非常的简单. 但是使用这种哈希取余的方式有一个很大的问题, 那就是当 redis 集群扩容或者缩容, 或者发生宕机的时候, 也就是上述公式中的 N 发生变化的时候, 这个时候 hash(key)%N 的值保持不变的概率非常小, 换句话说, 缓存系统会在这种情况下整个失效, 这对于后端的 mysql 来说瞬时压力会非常大, 很可能造成 mysql 的奔溃, 进而造成整个服务的不可用.
所以必须想一种办法来应对上述的情况, 即当一台 redis 服务挂掉的时候, 能不能做到只有 1/N 的缓存失效呢?
答案就是使用一致性哈希算法 CARP, 严格来讲 CARP 并不是一种算法, 而是一种协议, Cache Array Routing Protocol,Cache 群组路由协议. 下面来介绍些下它的工作原理:
首先假设有 N 个 redis 服务, 分别是 redis1, redis2 .... redisN, key 是想要获取的数据在 redis 中的键.
第一步, 计算所有的服务名与 key 的哈希值:
hash_v1 = hash(redis1 + key)
hash_v2 = hash(redis2 + key)
...
hash_vN = hash(redisN + key)
第二步, 计算值最大的 hash_vX, 那么选中的便是 redisX:
hash_vX = max(hash_v1, hash_v2, ..., hash_vN)
为什么这么做就可以达到增加一台 redis 服务的时候, 只有 1/(N+1) 的缓存失效呢?
hash_vX1 = max(hash_v1, hash_v2, ..., hash_vN)
hash_vX2 = max(hash_v1, hash_v2, ..., hash_vN, hash_vN+1)
看上面两个表达式, 如果要求 hash_vX2 大于 hash_vX1, 那么必须 hash_vN+1 大于前面 N 个哈希值, 那么你选取的 hash 函数足够散列的话, hash_vN+1 大于前面 N 个哈希值的概率为 1/(N+1). 你可以自行算一下减少一台 redis 服务时, 缓存失效的概率.
最后, 附上 Golang 实现版本:
package carp
import (
"crypto/md5"
"errors"
)
var (
ErrHaveNoRedis = errors.New("have no redis")
)
// 根据 carp 算法, 从 redisArr 的数组中选择合适的 redis, 返回值为下标
func GetTargetIndex(key string, redisArr []string) (idx int, err error) {
if len(redisArr) < 1 {
return -1, ErrHaveNoTarget
} else if len(redisArr) == 1 {
return 0, nil
}
hashArr := make([]string, len(redisArr))
for k, v := range redisArr {
hashArr[k] = hashString(v + key)
}
idx = minIdx(hashArr)
return
}
// 返回 arr 数组中最小值的下标
func minIdx(arr []string) (idx int) {
if len(arr) < 1 {
return -1
}
idx, min := 0, arr[0]
for k, v := range arr {
if v < min {
idx = k
min = v
}
}
return
}
func hashString(str string) (hash string) {
md5sum := md5.Sum([]byte(str))
return string(md5sum[:])
}
上面的代码中使用了 md5 的哈希算法, 如果你对性能有更高的要求可以使用 FNV 哈希算法.
一致性哈希算法 mysql_一致性哈希算法 CARP 原理解析, 附 Golang 实现相关推荐
- 一致性哈希算法 mysql_一致性哈希算法,在分布式开发中你必须会写,来看完整代码...
今天我想先给大家科普下一致性哈希算法这块,因为我下一篇文章关于缓存的高可用需要用到这个,但是又不能直接在里面写太多的代码以及关于一致性hash原理的解读,这样会失去对于缓存高可用的理解而且会造成文章很 ...
- 一致性哈希算法 mysql_一致性哈希
[TOC] 前言 伴随着系统流量的增大,出现了应用集群.在 Redis 中为了保证 Redis 的高可用也为 Redis 搭建了集群对数据进行分槽存放.在 Mysql数据库要存储的量达到一个很高的地步 ...
- 分布式事务seata只支持MySQL_阿里分布式事务框架Seata原理解析
Seata框架是一个业务层的XA(两阶段提交)解决方案.在理解Seata分布式事务机制前,我们先回顾一下数据库层面的XA方案. 1. MySQL XA方案 MySQL从5.7开始加入了分布式事务的支持 ...
- 【算法】一致性哈希算法原理详解
一.普通 hash 算法 (取模算法): 在了解一致性哈希算法之前,我们先了解一下缓存中的一个应用场景,了解了这个应用场景之后,再来理解一致性哈希算法,就容易多了,也更能体现出一致性哈希算法的优点,那 ...
- 哈希算法——murmurhash一致性哈希算法
Murmurhash: 是一种非加密型哈希函数,适用于一般的哈希检索操作.高运算性能,低碰撞率,由Austin Appleby创建于2008年,现已应用到Hadoop.libstdc++.nginx. ...
- [转]哈希分布与一致性哈希算法简介
哈希分布与一致性哈希算法简介 作者:liunx 来源:http://www.cnblogs.com/liunx/archive/2010/03/24/1693925.html 前言 在我们的日常web ...
- 软考2022高级架构师下午案例分析第4题:关于哈希算法、一致性哈希算法和布隆过滤器
目录 [说明] [问题1] [问题2] [问题3] [说明] 某大型电商平台建立了一个在线 B2B 商店系统,并在全国多地建设了货物仓储中心,通过提前备货的方式来提高货物的运送效率.但是在运营过程中, ...
- 什么是一致性哈希算法?一致性哈希算法原理刨析
一致性哈希算法在1997年由麻省理工学院提出,是一种特殊的哈希算法,目的是解决分布式缓存的问题. 在移除或者添加一个服务器时,能够尽可能小地改变已存在的服务请求与处理请求服务器之间的映射关系.一致性哈 ...
- 【算法】哈希算法——murmurhash一致性哈希算法
Murmurhash: 是一种非加密型哈希函数,适用于一般的哈希检索操作.高运算性能,低碰撞率,由Austin Appleby创建于2008年,现已应用到Hadoop.libstdc++.nginx. ...
最新文章
- iOS自动化测试之Appium的安装和使用
- 初识Tcl(五):Tcl 循环
- Android Crash战斗日记(一、原理篇)
- oracle including new values,物化视图日志加不加INCLUDING NEW VALUES有什么影响
- 2 中ascii函数_C语言编程预备知识--字节、ASCII
- 推荐九种天然食物脑黄金
- VTK:IO之GLTFExporter
- 为什么下载小电影时,经常会卡在99%?
- 将jOOQ与Spring结合使用:排序和分页
- JTable 一个最好的例子
- 2019java形势,2019Java开发还有哪些发展
- opencl初探-sobel检测
- 股票历史数据下载-A股所有股票的历史数据下载
- js使用正则表达式验证身份证格式
- 在服务系统部署MFC程序,出现DLL缺失情况的问题解决方式
- 关于 Burrows-Wheeler 变换和 Lempel-Ziv 解析的一些认识
- MATLAB 查找互素(质)对
- 【数据机构】最短路径之Dijkstra算法(迪克斯特拉算法)
- 测控仪器专业权威期刊
- opencv滤波函数简介
热门文章
- CCF系列题解--2015年3月第三题 节日
- 2015年11月小结
- Android 密码丢了,丢失密钥库密码
- [知识普及]世界知名洋酒
- ImageJ划痕实验分析
- python——人工智能(AI)之网络图片文字识别案例详细讲解
- 一元享移动怎么样_中国移动终于认怂?29元享100G流量还不限速,网友:后悔携号转网了...
- python中 a or b 的值为_若a=1, b=2,那么(a or b)的值为( )。 (2.0分)_学小易找答案...
- python 一个简单的网站采集
- https网站安全证书提示已过期怎么办?