How To Split Randomly But Unevenly – PHP Code For Load UNBalancing

I read over a recent post on load splitting, that got me thinking about code I’ve written over the years – how to divide the work between many resources, keeping in account how much each can ‘handle’?

For example, if you have a server that can handle 3 times the load of another, it makes sense that it should get 3 times the calls – so if you send a visitor randomly to each server, it should get 3/4 of them, and the other 1/4.

In PHP, you could just do this:

if (mt_rand()>0.75) { pick one server } else { pick the other server }

But how to scale it?

The trick is to use an array, with each one representing the ‘capacity’ of the server. The total then is ALL the traffic.

In PHP, you could set up an array like this:

$server=array(10,50,20);

with each value representing a server and its capacity.

The array total is 80, so if we created a random number from 0-79, here’s how it would map out:

Pick 0-9: server ‘0’, picked about 10/80 of the time
Pick 10-59: server ‘1’, picked about 50/80 of the time
Pick 60-79: server ‘2’, picked about 20/80 of the time

And here’s the code to do this:

$server=array(10,50,20);
$x=mt_rand(0,array_sum($server)-1);
$i=-1;
while ($x-$server[++$i]>=0) $x-=$server[$i];
// or more cryptic but faster: 
// while ( ($x-=$server[++$i]) >= 0 ) {;}
// the server to use is in $i

The advantage of this is the dynamic splitting – by changing the values of $server we can affect the load of each one dynamically – for example, if we set the value $server[1] to zero we’ve effectively taken it offline. If another server gets some extra memory, we just bump it up. And so on.

So this is a simple solution – now how can we complicate it?