学习负载均衡的算法

什么负载均衡

负载均衡是一种计算机技术,用于在多个系统、网络链接、硬盘驱动器、CPU等之间分配工作负载,以优化资源使用、最大化吞吐量、最小化响应时间、并避免任何单一资源的过载。在网络负载均衡的情况下,它可以帮助将网络流量有效地分配到多个服务器。
负载均衡可以在硬件、软件或两者的组合中实现。它通常使用一种算法,如轮询、最少连接、IP哈希或其他自定义方法,来决定将请求发送到哪个服务器。
在微服务架构和大规模并行处理的环境中,负载均衡尤其重要,因为它可以帮助分散大量的请求,并确保系统的稳定性和可靠性。

负载均衡的算法有那些

  1. round-robin (轮询)
  2. random(随机)
  3. ip-hash
  4. power of 2 random choice (两次随机策略)
  5. consistent hash (一致性hash)
  6. consistent hash with bounded (有界一致性hash)
  7. least-load(最小连接)
  8. Weighted Round Robin(权重轮询)

round-robin(轮询)

在这里插入图片描述
i的类型是线程安全的,每次请求i就 +1
hosts 是目标服务器中host的slice,可以存储多个host
每次请求我们的i就会+1然后和host是的长度进行取余来轮询我们的目标服务器的ip。

random(随机)

在这里插入图片描述
rnd 是个随机来源
我们在调用该函数的时候需要先下一个随机种子

	rnd := rand.New(rand.NewSource(time.Now().UnixNano()))

每次我们使用的时候,会根据hosts长度的大小随机一个该长度内的数据来获取一个目标服务器的ip。

ip-hash (ip哈希)

在这里插入图片描述
我们通过代码可以看到,传入进来的client的ip是通过crc32进行了hash计算,算出来一个值以后和hosts的长度进行了取余。
该负责均衡的算法有个好处就是同一个ip的用户访问我们的服务会被分配到同一个目标服务器上。

power of 2 random choice (两次随机策略)

type host struct {
	name string
	load uint64
}

// P2C refer to the power of 2 random choice
type P2C struct {
	sync.RWMutex
	hosts   []*host
	rnd     *rand.Rand
	loadMap map[string]*host
}

// NewP2C create new P2C balancer
func NewP2C(hosts []string) Balancer {
	p := &P2C{
		hosts:   []*host{},
		loadMap: make(map[string]*host),
		rnd:     rand.New(rand.NewSource(time.Now().UnixNano())),
	}

	for _, h := range hosts {
		p.Add(h)
	}
	return p
}

// Add new host to the balancer
func (p *P2C) Add(hostName string) {
	p.Lock()
	defer p.Unlock()
	if _, ok := p.loadMap[hostName]; ok {
		return
	}

	h := &host{name: hostName, load: 0}
	p.hosts = append(p.hosts, h)
	p.loadMap[hostName] = h
}

// Remove new host from the balancer
func (p *P2C) Remove(host string) {
	p.Lock()
	defer p.Unlock()
	if _, ok := p.loadMap[host]; !ok {
		return
	}

	delete(p.loadMap, host)

	for i, h := range p.hosts {
		if h.name == host {
			p.hosts = append(p.hosts[:i], p.hosts[i+1:]...)
			return
		}
	}
}

// Balance selects a suitable host according to the key value
func (p *P2C) Balance(key string) (string, error) {
	p.RLock()
	defer p.RUnlock()

	if len(p.hosts) == 0 {
		return "", NoHostError
	}

	n1, n2 := p.hash(key)
	host := n2
	if p.loadMap[n1].load <= p.loadMap[n2].load {
		host = n1
	}
	return host, nil
}

func (p *P2C) hash(key string) (string, string) {
	var n1, n2 string
	if len(key) > 0 {
		saltKey := key + Salt
		n1 = p.hosts[crc32.ChecksumIEEE([]byte(key))%uint32(len(p.hosts))].name
		n2 = p.hosts[crc32.ChecksumIEEE([]byte(saltKey))%uint32(len(p.hosts))].name
		return n1, n2
	}
	n1 = p.hosts[p.rnd.Intn(len(p.hosts))].name
	n2 = p.hosts[p.rnd.Intn(len(p.hosts))].name
	return n1, n2
}

// Inc refers to the number of connections to the server `+1`
func (p *P2C) Inc(host string) {
	p.Lock()
	defer p.Unlock()

	h, ok := p.loadMap[host]

	if !ok {
		return
	}
	h.load++
}

// Done refers to the number of connections to the server `-1`
func (p *P2C) Done(host string) {
	p.Lock()
	defer p.Unlock()

	h, ok := p.loadMap[host]

	if !ok {
		return
	}

	if h.load > 0 {
		h.load--
	}
}

我们看到(两次随机策略)的算法和ip-hash一样都是使用crc32的hash算法,只不过ip-hash是对key 进行一次hash然后于hosts的长度进行取余,但是(两次随机策略)是对同一个key进行两次hash,一次是用key直接进行hash,另外一次是对key加盐之后进行hash,这时候就求出来两个值,然后在hosts里面获取两个ip,然后对比他们的连接数,取最小连接数。

我们还发现当我们传入的key是个空值的时候,(两次随机策略)使用的随机策略。

Inc 方法和Done方法是在我们进行访问的时候会对连接的ip进行连接数的加减。

consistent hash (一致性hash)

在学习算法之前我们需要先学习下一致性hash

什么是一致性hash

一致性哈希(Consistent Hashing)是一种特殊的哈希技术,广泛应用于分布式系统中,用于解决数据的分布式存储问题。

在传统的哈希表中,如果哈希空间的大小发生变化(例如,增加或减少服务器),几乎所有的键值对都需要重新映射,这会导致大量的数据迁移,对系统的性能和稳定性产生影响。

一致性哈希通过引入虚拟节点和环形哈希空间的概念,使得哈希空间的大小变化时,只有一小部分的键值对需要重新映射。这大大减少了数据迁移的数量,提高了系统的稳定性。

一致性hash解决什么问题

一致性哈希(Consistent Hashing)主要解决分布式系统中的数据分布和负载均衡问题。

一致性哈希通过创建一个环形的哈希空间,并将节点和数据都映射到这个空间上,使得节点数量的变化只会影响哈希空间中的一小部分数据,大大减少了数据重新分配的数量。这使得一致性哈希非常适合动态变化的系统。

一致性哈希还可以通过引入虚拟节点来解决数据分布不均的问题。通过为每个节点创建多个虚拟节点,可以使得数据更均匀地分布在各个节点上,从而实现更好的负载均衡。

原理

在传统的哈希表中,如果哈希空间的大小发生变化,几乎所有的键值对都需要重新映射,这会导致大量的数据迁移,对系统的性能和稳定性产生影响。

但是一致性哈希通过引入虚拟节点和环形哈希空间的概念,使得哈希空间的大小变化时,只有一小部分的键值对需要重新映射。这大大减少了数据迁移的数量,提高了系统的稳定性。

一致性hash算法是对232 进行取模运算,是一个固定的值。通过和232 次进行取模运算的结果值组织成一个圆环。所以,一致性哈希是指将「存储节点」和「数据」都映射到一个首尾相连的哈希环上。
在这里插入图片描述
在hash 环上的结果的映射是顺时针方向第一个节点。
在这里插入图片描述
如果hash环上增加了节点,并不会想传统hash一样发生大量数据迁移的情况从而造成(hash洪水),而是只有部分数据会发生迁移。
在这里插入图片描述
但是一般的hash环会有个节点分布不均匀的问题,这样会导致如会有大量的数据或请求指向同一个节点上去。
在这里插入图片描述
为了解决这个问题我们在hash环上引入虚拟节点来均衡实体节点在hash环上分布不均匀的问题。
在这里插入图片描述
这时候节点数量多了以后,节点在hash环上的分布就均匀了。
在这里插入图片描述
我们看一致性hash负载均衡的类,里面有hash一致性的函数。
在这里插入图片描述
在这里插入图片描述

我们在调用一致性hash的add的时候我们看源码发现,针对每个host我们会创建10个虚拟的因子来加入到hash环上。
在这里插入图片描述
在这里插入图片描述
当我们在发送请求的时候通过我们client ip去获取对应的server ip
在这里插入图片描述
这里我们需要看下c.hash这个方法

  1. blake2b.Sum512:这一行代码将key转换为一个字节切片,然后使用BLAKE2b哈希算法计算其512位(64字节)的哈希值。BLAKE2b是一种密码学哈希函数,可以生成不同长度的哈希值,这里生成的是512位的哈希值。计算结果被存储在out中。、
  2. binary.LittleEndian.Uint64(out[:]):这一行代码将out的前8个字节(64位)解释为一个小端格式的无符号整数。

在这里插入图片描述
我们在看下search函数,该函数使用key计算出来的hash的值和hash环中的值进行比较,并返回index。
在这里插入图片描述
我们通过上面函数返回的index获取到hash环中的对应的hash值,在冲hosts中获取到对应的服务器ip。

consistent hash with bounded (有界一致性hash)

在这里插入图片描述

什么是有界一致性hash

有界一致性哈希(Bounded Load Consistent Hashing)是一致性哈希的一个改进版本,它在一致性哈希的基础上增加了负载均衡的考虑。

在传统的一致性哈希中,虽然理论上数据会均匀地分布在各个节点上,但在实际应用中,由于哈希函数的随机性,可能会出现某些节点上数据过多,而某些节点上数据过少的情况,这被称为"哈希倾斜"。

有界一致性哈希通过引入一个负载因子的概念来解决这个问题。每个节点都有一个负载因子,表示该节点当前承载的数据量。当一个新的数据项需要被插入时,它不仅会考虑哈希环上的位置,还会考虑各个节点的负载因子,优先选择负载因子较小的节点。

这样,有界一致性哈希不仅保持了一致性哈希的优点(如高可用性和可扩展性),还提高了系统的负载均衡性,使得数据在各个节点之间的分布更加均匀。

在这里插入图片描述
有界一致性hash 其实和一致性的hash的添加方式是一样的,不一样是不一样在获取和请求的时候,有界一致性hash多了一个对ip负载的统计,不废话上代码。
在这里插入图片描述

在这里插入图片描述

  1. Inc是对我们请求的servic ip进行负载的原子操作+1
  2. Done是在我们对service ip 请求结束后的进行负载的原子操作-1

在这里插入图片描述
通过ip获取到服务器的service ip ,接下来我们看看GetLeast
在这里插入图片描述
在这里插入图片描述
hash和search这两个函数我们在一致性hash的时候解读过了,这里我们看看loadOk 这个函数,这个函数是来比较每个节点的平均负载,获取最小负载的host

通过代码我们可以看出我们要获取到负载小于平均负载的host

我们看到代码中*1.25 为什么这样作呢,是为了引入一个负载因子,使得每个节点可以接受稍微超过平均负载的请求。

乘以1.25就是为了给每个节点提供一些额外的容量,允许其负载稍微超过平均负载,以应对这种情况。这样可以提高系统的灵活性和鲁棒性,使得在节点的负载稍微超过平均负载时,系统仍能正常工作,而不是立即拒绝新的请求。

least-load(最小连接)

“Least Load” 是一种负载均衡策略,其目标是将新的请求分配给当前负载最小的服务器。这种策略可以帮助确保所有的服务器都能得到充分利用,同时避免某些服务器过载。

该策略使用了斐波那契堆来实现

斐波那契堆(Fibonacci Heap)是一种优先队列数据结构,它支持一系列操作,如插入、获取最小值、合并等,具有很好的理论性能。斐波那契堆在图算法(如 Dijkstra 和 Prim)中特别有用,因为它可以更有效地处理减少关键字的操作。

斐波那契堆的特点是:

  • 它是一组最小堆有序树的集合,这些树都满足斐波那契堆的性质(即,每个节点的孩子数大于或等于其父节点的秩)。
  • 它有一个指针指向最小元素。
  • 它的所有操作(插入、删除最小元素、减少关键字、合并两个堆)都有很好的平摊时间复杂度。

在这里插入图片描述
我们在使用该策略的时候发现host让存入了斐波那契堆里面。该堆里面还记录了每个host的负载。
在这里插入图片描述
我们在每次请求的时候通过client ip 获取对应的host,但是在请求的时候会堆该host进行负载+1,请求结束以后会进行负载 -1
在这里插入图片描述
所以我们在获取service ip的时候就非常方便的从该堆里面获取到负载最小的ip,防止我们某个服务器过载。
在这里插入图片描述
我们在初始化该策略的时候会将host 通过斐波那契堆的insert存入到该堆的节点里面。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们在请求的时候需要堆host进行负载的加减,这两个函数是通过递归的形式对堆里面的元素进行操作的。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

WebAPI [Swagger] 发布ISS不能生成xml文件问题记录

因为Swagger文件的注释是读取项目xml的。 除了Debug要输出xml&#xff0c;正式发布release时也要输出xml

Camtasia2024试用版最新核心功能介绍

Camtasia的试用版通常提供与正式版本相同的核心功能&#xff0c;但可能会有一些限制或水印。以下是试用版中可能包含的一些功能&#xff1a; 屏幕录制&#xff1a;试用版允许用户录制电脑屏幕上的活动&#xff0c;无论是全屏、特定区域还是特定窗口。用户可以选择录制光标、添加…

LeetCode LCR 055.二叉搜索树迭代器

实现一个二叉搜索树迭代器类BSTIterator &#xff0c;表示一个按中序遍历二叉搜索树&#xff08;BST&#xff09;的迭代器&#xff1a; BSTIterator(TreeNode root) 初始化 BSTIterator 类的一个对象。BST 的根节点 root 会作为构造函数的一部分给出。指针应初始化为一个不存在…

基于PID-bang-bang控制算法的卫星姿态控制matlab仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 基于PID-bang-bang控制算法的卫星姿态控制。仿真输出控制器的控制收敛曲线&#xff0c;卫星姿态调整过程的动画。 2.系统仿真结果 3.核心程序与模型 版本&#xff1a;MATLAB…

c语言经典测试题3

1.题1 int a 248, b 4; int const *c 21; const int *d &a; int *const e &b; int const * const f &a; 请问下列表达式哪些会被编译器禁止&#xff1f; A: *c 32; B: *d 43 C: e&a D: f0x321f 我们来分析一下&#xff1a;const用来修饰变量是想其…

Kotlin filterIsInstance filterNotNull forEach

Kotlin filterIsInstance filterNotNull forEach fun main(args: Array<String>) {val i1 MyItem(1, 1)val i2: MyItem? nullval i3: Int 3val i4 "4"val i5 nullval i6 MyItem(6, 6)val list mutableListOf<Any?>(i1, i2, i3, i4, i5, i6)lis…

百度地图海量点方案趟坑记录(百度地图GL版 + MapVGL + vue3 + ts)

核心需求描述 不同层级有不同的海量图标展示底层海量图标需要展示文字拖动、放大缩小都需要重新请求数据并展示固定地图中心点&#xff08;拖动、放大缩小&#xff0c;中心点始终在地图中心&#xff09; 示例图片&#xff1a;&#xff08;某些图片涉及公司数据&#xff0c;就未…

靡语IT:Vue精讲(一)

Vue简介 发端于2013年的个人项目&#xff0c;已然成为全世界三大前端框架之一&#xff0c;在中国大陆更是前端首选。 它的设计思想、编码技巧也被众多的框架借鉴、模仿。 纪略 2013年&#xff0c;在Google工作的尤雨溪&#xff0c;受到Angular的启发&#xff0c;从中提取自…

unity学习(30)——跳转到角色选择界面(跳转新场景)

1.在scene文件夹中&#xff08;[siːn]&#xff09;&#xff0c;右键->create->scene&#xff0c;名字叫SelectMenu&#xff08;选择角色场景&#xff09;。 2.把新建场景拖拽到hierarchy[ˈhaɪərɑːki]中。 3.此时才能在file->build setting中Add open scene&…

图解李白的“朋友圈”

《长安三万里》作为2023年票房第一的国漫电影&#xff0c;以安史之乱为背景&#xff0c;从诗人高适的视角铺设了一幅绚丽的历史长卷&#xff0c;细细讲述“诗仙”李白跌宕起伏的一生&#xff0c;以及大唐盛世一路荣耀幻灭的唏嘘。同时&#xff0c;在这部动画电影中出现了多位大…

【了解机器学习的定义与发展历程】

曾梦想执剑走天涯&#xff0c;我是程序猿【AK】 目录 简述概要知识图谱 简述概要 了解机器学习的定义与发展历程 知识图谱 机器学习&#xff08;Machine Learning&#xff0c;ML&#xff09;是一门跨学科的学科&#xff0c;它使用计算机模拟或实现人类学习行为&#xff0c;通…

HTML5新婚、年会、各种聚会的现场抽奖活动(附源码)

文章目录 1.抽奖平台设计来源1.1 主界面效果1.2 抽奖效果1.3 中奖效果 2.效果和源码配置2.1 动态效果2.2 人员信息配置2.3 奖品信息配置2.4 抽奖音效配置2.5 源代码 源码下载 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/article/deta…

UnityWebGL 设置全屏

这是Unity导出Web默认打开的页面尺寸 修改后效果 修改 index.html 文件 1.div元素的id属性值为"unity-container"&#xff0c;宽度和高度都设置为100%&#xff0c;意味着该div元素将占据整个父容器的空间。canvas元素的id属性值为"unity-canvas"&#xff…

liunx docker 安装 nginx:stable-alpine 后报500错误

参考:docker使用nginx部署网站报500错误_docker nginx 500-CSDN博客 重启容器后访问,正常

在面试中,如何回复擅长 Vue 还是 React

目录 一、Vue.JS 二、React 三、Vue和React的区别 四、前端开发框架 一、Vue.JS Vue.js&#xff08;通常简称为Vue&#xff09;是一个用于构建用户界面的开源JavaScript框架。它采用了MVVM&#xff08;Model-View-ViewModel&#xff09;的架构模式&#xff0c;通过数据驱动…

C语言——指针——第1篇——(第19篇)

坚持就是胜利 文章目录 1.指针是什么2.指针和指针类型&#xff08;1&#xff09;指针 - 整数&#xff08;2&#xff09;指针 的 解引用 3.野指针(1)野指针成因1.指针未初始化2.指针越界访问3.指针指向的空间释放 (2)如何规避野指针1.指针初始化2.小心指针越界3.指针指向的空间…

Vue+SpringBoot打造生活废品回收系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容三、界面展示3.1 登录注册3.2 资源类型&资源品类模块3.3 回收机构模块3.4 资源求购/出售/交易单模块3.5 客服咨询模块 四、免责说明 一、摘要 1.1 项目介绍 生活废品回收系统是可持续发展的解决方案&#xff0c;旨在鼓…

FreeBSD如何进行系统升级

为什么要升级 原因是当前在使用的版本是12.4&#xff0c;官方已经停止维护了&#xff0c;而且找了几个国内的镜像站也不维护了&#xff0c;导致pkg工具都无法安装&#xff0c;干脆直接进行系统升级。 FreeBSD的系统升级 目前打算升级到13.2-RELEASE版本 获取目前版本需要的…

前端快速网格布局

直接进去CSS Grid Generator 真的好方便&#xff1a;

Python实战:读取MATLAB文件数据(.mat文件)

Python实战&#xff1a;读取MATLAB文件数据(.mat文件) &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程 &#x1f448; 希望得到您的订阅…
最新文章