小知识:服务器开发设计之算法宝典

%小知识:服务器开发设计之算法宝典-猿站网-插图

孙子云:“上兵伐谋,其次伐交,其次伐兵,其下攻城”,最上乘行军打仗的方式是运用谋略,下乘的方式才是与敌人进行惨烈的厮杀。同样的,在程序设计中,解决问题的办法有很多种,陷入到与逻辑进行贴身肉搏的境况实属下下之策,而能运用优秀合理的算法才是”伐谋”的上上之策。

算法的思想精髓是值得深入研究和细细品味的,本宝典总结了服务器开发设计过程中涉及到的一些常用算法,试图尽量以简洁的文字和图表来解释和说明其中的思想原理,希望能给大家带来一些思考和启示。

思维导图

%小知识:服务器开发设计之算法宝典-1猿站网-插图

1. 调度算法

在服务器逻辑开发设计中,调度算法随处可见,资源的调度,请求的分配,负载均衡的策略等等都与调度算法相关。调度算法没有好坏之分,最适合业务场景的才是最好的。

1.1. 轮询

轮询是非常简单且常用的一种调度算法,轮询即将请求依次分配到各个服务节点,从第一个节点开始,依次将请求分配到最后一个节点,而后重新开始下一轮循环。最终所有的请求会均摊分配在每个节点上,假设每个请求的消耗是一样的,那么轮询调度是最平衡的调度(负载均衡)算法。

1.2. 加权轮询

有些时候服务节点的性能配置各不相同,处理能力不一样,针对这种的情况,可以根据节点处理能力的强弱配置不同的的权重值,采用加权轮询的方式进行调度。

加权轮询可以描述为:

调度节点记录所有服务节点的当前权重值,初始化为配置对应值。

当有请求需要调度时,每次分配选择当前权重最高的节点,同时被选择的节点权重值减一。

若所有节点权重值都为零,则重置为初始化时配置的权重值。

最终所有请求会按照各节点的权重值成比例的分配到服务节点上。假设有三个服务节点{a,b,c},它们的权重配置分别为{2,3,4},那么请求的分配次序将是{c,b,c,a,b,c,a,b,c},如下所示:

请求序号当前权重选中节点调整后权重1{2,3,4}c{2,3,3}2{2,3,3}b{2,2,3}3{2,2,3}c{2,2,2}4{2,2,2}a{1,2,2}5{1,2,2}b{1,1,2}6{1,1,2}c{1,1,1}7{1,1,1}a{0,1,1}8{0,1,1}b{0,0,1}9{0,0,1}c{0,0,0}

1.3. 平滑权重轮询

加权轮询算法比较容易造成某个服务节点短时间内被集中调用,导致瞬时压力过大,权重高的节点会先被选中直至达到权重次数才会选择下一个节点,请求连续的分配在同一个节点上的情况,例如假设三个服务节点{a,b,c},权重配置分别是{5,1,1},那么加权轮询调度请求的分配次序将是{a,a,a,a,a,b,c},很明显节点 a 有连续的多个请求被分配。

为了应对这种问题,平滑权重轮询实现了基于权重的平滑轮询算法。所谓平滑,就是在一段时间内,不仅服务节点被选择次数的分布和它们的权重一致,而且调度算法还能比较均匀的选择节点,不会在一段时间之内集中只选择某一个权重较高的服务节点。

平滑权重轮询算法可以描述为:

调度节点记录所有服务节点的当前权重值,初始化为配置对应值。

当有请求需要调度时,每次会先把各节点的当前权重值加上自己的配置权重值,然后选择分配当前权重值最高的节点,同时被选择的节点权重值减去所有节点的原始权重值总和。

若所有节点权重值都为零,则重置为初始化时配置的权重值。

同样假设三个服务节点{a,b,c},权重分别是{5,1,1},那么平滑权重轮询每一轮的分配过程如下表所示:

%小知识:服务器开发设计之算法宝典-2猿站网-插图

最终请求分配的次序将是{ a, a, b, a, c, a, a},相对于普通权重轮询算法会更平滑一些。

1.4. 随机

随机即每次将请求随机地分配到服务节点上,随机的优点是完全无状态的调度,调度节点不需要记录过往请求分配情况的数据。理论上请求量足够大的情况下,随机算法会趋近于完全平衡的负载均衡调度算法。

1.5. 加权随机

类似于加权轮询,加权随机支持根据服务节点处理能力的大小配置不同的的权重值,当有请求需要调度时,每次根据节点的权重值做一次加权随机分配,服务节点权重越大,随机到的概率就越大。最终所有请求分配到各服务节点的数量与节点配置的权重值成正比关系。

1.6. 最小负载

实际应用中,各个请求很有可能是异构的,不同的请求对服务器的消耗各不相同,无论是使用轮询还是随机的方式,都可能无法准确的做到完全的负载均衡。最小负载算法是根据各服务节点当前的真实负载能力进行请求分配的,当前负载最小的节点会被优先选择。

最小负载算法可以描述为:

服务节点定时向调度节点上报各自的负载情况,调度节点更新并记录所有服务节点的当前负载值。

当有请求需要调度时,每次分配选择当前负载最小(负载盈余最大)的服务节点。

负载情况可以统计节点正在处理的请求量,服务器的 CPU 及内存使用率,过往请求的响应延迟情况等数据,综合这些数据以合理的计算公式进行负载打分。

1.7. 两次随机选择策略

最小负载算法可以在请求异构情况下做到更好的均衡性。然而一般情况下服务节点的负载数据都是定时同步到调度节点,存在一定的滞后性,而使用滞后的负载数据进行调度会导致产生“群居”行为,在这种行为中,请求将批量地发送到当前某个低负载的节点,而当下一次同步更新负载数据时,该节点又有可能处于较高位置,然后不会被分配任何请求。再下一次又变成低负载节点被分配了更多的请求,一直处于这种很忙和很闲的循环状态,不利于服务器的稳定。

为应对这种情况,两次随机选择策略算法做了一些改进,该算法可以描述为:

服务节点定时向调度节点上报各自的负载情况,调度节点更新并记录所有服务节点的当前负载值。

从所有可用节点列表中做两次随机选择操作,得到两个节点。

比较这两个节点负载情况,选择负载更低的节点作为被调度的节点。

两次随机选择策略结合了随机和最小负载这两种算法的优点,使用负载信息来选择节点的同时,避免了可能的“群居”行为。

1.8. 一致性哈希

为了保序和充分利用缓存,我们通常希望相同请求 key 的请求总是会被分配到同一个服务节点上,以保持请求的一致性,既有了一致性哈希的调度方式。

关于一致性哈希算法,笔者曾在 km 发表过专门的文章《一致性哈希方案在分布式系统中应用对比》,详细介绍和对比了它们的优缺点以及对比数据,有兴趣的同学可以前往阅读。

1.8.1. 划段

最简单的一致性哈希方案就是划段,即事先规划好资源段,根据请求的 key 值映射找到所属段,比如通过配置的方式,配置 id 为[1-10000]的请求映射到服务节点 1,配置 id 为[10001-20000]的请求映射到节点 2 等等,但这种方式存在很大的应用局限性,对于平衡性和稳定性也都不太理想,实际业务应用中基本不会采用。

1.8.2. 割环法

割环法的实现有很多种,原理都类似。割环法将 N 台服务节点地址哈希成 N 组整型值,该组整型即为该服务节点的所有虚拟节点,将所有虚拟节点打散在一个环上。

请求分配过程中,对于给定的对象 key 也哈希映射成整型值,在环上搜索大于该值的第一个虚拟节点,虚拟节点对应的实际节点即为该对象需要映射到的服务节点。

如下图所示,对象 K1 映射到了节点 2,对象 K2 映射到节点 3。

%小知识:服务器开发设计之算法宝典-3猿站网-插图

割环法实现复杂度略高,时间复杂度为 O(log(vn)),(其中,n 是服务节点个数,v 是每个节点拥有的虚拟节点数),它具有很好的单调性,而平衡性和稳定性主要取决于虚拟节点的个数和虚拟节点生成规则,例如 ketama hash 割环法采用的是通过服务节点 ip 和端口组成的字符串的 MD5 值,来生成 160 组虚拟节点。

1.8.3. 二次取模

取模哈希映射是一种简单的一致性哈希方式,但是简单的一次性取模哈希单调性很差,对于故障容灾非常不好,一旦某台服务节点不可用,会导致大部分的请求被重新分配到新的节点,造成缓存的大面积迁移,因此有了二次取模的一致性哈希方式。

二次取模算法即调度节点维护两张服务节点表:松散表(所有节点表)和紧实表(可用节点表)。请求分配过程中,先对松散表取模运算,若结果节点可用,则直接选取;若结果节点已不可用,再对紧实表做第二次取模运算,得到最终节点。如下图示:

%小知识:服务器开发设计之算法宝典-4猿站网-插图

二次取模算法实现简单,时间复杂度为 O(1),具有较好的单调性,能很好的处理缩容和节点故障的情况。平衡性和稳定性也比较好,主要取决于对象 key 的分布是否足够散列(若不够散列,也可以加一层散列函数将 key 打散)。

1.8.4. 最高随机权

最高随机权重算法是以请求 key 和节点标识为参数进行一轮散列运算(如 MurmurHash 算法),得出所有节点的权重值进行对比,最终取最大权重值对应的节点为目标映射节点。可以描述为如下公式:

散列运算也可以认为是一种保持一致性的伪随机的方式,类似于前面讲到的普通随机的调度方式,通过随机比较每个对象的随机值进行选择。

这种方式需要 O(n)的时间复杂度,但换来的是非常好的单调性和平衡性,在节点数量变化时,只有当对象的最大权重值落在变化的节点上时才受影响,也就是说只会影响变化的节点上的对象的重新映射,因此无论扩容,缩容和节点故障都能以最小的代价转移对象,在节点数较少而对于单调性要求非常高的场景可以采用这种方式。

1.8.5. Jump consistent hash

jump consistent hash 通过一种非常简单的跳跃算法对给定的对象 key 算出该对象被映射的服务节点,算法如下:

int

声明: 猿站网有关资源均来自网络搜集与网友提供,任何涉及商业盈利目的的均不得使用,否则产生的一切后果将由您自己承担! 本平台资源仅供个人学习交流、测试使用 所有内容请在下载后24小时内删除,制止非法恶意传播,不对任何下载或转载者造成的危害负任何法律责任!也请大家支持、购置正版! 。本站一律禁止以任何方式发布或转载任何违法的相关信息访客发现请向站长举报,会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。本网站的资源部分来源于网络,如有侵权烦请发送邮件至:2697268773@qq.com进行处理。
建站知识

小知识:「容器云架构」K8s 多区域部署

2023-3-13 10:54:46

建站知识

小知识:教你如何将 Lvm 卷移动到另一台服务器中

2023-3-13 11:09:31

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索