负载均衡:一致性哈希解决了哪些问题?

在业务开发中,缓存服务和其他数据服务一样,需要满足高可用性,而高可用最常用的手段就是集群扩展

缓存的集群高可用

目前 Redis 流行的集群方案有 官方 Cluster 方案、twemproxy 代理方案、哨兵模式、Codis 等方案,关于这几种方案的具体应用,我们在下一课时将详细展开讲解。

缓存服务从单点扩展到集群以后,势必会产生缓存数据的分发问题,假设我们的缓存服务器有 3 台,每台缓存的数据是不相同的,那么我们在更新缓存时,该放置在哪台机器上呢?根据 key 获取缓存时,该从哪台服务器上获取?这就涉及缓存的负载均衡策略

关于缓存集群高可用的配置方式,有数据同步和不同步之分。在数据同步的方案下,所有节点之间数据都是一样的,不同节点互为副本,这种方式不需要关心缓存数据的分发,实现了缓存集群的最大可用,但是由于冗余了多份缓存数据,会造成比较多的服务器资源浪费;另外一方面,在更新缓存数据时,还要考虑不同节点之间的一致性。

数据不同步的方案,就是每个缓存节点存储的数据不同,在缓存读写时使用一定的策略进行分发。在实际开发中,大部分都是应用数据不同步的方案,如果需要冗余数据,则可以通过缓存集群主从同步实现。

不同路由方案的扩容问题

在第 22 课时讲解数据库分库分表时,我们分析了数据库分库分表扩容的问题,分库分表以后,当存储节点发生增加或减少时,合理的配置分表策略,可以使得数据迁移最小。

其实不只是数据库,缓存集群也有一样的问题。下面来看一下几种负载均衡策略,以及对应的优缺点。

哈希取模路由

最常见的方式是对缓存数据进行哈希,典型的操作就是通过对缓存 hash(缓存 Key)/ 节点数量。

假设我们有 5 台缓存服务器,伪代码如下:

//获取缓存服务器下标 
public Integer getRoute(String key){ 
int cacheIndex = key.hashcode() % 5; 
return cacheIndex; 
} 

哈希取模的方式,适合对固定数量的缓存集群进行路由,但是对横向扩展不友好。如果缓存机器数量发生变更过,比如从 5 台服务器调整为 10 台服务器,原来的缓存数据无法分配到正确机器,就会出现路由不正确,从而业务请求直接落到数据库上。

一致性哈希

在负载均衡策略中,可以应用一致性哈希,减少节点扩展时的数据失效或者迁移的情况。维基百科对一致性哈希是这么定义的:

一致性哈希是一种特殊的哈希算法。在使用一致性哈希算法后,哈希表槽位数(大小)的改变平均只需要对 K/n 个关键字重新映射,其中 K 是关键字的数量,n 是槽位数量。然而在传统的哈希表中,添加或删除一个槽位几乎需要对所有关键字进行重新映射。

一致性哈希通过一个哈希环实现,Hash 环的基本思路是获取所有的服务器节点 hash 值,然后获取 key 的 hash,与节点的 hash 进行对比,找出顺时针最近的节点进行存储和读取。

以电商中的商品数据为例,假设我们有 4 台缓存服务器:

  • A 服务器,地址 hash 结果是 100

  • B 服务器,地址 hash 结果是 200

  • C 服务器,地址 hash 结果是 300

  • D 服务器,地址 hash 结果是 400

现在有某条数据的 Key 进行哈希操作,得到 200,则存储在 B 服务器;某条数据的 Key 进行哈希操作,得到 260,则存储在 C 服务器;某条数据的 Key 进行哈希操作,得到 500,则存储在 A 服务器。

一致性哈希算法在扩展时,只需要迁移少量的数据就可以。例如,我们刚才的例子中,如果 D 服务器下线,原先路由到 D 服务器的数据,只要顺时针迁移到 A 服务器就可以,其他服务器不受影响,我们只需要移动一台机器的数据即可。

一致性哈希虽然对扩容和缩容友好,但是存在另外一个问题,就很容易出现数据倾斜。

相信你已经考虑到了,假设我们有 A、B、C 一直到 J 服务器,总共 10 台,组成一个哈希环。如果从 F 服务器一直到 J 服务器的 5 个节点宕机,那么这 5 台服务器原来的访问,都会被转移到服务器 A 之上,服务器的流量可能是原来的 5 倍或者更高,直到把服务器 A 打爆,这时候流量继续转移到 B 服务器,就出现我们在第 34 课时提到的缓存雪崩

那么数据倾斜是如何解决的呢? 一个方案就是添加虚拟节点,对服务器节点也进行哈希操作,在整个哈希环上,均匀添加若干个节点。比如 a1 和 a2 都属于 A 节点,b1、b2 都属于 B 节点,这样在哈希时可以平衡各个节点的数据。

另外,在面试中,面试官可能会要求你实现一致性哈希算法。以 Java 为例,可以应用 TreeMap 这个数据结构。

TreeMap 基于红黑树实现,元素默认按照 keys 的自然排序排列,对外开放了一个 tailMap(K fromKey) 方法,该方法可以返回比 fromKey 顺序的下一个节点,大大简化了一致性哈希的实现。这里我就不添加代码了,感兴趣的同学可以去动手模拟实现一下。

总结

本文内容,和你分享了应用缓存集群的知识点,包括集群下的高可用,以及哈希取模和一致性哈希的负载均衡策略。

一致性哈希算法的应用,主要是考虑到分布式系统每个节点都有可能失效,并且新的节点很可能动态地增加进来的情况,如何保证当系统的节点数目发生变化的时候,我们的系统仍然能够对外提供良好的服务。

负载均衡在分布式系统设计中是非常重要的一部分,今天主要关注的是数据路由方案,除了数据路由,负载均衡在 API 网关、分布式服务调用中也非常关键。在服务调用中常用的负载均衡策略还包括轮训、随机,根据响应时间判断等。在你的工作中,有哪些场景用到了负载均衡,又是如何进行应用的呢?欢迎留言进行分享。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/238038.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java 自定义泛型

1、接口的泛型 例如List<数据类型>&#xff0c;在创建接口的时候可以通过传不同的类型&#xff0c;进行使用。 如果需要对一些类型进行一些相同的类似于增删改查的操作&#xff0c;那么可以用泛型来简化&#xff0c;只需要将需要操作的类型传入即可。 需要注意的是泛型…

阿里云赵大川:弹性计算推理解决方案拯救 AIGC 算力危机

云布道师 本篇文章围绕弹性计算推理解决方案 DeepGPU 实例如何支持 Stable Diffusion 文生图推理、Stable Diffusion 推理演示示例等相关话题展开。 赵大川 阿里云弹性计算高级技术专家 GPU 云服务器推理解决方案的提出背景 随着 AIGC 时代的到来&#xff0c;两个重要应用应…

js如何调用iframe页面里的方法

document.getElementById("iframeID").contentWindow.子级页面方法(); <body><h3>父页面</h3><iframe id"iframebb" src"b.html" ></iframe><br><script>function ff(){alert("这里是父页面ff的…

IDEA版SSM入门到实战(Maven+MyBatis+Spring+SpringMVC) -SpringMVC @RequestMapping详解

第一章 RequestMapping详解 RequestMapping注解作用&#xff1a;为指定的类或方法设置相应URL 1.1 RequestMapping注解位置 书写在类上面 作用&#xff1a;为当前类设置映射URL注意&#xff1a;不能单独使用&#xff0c;需要与方法上的RequestMapping配合使用 书写在方法上面 …

vi和vim的区别

目录 一、前言 二、vi/vim 的介绍 三、Vi/Vim 常见指令 四、vi和vim的区别 一、前言 写这篇文章的目的&#xff0c;是为了告诉大家我们如果要在终端下对文本进行编辑和修改可以使用vim编辑器。 Ubuntu 自带了 VI 编辑器&#xff0c;但是 VI 编辑器对于习惯了 Windows 下进…

Python办公自动化 – 日志分析和自动化FTP操作

Python办公自动化 – 日志分析和自动化FTP操作 以下是往期的文章目录&#xff0c;需要可以查看哦。 Python办公自动化 – Excel和Word的操作运用 Python办公自动化 – Python发送电子邮件和Outlook的集成 Python办公自动化 – 对PDF文档和PPT文档的处理 Python办公自动化 – 对…

55 回溯算法解黄金矿工问题

问题描述&#xff1a;你要开发一座金矿&#xff0c;地质学家已经探明了这座金矿中的资源分布&#xff0c;并用大小为m*n的网格grid进行了标注&#xff0c;每个单元格中的整数就表示这一单元格中的黄金数量&#xff1b;如果单元格是空的&#xff0c;那么就是0&#xff0c;为了使…

【pentaho】kettle读取Hive表不支持bigint和timstamp类型解决。

一、bigint类型 报错: Unable to get value BigNumber(16) from database resultset显示kettle认为此应该是decimal类型(kettle中是TYPE_BIGNUMBER或称BigNumber)&#xff0c;但实际hive数据库中是big类型。 修改kettle源码解决&#xff1a; kettle中java.sql.Types到kettle…

MFC使用高速绘图控件high-speed Charting Control绘制柱形图

1. 创建MFC单文档工程BarChartDemo。 2. 在工程文件夹下新建文件夹ChartCtrl,将ChartCtrl源码放入,如下图所示。在工程中添加这些项,项目——添加——现有项,全部添加。 3. 添加一个对话框,ID为IDD_DLG_BAR,类名为CBarDlg。 4. 在对话框中添加Custom Control控件,将控…

【SpringBoot应用篇】【AOP+注解】SpringBoot+SpEL表达式基于注解实现权限控制

【SpringBoot应用篇】【AOP注解】SpringBootSpEL表达式基于注解实现权限控制 Spring SpEL基本表达式类相关表达式表达式模板 SpEL表达式实现权限控制PreAuthAuthFunPreAuthAspectUserControllerSpelParserUtils Spring SpEL Spring 表达式语言 SpEL 是一种非常强大的表达式语言…

cka从入门到放弃

无数次想放弃&#xff0c;最后选择了坚持 监控pod日志 监控名为 foobar 的 Pod 的日志&#xff0c;并过滤出具有 unable-access-website 信息的行&#xff0c;然后将 写入到 /opt/KUTR00101/foobar # 解析 监控pod的日志&#xff0c;使用kubectl logs pod-name kubectl logs…

OSPF面试总结

OSPF 基本特点 属于IGP、LS支持无类域间路由没有环路&#xff08;区域内运行LS、区域间是DV,所以所有的区域要和区域0相连&#xff09;收敛速度快使用组播发送数据 224.0.0.5、224.0.0.6 什么时候用224.0.0.5&#xff1f;支持多条等价路由支持协议报文认证 OSPF路由的计算过程…

Pytorch:torch.nn.utils.clip_grad_norm_梯度截断_解读

torch.nn.utils.clip_grad_norm_函数主要作用&#xff1a; 神经网络深度逐渐增加&#xff0c;网络参数量增多的时候&#xff0c;容易引起梯度消失和梯度爆炸。对于梯度爆炸问题&#xff0c;解决方法之一便是进行梯度剪裁torch.nn.utils.clip_grad_norm_&#xff08;&#xff09…

CMD中文名称修改

会引发的问题 1. jupyter notebook运行出现Bad file descriptor (bundled\zeromq\src\epoll.cpp:100) 2. 用Anaconda或pycharm运行jupyter notebook时候&#xff0c;创建ipynb文件没一会儿就开始报错,且没法运行代码 3. 使用opencv时报错&#xff0c;opencv不支持中文路径&…

Python 爬虫之下载视频(二)

爬取某Y的视频链接和标题 文章目录 爬取某Y的视频链接和标题前言一、基本思路二、程序解析阶段三、程序处理阶段总结 前言 这篇内容就简单给大家写个如何从网页上爬取某B主 主页 页面上所有的视频链接和视频标题。 这篇是基础好好看&#xff0c;下篇会根据这篇的结果做一个批…

如何开发专属花店展示平台小程序?

如今&#xff0c;微信小程序已经成为了花店行业拓展客户资源的重要工具。通过开发一个专属花店小程序&#xff0c;你可以为自己的花店带来更多的曝光和客户资源。那么&#xff0c;如何开发一个专属花店小程序呢&#xff1f;接下来&#xff0c;我们将一步步为你详细讲解。 首先&…

产能过剩的今天,企业的方向在哪里?

随着经济的发展和技术的进步&#xff0c;许多行业都面临着产能过剩的问题。在产能过剩的背景下&#xff0c;企业如何找到新的发展方向&#xff0c;成为了一个亟待解决的问题。本文将探讨产能过剩时代下&#xff0c;企业应该如何寻找新的发展之路。 接下来我们就来看看当今的产…

共建还是对抗?BTC 铭文风波中开发者、矿工与社区的平衡艺术

近期&#xff0c;比特币铭文正加速进入一场争议与危机的漩涡。12 月 6 日&#xff0c;比特币核心开发人员 Luke Dashjr 在 X 表示&#xff0c;铭文&#xff08;Inscriptions&#xff09;正在利用比特币核心客户端 Bitcoin Core 的一个漏洞向区块链发送垃圾信息&#xff0c;Bitc…

MUX VLAN配置

MUX VLAN简介 产生背景 MUX VLAN&#xff08;Multiplex VLAN&#xff09;提供了一种通过VLAN进行网络资源控制的机制。 例如&#xff0c;在企业网络中&#xff0c;企业员工和企业客户可以访问企业的服务器。对于企业来说&#xff0c;希望企业内部员工之间可以互相交流&#…

使用工具类Exectors创建线程池

大型并发项目 不能使用Executors 通过ThreadPoolExector的方式 核心线程配置方式: 计算密集型的任务 核心线程数量 CPU的核数 1 IO密集型的任务 核心线程数量 CPU的核数*2 演示: Callable import java.util.concurrent.Callable;public class MyCallable implements Callab…