(二)动态轮循调度算法实现

版权声明:本文为博主原创,欢迎转载,转载请注明链接地址。 https://blog.csdn.net/qq_30164225/article/details/85068128

想看上篇的童鞋请移步静态轮循调度算法实现
上篇说到,使用取模方式,没有办法实现公平轮询调度,于是有了这篇,采用引用计数的方式实现动态轮询调度。如下:

<?php

/**
 * Class RoundCounter
 * 动态公平循环分配实现算法
 * 原理:
 *    通过整体循环计数和成员循环计数实现轮循调度
 * 数据结构:
 *
 * 权限人员集合 [1,2,3,4,5]
 * 本组的轮循次数 1
 * 人员初始化轮循次数:0
 *
 * 测试操作:
 * 1.人员状态变更
 * 2.组内人员变更 (不公平)
 */

class RoundCounter{
    protected $members;
    protected $loop;
    protected $membersInfo = [];

    public function __construct(array $members){
        $this->members = $members;
        $this->loop = 1;
        //初始化 成员状态
        foreach ($members as $member){
            $memberInfo = $this->initStatus($member);
            if($memberInfo['status'] == 1){
                $this->membersInfo[] = $memberInfo;
            }
        }
        echo '当前组内成员: '.json_encode($this->membersInfo).PHP_EOL;
    }

    //人员上/下线
    private function initStatus($member){
        $status =  mt_rand(1,2);
        return $info = array(
            'id'=>$member,
            'status'=>$status,
            'loop'=>$this->loop-1 //当前被轮循次数
        );
    }

    //todo 加减组内成员 如果能实现动态轮寻就完美了 静态有漏洞 会掠过部分客服
    public function changeGroupMembers(){
        // 新增一个成员
        $add = $this->initStatus(6);
        $add['status'] = 1;
        array_push($this->membersInfo,$add);
	echo '新增成员:  6 '.PHP_EOL;
        // 减少一个成员
        //$rand = mt_rand(0,count($this->membersInfo));
        //array_splice($this->membersInfo,$rand,1);
    }

    //获取当前组成员列表
    public function getMembers(){
        return $this->members;
    }

    //重置循环
    public function resetLoop(){
        $this->loop = 1;
        foreach($this->membersInfo  as &$v){
            $v['loop'] = 0;
        }
    }

    //分配在线客服
    public function choose(){
        if($this->loop > 10){
            $this->resetLoop();
        }

        $member1 = [];
        foreach($this->membersInfo as &$member){
            //轮循状态
            if($member['loop'] == $this->loop-1){
                echo '分配给: '.json_encode($member).PHP_EOL;
                $member['loop'] +=1;
                return $member1 = $member;
            }
        }

        //轮循
        if(!$member1){
            $this->loop++;
            return reset($this->membersInfo);
        }
    }
}

//测试参数
$a = new RoundCounter([1,2,3,4,5]);
echo '----第一轮调度-----'.PHP_EOL;
for($i = 1;$i<100;$i++){
    $a->choose();
}
$a->choose();
echo '----结束-----'.PHP_EOL;

echo '----修改组内客服-----'.PHP_EOL;
$a->changeGroupMembers();
echo '----第二轮循调度-----'.PHP_EOL;
for($i = 1;$i<100;$i++){
    $a->choose();
}

执行结果:

MacBook-2:Desktop lemon$ php RoundCounter.php
当前组内成员: [{"id":1,"status":1,"loop":0},{"id":2,"status":1,"loop":0},{"id":3,"status":1,"loop":0},{"id":4,"status":1,"loop":0}]
----第一轮调度-----
分配给: {"id":1,"status":1,"loop":0}
分配给: {"id":2,"status":1,"loop":0}
分配给: {"id":3,"status":1,"loop":0}
分配给: {"id":4,"status":1,"loop":0}
分配给: {"id":1,"status":1,"loop":1}
分配给: {"id":2,"status":1,"loop":1}
分配给: {"id":3,"status":1,"loop":1}
分配给: {"id":4,"status":1,"loop":1}
分配给: {"id":1,"status":1,"loop":2}
分配给: {"id":2,"status":1,"loop":2}
分配给: {"id":3,"status":1,"loop":2}
分配给: {"id":4,"status":1,"loop":2}
分配给: {"id":1,"status":1,"loop":3}
分配给: {"id":2,"status":1,"loop":3}
分配给: {"id":3,"status":1,"loop":3}
分配给: {"id":4,"status":1,"loop":3}
----结束-----
----修改组内客服-----
新增成员:6
----第二轮循调度-----
分配给: {"id":1,"status":1,"loop":4}
分配给: {"id":2,"status":1,"loop":4}
分配给: {"id":3,"status":1,"loop":4}
分配给: {"id":4,"status":1,"loop":4}
分配给: {"id":6,"status":1,"loop":4}
分配给: {"id":1,"status":1,"loop":5}
分配给: {"id":2,"status":1,"loop":5}
分配给: {"id":3,"status":1,"loop":5}
分配给: {"id":4,"status":1,"loop":5}
分配给: {"id":6,"status":1,"loop":5}
分配给: {"id":1,"status":1,"loop":6}
分配给: {"id":2,"status":1,"loop":6}
分配给: {"id":3,"status":1,"loop":6}
分配给: {"id":4,"status":1,"loop":6}
分配给: {"id":6,"status":1,"loop":6}
分配给: {"id":1,"status":1,"loop":7}

引用计数的方式,虽然看起来不那么高大上,比较朴素,但是却是最行之有效的方法。因为是原子操作,每个个体不受成员数量变更带来的算法影响,所以可以保证公平调度。(^__^) 嘻嘻……

有时候还是要仔细想想,多问问自己为什么这样写,是不是可以换个思路做的更好,才能不断进步。
(完)

猜你喜欢

转载自blog.csdn.net/qq_30164225/article/details/85068128
今日推荐