一致性哈希算法在分布式缓存中的应用

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 目的1.介绍一致性hash算法(Consistent Hashing)及其在分布式缓存中的应用,以及对一致性hash算法原理的介绍。2.福利彩蛋应用场景假设我们有一个网站,最近发现随着流量增加,服务器压力越来越大,之前直接读写数据库的方式不太给力了,于是我们想引入Redis作为缓存机制。

目的


1.介绍一致性hash算法(Consistent Hashing)及其在分布式缓存中的应用,以及对一致性hash算法原理的介绍。
2.福利彩蛋

应用场景


假设我们有一个网站,最近发现随着流量增加,服务器压力越来越大,之前直接读写数据库的方式不太给力了,于是我们想引入Redis作为缓存机制。现在我们一共有三台机器可以作为Redis服务器,如下图所示。


img_f3d1363e3c9a7e7da0652247c24e1649.png
分布式缓存示意图.png

要解决的问题


一般来说我们在大规模访问,大并发流量下都会使用到分布式缓存,即将廉价机器部署在同一个子网内,形成多机器集群,然后通过负载均衡以及一定的路由规则进行读请求的分流,将请求映射到
对应的缓存服务器上。如何对请求与缓存服务器之间进行精准映射,以及优雅的扩展,剔除缓存服务器是分布式缓存部署的痛点。
接下来我们会对解决以上问题的一些传统做法进行分析。

1.请求与缓存服务器之间精准映射问题.

  • 最简策略-随机选取:
    含义:将每一次Redis请求随机发送到一台Redis服务器.
    产生的问题:
   1.同一份数据可能被存在不同的机器上而造成数据冗余。
   2.有可能某数据已经被缓存但是访问却没有命中,因为无法保证对相同key的所有访问都被发送到相同的服务器。
     因此,随机策略无论是时间效率还是空间效率都非常不好。
  • 解决保证相同key每次访问同一台Redis服务器-计算哈希:
    含义:保证对相同key的访问会被发送到相同的服务器。
    方案描述:
    对于每次访问,可以按如下算法计算其哈希值:
    h = Hash(key) % 3
    其中Hash是一个从字符串到正整数的哈希映射函数。这样,如果我们将Redis Server分别编号为0、1、2,那么就可以根据上式和key计算出服务器编号h,然后去访问。
    这个方法虽然解决了上面提到的两个问题,但是存在一些其它的问题。如果将上述方法抽象,可以认为通过:
    h = Hash(key) % N
    这个算式计算每个key的请求应该被发送到哪台服务器,其中N为服务器的台数,并且服务器按照0 – (N-1)编号。

2.优雅的扩展,剔除缓存服务器问题
对于根据请求的key进行hash 运算定位Redis缓存服务器产生的问题: 容错性和扩展性将会变得极差.

  • 容错性:指当系统中某一个或几个服务器变得不可用时,整个系统是否可以正确高效运行;
  • 扩展性:指当加入新的服务器后,整个系统是否可以正确高效运行。
    现假设有一台服务器宕机了,那么为了填补空缺,要将宕机的服务器从编号列表中移除,后面的服务器按顺序前移一位并将其编号
    值减一,此时每个key就要按h = Hash(key) % (N-1)重新计算;同样,如果新增了一台服务器,虽然原有服务器编号不用改变,
    但是要按h = Hash(key) % (N+1)重新计算哈希值。因此系统中一旦有服务器变更,大量的key会被
    重定位到不同的服务器从而造成大量的缓存不命中。
    而这种情况在分布式系统中是非常糟糕的。

一个设计良好的分布式哈希方案应该具有良好的单调性,即服务节点的增减不会造成大量哈希重定位。一致性hash算法就是这样一种hash方案。

解决方法-一致性hash算法##


算法简述
一致性哈希算法(Consistent Hashing)最早在论文《Consistent Hashing and Random Trees: Distributed Caching Protocols for Relieving Hot Spots on the World Wide Web》中被提出。简单来说,一致性哈希将整个哈希值空间组织成一个虚拟的圆环,如假设某哈希函数H的值空间为0 - 2的32次方
-1(即哈希值是一个32位无符号整形),整个哈希空间环如下:

img_92ef0168d2db8b89b55ef546ce5a01ea.png
一致性hash函数值空间.png

整个空间按顺时针方向组织。0和232-1在零点中方向重合。

下一步将各个服务器使用H进行一个哈希,具体可以选择服务器的ip或主机名作为关键字进行哈希,这样每台机器就能确定其在哈希环上的位置,这里假设将上文中三台服务器使用ip地址哈希后在环空间的位置如下:

img_f08b762f61baa09eb6d08dcf7b275bf3.png
一致性hash函数值空间 (1).png

接下来使用如下算法定位数据访问到相应服务器:将数据key使用相同的函数H计算出哈希值h,通根据h确定此数据在环上的位置,从此位置沿环顺时针“行走”,第一台遇到的服务器就是其应该定位到的服务器。

例如我们缓存服务器中有A、B、C、D四个key对应的数据对象,经过哈希计算后,在环空间上的位置如下:

img_2814d94f08800ddb3e7697b177eac3db.png
一致性hash函数值空间 (2).png

截止到现在似乎还没有什么觉得神奇的地方,请往下看:
容错性与可扩展性分析
下面分析一致性哈希算法的容错性和可扩展性。现假设Redis-2宕机了:

img_59643cfe53da92c614cd2d9044dbbb9f.png
一致性hash函数值空间 (3).png

我们可以看到ACD节点并不受影响,只有B节点被重定向至Redis-0。

下面考虑另外一种情况,如果我们在系统中增加一台服务器Redis-3 Server:

img_29df1d978033e7a71fec2bdcba691c14.png
一致性hash函数值空间 (4).png

可以发现对于C这个key,重新定位至Redis-3 服务器,其他非C的key均不受影响。

综上所述,一致性哈希算法对于节点的增减都只需重定位环空间中的一小部分数据,具有较好的容错性和可扩展性。

数据倾斜问题


解决办法-虚拟节点
一致性哈希算法在服务节点太少时,容易因为节点分部不均匀而造成数据倾斜问题。例如我们的系统中有两台服务器,其环分布如下:

img_5b45680726c3f2baa29d932a9e4ed9d5.png
一致性hash函数值空间 (5).png

此时必然造成大量数据集中到Redis-1上,而只有极少量会定位到Redis-0上。为了解决这种数据倾斜问题,一致性哈希算法引入了虚拟节点机制,即对每一个服务节点计算多个哈希,每个计算结果位置都放置一个此服务节点,称为虚拟节点。具体做法可以在服务器ip或主机名的后面增加编号来实现。例如上面的情况,我们决定为每台服务器计算三个虚拟节点,于是可以分别计算“Redis-1 #1”、“Redis-1 #2”、“Redis-1 #3”、“Redis-0 #1”、“Redis-0 #2”、“Redis-0 #3”的哈希值,于是形成六个虚拟节点:

img_b92159d8dca58dce9fcfe38f520951b3.png
一致性hash函数值空间 (6).png

同时数据定位算法不变,只是多了一步虚拟节点到实际节点的映射,例如定位到“Redis-1#1”、“Redis-1#2”、“Redis-1#3”三个虚拟节点的数据均定位到Redis-1上。这样就解决了服务节点少时数据倾斜的问题。在实际应用中,通常将虚拟节点数设置为32甚至更大,因此即使很少的服务节点也能做到相对均匀的数据分布。

总结

目前一致性哈希基本成为了分布式系统组件的标准配置,例如Redis的各种客户端都提供内置的一致性哈希支持。本文只是简要介绍了这个算法的思想,以及在分布式应用中的应用场景。

福利彩蛋

职位:腾讯OMG 广告后台高级开发工程师;
Base:深圳;
场景:海量数据,To B,To C,场景极具挑战性。
基础要求:
熟悉常用数据结构与算法;
熟悉常用网络协议,熟悉网络编程;
熟悉操作系统,有线上排查问题经验;
熟悉MySQL,oracle;
熟悉JAVA,GoLang,c++其中一种语言均可;
可内推,欢迎各位优秀开发道友私信[微笑]
期待关注我的开发小哥哥,小姐姐们私信我,机会很好,平台对标抖音,广告生态平台,类似Facebook 广告平台,希望你们用简历砸我~
联系方式 微信 13609184526

博客搬家:大坤的个人博客
欢迎评论哦~

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
16天前
|
存储 算法 安全
分布式系统架构1:共识算法Paxos
本文介绍了分布式系统中实现数据一致性的重要算法——Paxos及其改进版Multi Paxos。Paxos算法由Leslie Lamport提出,旨在解决分布式环境下的共识问题,通过提案节点、决策节点和记录节点的协作,确保数据在多台机器间的一致性和可用性。Multi Paxos通过引入主节点选举机制,优化了基本Paxos的效率,减少了网络通信次数,提高了系统的性能和可靠性。文中还简要讨论了数据复制的安全性和一致性保障措施。
33 1
|
26天前
|
机器学习/深度学习 人工智能 算法
探索人工智能中的强化学习:原理、算法与应用
探索人工智能中的强化学习:原理、算法与应用
|
25天前
|
机器学习/深度学习 算法 数据挖掘
C语言在机器学习中的应用及其重要性。C语言以其高效性、灵活性和可移植性,适合开发高性能的机器学习算法,尤其在底层算法实现、嵌入式系统和高性能计算中表现突出
本文探讨了C语言在机器学习中的应用及其重要性。C语言以其高效性、灵活性和可移植性,适合开发高性能的机器学习算法,尤其在底层算法实现、嵌入式系统和高性能计算中表现突出。文章还介绍了C语言在知名机器学习库中的作用,以及与Python等语言结合使用的案例,展望了其未来发展的挑战与机遇。
39 1
|
25天前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
56 1
|
1月前
|
缓存 NoSQL PHP
Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出
本文深入探讨了Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出。文章还介绍了Redis在页面缓存、数据缓存和会话缓存等应用场景中的使用,并强调了缓存数据一致性、过期时间设置、容量控制和安全问题的重要性。
43 5
|
1月前
|
机器学习/深度学习 监控 算法
基于反光衣和检测算法的应用探索
本文探讨了利用机器学习和计算机视觉技术进行反光衣检测的方法,涵盖图像预处理、目标检测与分类、特征提取等关键技术。通过YOLOv5等模型的训练与优化,展示了实现高效反光衣识别的完整流程,旨在提升智能检测系统的性能,应用于交通安全、工地监控等领域。
|
1月前
|
存储 算法 网络协议
OSPF的SPF算法介绍:原理、实现与应用
OSPF的SPF算法介绍:原理、实现与应用
81 3
|
26天前
|
机器学习/深度学习 人工智能 算法
探索人工智能中的强化学习:原理、算法及应用
探索人工智能中的强化学习:原理、算法及应用
|
5天前
|
存储 缓存 NoSQL
解决Redis缓存数据类型丢失问题
解决Redis缓存数据类型丢失问题
118 85
|
2月前
|
消息中间件 缓存 NoSQL
Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。
【10月更文挑战第4天】Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。随着数据增长,有时需要将 Redis 数据导出以进行分析、备份或迁移。本文详细介绍几种导出方法:1)使用 Redis 命令与重定向;2)利用 Redis 的 RDB 和 AOF 持久化功能;3)借助第三方工具如 `redis-dump`。每种方法均附有示例代码,帮助你轻松完成数据导出任务。无论数据量大小,总有一款适合你。
82 6