代码之家  ›  专栏  ›  技术社区  ›  John Lemp Chris Heald

非随机加权分布

  •  5
  • John Lemp Chris Heald  · 技术社区  · 16 年前

    当前算法根据时间窗口中的秒数对客户机的10位ID号(公平分布)进行mod,并为每个客户机连接到服务器提供一个非常均匀、可预测的时间。现在的问题是,客户端不成比例地位于不同的时区,并且特定的时区在给定的窗口中重叠,因此净影响是负载在服务器上分布不均匀。我想要的是设计一种算法,我可以用当前每个时区的客户端百分比进行配置,并让它在窗口之间分配客户端的下一次连接时间,从而以可预测(非随机)的方式在服务器上实现均匀负载。

    以下是一个简单的图形表示:

                                12AM 1AM 2AM 3AM 4AM 5AM 6AM GMT
    GMT -4  40% of the clients  ||||||||||||||||||||||||||||||            
    GMT -5  10% of the clients       ||||||||||||||||||||||||||||||        
    GMT -6  20% of the clients           ||||||||||||||||||||||||||||||    
    GMT -7  30% of the clients               ||||||||||||||||||||||||||||||
    
    5 回复  |  直到 16 年前
        1
  •  5
  •   Jason Orendorff Oliver    16 年前

    将问题分为两部分:(1)确定您希望每组客户机具有什么分布;和(2)确定地分配符合该分布的重新连接时间。

    对于问题(1),考虑一个二维数组,就像你画的图一样:每一行代表一个时区,每个列代表一天中的一个相等的时间段(一个小时,也许)。你要解决的问题是用数字填充网格

    • 每行的总数是该时区中的客户端数;
    • 对于每一行,时区重新连接窗口之外的所有数字都是零;
    • 列的总和不超过某个预定的最大值(并且尽可能均衡)。

    这种问题有很多解决办法。你可以通过模拟找到一个,而不需要做任何艰苦的数学计算。编写一个填充网格的程序,使每个时区的客户机均匀分布(即您现在的分布方式),然后重复地将客户机从一天中拥挤的时间水平移动到不那么拥挤的时间。

    12:00    1:00   2:00   3:00   4:00   5:00   6:00 ...
      +------+------+------+------+------+------+----
      |    0 |    0 |  100 |   70 |   30 |    0 |   ...
      +------+------+------+------+------+------+----
    

    首先找到整行的总和,并将数字放大到ID的范围。也就是说,除以和,再乘以10 10 .

    12:00    1:00   2:00        3:00       4:00        5:00   6:00 ...
      +------+------+-----------+-----------+-----------+------+----
      |    0 |   0  | 500000000 | 350000000 | 150000000 |    0 |   ...
      +------+------+-----------+-----------+-----------+------+----
    

    现在让x=十位数的ID,并从左到右读取该行。在每个框中,用x减去该框中的值。继续,直到方框中的数字大于x中的剩余数字。报时

    (start time for this box) + (duration of this box) * x / (number in box)
    

    下次重新计算矩阵时。然后每个人的重新连接时间都会有一点变化,但不会太多,除非矩阵发生显著变化。

        2
  •  3
  •   Anna    16 年前

    除了ID之外,您还可以考虑用户的时区。

    使用此方法的一个示例解决方案如下:

    有24个时区。计算每个时区的相对负载。您可以通过将静态数据中每个时区的客户端总数相加来实现这一点。现在你有了“加权时区”。每个时区将获得与其权重成比例的时间份额。

    例如,如果您有以下数据(为简单起见,假设只有三个时区):

    Time Zone | Clients num
    ------------------------
        0     |     20
        1     |     30
        2     |     10
    

    然后你将你的时间间隔大小除以60,给每个时区分配时间:第一个时区将得到(20/60*#时间),第二个时区将得到以下(30/60*#时间)等等。

    笔记:

    1. 这是“时间分割”的一个示例,您可以根据需要修改此示例,例如,您可以为多个时区设置共同的时间框架。

    编辑:

    根据您在问题中添加的示例,您可以通过以下方式应用此方法:

    使用上面解释的想法,可以非均匀地划分用户,因此对于每个时区,有“概率更高”的小时,也有“概率更低”的小时。在您的示例中,在GMT-4组中,10%/40%的客户端将在第一个小时内访问服务器:GMT上午12点到凌晨1点。可以计算每个时区的负载,以便服务器每小时的总负载为10%。有很多方法可以做到这一点——贪婪的方法也可以。 一旦你有了这个,你就知道了每个时区的权重,并且应该更清楚地知道如何使用上面描述的分时方法。

        3
  •  1
  •   Grzenio    16 年前

    我将为您正在查看的每个时区定义一个助手类:

    class Timezone
    {
      DateTime start;
      int hourlyWeights[6]; //assuming you have 6 hour long timeslot for every timezone
    
      DateTime GetStartTime(long clientId)
      {
        long allTicks = 3600*sum(hourlyWeights);
        long clientTicks = clientId%allTicks;
        int i = 0;
        while(clientTicks>hourlyWeights[i])
        {
          clientTicks -= hourlyWeights[i]*3600;
          i++;
        }
        long seconds = clientTicks/hourlyWeights[i];
        return start.AddHours(i).AddSeconds(seconds);
      }
    }
    

    现在使用GetStartTime方法从该时区获取客户端的开始时间。这里的想法是,我们有一个hourlyWeights表,其中包含给定时区的分布,例如[40,20,0,0,0,0,0],这意味着这些客户将仅在前两个小时内得到服务,我们希望在第一个小时内得到两倍的客户。注意:我假设ID在给定时区的客户端之间均匀分布。

    棘手的一点是创建这些类。如果您有相当稳定的客户结构,那么您可以手动计算分布并将其放入配置文件中。如果它经常更改,请告诉我,我将发布一些代码来动态地解决它。

        4
  •  0
  •   Jason Orendorff Oliver    16 年前

    简单一点,这个怎么样:

    • 如果服务器上的负载过高,则改为在时间窗口中向客户端发送其他一些随机数。

    过几天事情会自行解决的。

        5
  •  0
  •   jilles de wit    16 年前