PHP实现负载均衡的加权轮询方法分析

本文实例讲述了PHP实现负载均衡的加权轮询方法。分享给大家供大家参考,具体如下:

1. 负载均衡算法有哪些?

  • 轮询法:将请求按顺序轮流地分配到后端服务器上,它均衡地对待后端的每一台服务器,而不关心服务器实际的连接数和当前的系统负载。
  • 随机法:通过系统的随机算法,根据后端服务器的列表大小值来随机选取其中的一台服务器进行访问。
  • 源地址哈希法:根据获取客户端的IP地址,通过哈希函数计算得到一个数值,用该数值对服务器列表的大小进行取模运算,得到的结果便是客服端要访问服务器的序号。采用源地址哈希法进行负载均衡,同一IP地址的客户端,当后端服务器列表不变时,它每次都会映射到同一台后端服务器进行访问。
  • 加权轮询法:不同的后端服务器可能机器的配置和当前系统的负载并不相同,因此它们的抗压能力也不相同。给配置高、负载低的机器配置更高的权重,让其处理更多的请;而配置低、负载高的机器,给其分配较低的权重,降低其系统负载,加权轮询能很好地处理这一问题,并将请求顺序且按照权重分配到后端。
  • 加权随机法:与加权轮询法一样,加权随机法也根据后端机器的配置,系统的负载分配不同的权重。不同的是,它是按照权重随机请求后端服务器,而非顺序。
  • 最小连接数法:由于后端服务器的配置不尽相同,对于请求的处理有快有慢,最小连接数法根据后端服务器当前的连接情况,动态地选取其中当前积压连接数最少的一台服务器来处理当前的请求,尽可能地提高后端服务的利用效率,将负责合理地分流到每一台服务器。

2.如何用PHP实现加权轮询?

实现思路:

通过传入不同的用户id,然后给他们分配不同的主机。

首先,需要一个接收用户id的数组。

其次,需要一个存主机的数组,这些主机有不同的权重。这里的权重可以这么考虑:

假设有abc三台主机,权重分别为3,1,1,那么a的占比为0.6,b和c的占比各为0.2。

直接遍历主机的数组,假如用户来了100个人,到a的时候,a的占比是0.6,就从用户数组里随机取60个人分给a;轮到b时,b的占比是0.2,就从用户数组里随机取20人;同理,c20人,这样就完成了100个请求的转发。

可是真实场景不是固定一批用户,而是持续不断的用户请求,由于转发非常快,当来的新用户非常少时,每次从用户队列中取完、转发后立马去用户队列中取,很有可能每次只取2条,造成请求全部给了a,b和c一直没有的情况。这时候可以考虑按照不同策略从用户队列中取数据。假设以前5ms就处理完一次转发,则现在定义两种策略,如果用户队列中有100个用户时,就取出来,按着主机占比进行转发,如果用户队列中不足100人,但是当前时间和上一次取值时间相差10ms,就取出来进行转发,这样就可以累积5ms,而这5ms里队列中又会多一些用户请求,这样就不会把所有请求都分给一台机器了。

代码:

<?php
// php实现负载均衡的加权轮询(WRR)
class WRR {
  // 每次取100人
  const num = 100;
  // 上次取值时间,秒级时间戳
  public $last_time;
  // 权重 machine=>weight
  public $machines = array(
    'a' => 3, // 0.6
    'b' => 1, // 0.2
    'c' => 1 // 0.2
  );
  // 占比
  public $proportion = array();
  // 用户队列
  public static $user_ids = array();
  public function __construct() {
    // 各机器的占比
    $total = 0;
    foreach ($this->machines as $machine => $weight) {
      $total += $weight;
    }
    $this->proportion['a'] = $this->machines['a'] / $total;
    $this->proportion['b'] = $this->machines['b'] / $total;
    $this->proportion['c'] = $this->machines['c'] / $total;
  }
  public function getUsers() {
    // 用户人数
    $cnt = count(self::$user_ids);
    $a_num = 0;
    $b_num = 0;
    $c_num = 0;
    if ($cnt >= self::num) { // 队列超过100人
      $a_num = round(self::num * $this->proportion['a']);
      $b_num = round(self::num * $this->proportion['b']);
      $c_num = $cnt - $a_num - $b_num;
    } else { // 队列不足100人
      $last_time = $this->last_time; // 上次访问时间
      while (true) {
        $current_time = $this->getMillisecond();
        if (($current_time - $last_time) >= 10) { // 当前时间和上一次取值时间超过10ms
          $a_num = round($cnt * $this->proportion['a']);
          $b_num = round($cnt * $this->proportion['b']);
          $c_num = $cnt - $a_num - $b_num;
          $this->last_time = self::getMillisecond();  // 更新访问时间
          break;
        }
      }
    }
    $a = array_splice(self::$user_ids, 0, $a_num);
    $b = array_splice(self::$user_ids, 0, $b_num);
    $c = array_splice(self::$user_ids, 0, $c_num);
    return array(
      'a' => $a,
      'b' => $b,
      'c' => $c
    );
  }
  // 获取毫秒级时间戳
  public function getMillisecond() {
    list($t1, $t2) = explode(" ", microtime());
    return (float)sprintf('%.0f', (floatval($t1) + floatval($t2)) * 1000);
  }
}
// 测试
$wrr = new WRR();
for ($i = 0; $i < 3; $i++) {// 模拟持续不断的用户请求
  $random = rand(10, 120);
  $user_ids = range(1, $random);
  WRR::$user_ids = $user_ids;
  $users = $wrr->getUsers();
  print_r($users);
}

真实的算法比这个复杂多了,它需要考虑一点,就是来过的用户要保持原来分配的机器,除非原来的机器挂了。这样做的原因是缓存。很多基于内存的缓存,都是基于用户级别的,所以相同的用户保持同一台机器,有助于提升性能。

更多关于PHP相关内容感兴趣的读者可查看本站专题:《PHP数据结构与算法教程》、《php程序设计算法总结》、《php字符串(string)用法总结》、《PHP数组(Array)操作技巧大全》、《PHP常用遍历算法与技巧总结》及《PHP数学运算技巧总结》

希望本文所述对大家PHP程序设计有所帮助。

(0)

相关推荐

  • PHP实现的一致性Hash算法详解【分布式算法】

    本文实例讲述了PHP实现的一致性Hash算法.分享给大家供大家参考,具体如下: 一致性哈希算法是分布式系统中常用的算法,为什么要用这个算法? 比如:一个分布式存储系统,要将数据存储到具体的节点(服务器)上, 在服务器数量不发生改变的情况下,如果采用普通的hash再对服务器总数量取模的方法(如key%服务器总数量),如果期间有服务器宕机了或者需要增加服务器,问题就出来了. 同一个key经过hash之后,再与服务器总数量取模的结果跟之前的结果会不一样,这就导致了之前保存数据的丢失.因此,引入了一致性

  • PHP经典算法集锦【经典收藏】

    本文实例总结了PHP经典算法.分享给大家供大家参考,具体如下: 1.首先来画个菱形玩玩,很多人学C时在书上都画过,咱们用PHP画下,画了一半. 思路:多少行for一次,然后在里面空格和星号for一次. <?php for($i=0;$i<=3;$i++){ echo str_repeat(" ",3-$i); echo str_repeat("*",$i*2+1); echo '<br/>'; } 2.冒泡排序,C里基础算法,从小到大对一组数

  • PHP实现负载均衡session共享redis缓存操作示例

    本文实例讲述了PHP实现负载均衡session共享redis缓存操作.分享给大家供大家参考,具体如下: 1.首先先创建html表单页面 <meta chatset='utf-8'> <center> <form action="se.php" method="post"> <table> <tr> <td>帐号:</td> <td><input type="

  • PHP实现负载均衡下的session共用功能

    本文实例讲述了PHP实现负载均衡下的session共用功能.分享给大家供大家参考,具体如下: 最近忙于开发台湾运动彩券第四版的程序,所以已经很久没有上来写东西了,今天随便写点东西和大家分享. 首先说一下负载均衡,相信大家都知道负载均衡可以很好地解决网站大流量的问题,负载均衡就是把用户的请求分发到多态pc上进行处理,既然分发了请求那么session就要考虑好处理方法.传统情况下php会把session存入本机的暂存档内,可是这种情况下分发了之后session就丢失了,其实最简单的解决方法就是用me

  • Nginx 安装笔记(含PHP支持、虚拟主机、反向代理负载均衡)

    系统环境:RHEL5 [ 2.6.18-8.el5xen ] 软件环境: nginx-0.7.17 lighttpd-1.4.20.tar.gz pcre-6.6-1.1 pcre-devel-6.6-1.1 php-5.1.6-5.el5 参考下载地址: http://sysoev.ru/nginx/nginx-0.7.17.tar.gz (最新稳定版为0.6.32) http://www.lighttpd.net/download/lighttpd-1.4.20.tar.gz #######

  • Thinkphp结合AJAX长轮询实现PC与APP推送详解

    前言 本文主要给大家介绍的关于Thinkphp结合AJAX长轮询实现PC与APP推送的相关内容,分享出来供大家参考学习,话不多说,来一起看看详细的介绍. 实现逻辑 某个操作(比如新建一条公告)后,触发同时推送消息给APP或是移动WEB的所有用户或指定用户. 不论性能,总还是有人会用到吧,实现如下(基于Thinkphp5消息推送): PHP长轮询 /* * long轮询 API查询接口 */ public function id_log() { if (request()->isPost()) {

  • PHP中对各种加密算法、Hash算法的速度测试对比代码

    PHP 的Hash算法是比较常用的,现在的MD5有时候不太安全,就得用到Hash_algos()中的其它算法,下面进行了一个性能的比较. php代码: define('testtime', 50000); $algos = hash_algos(); foreach($algos as $algo) { $st = microtime(); for($i = 0; $i < testtime; $i++) { hash($algo, microtime().$i); } $et = microt

  • php 分库分表hash算法

    复制代码 代码如下: //分库分表算法 function calc_hash_db($u, $s = 4) { $h = sprintf("%u", crc32($u)); $h1 = intval(fmod($h, $s)); return $h1; } for($i=1;$i<100;$i++) { echo calc_hash_db($i); echo "<br>"; } function calc_hash_tbl($u, $n = 256

  • php的hash算法介绍

    Hash Table是PHP的核心,这话一点都不过分. PHP的数组,关联数组,对象属性,函数表,符号表,等等都是用HashTable来做为容器的. PHP的HashTable采用的拉链法来解决冲突, 这个自不用多说, 我今天主要关注的就是PHP的Hash算法, 和这个算法本身透露出来的一些思想. PHP的Hash采用的是目前最为普遍的DJBX33A (Daniel J. Bernstein, Times 33 with Addition), 这个算法被广泛运用与多个软件项目,Apache, P

  • PHP开发负载均衡指南

    今天,'大型服务器'模式已经过去,取而代之的是大量的小服务器,使用各种各样的负载均衡技术.这是一种更可行的方法,将使硬件成本降至最低. '更多小服务器'的优势超过过去的'大型服务器'模式体现在两个方面: 1. 如果服务器宕机,那么负载均衡系统将停止请求到宕机的服务器,转而分发负载到其他正常运行的服务器上. 2. 扩展你的服务器更加容易.你要做的仅仅是加入新的服务器到负载均衡系统.不需要中断你的应用运行. 所以,把握住这个机会:). 当然,代价就是这要求你的应用开发时增加一点复杂度.这就是本文要覆

随机推荐