• PHP随机红包算法


    2017年1月14日 14:19:14 星期六

    一, 整体设计

    算法有很多种, 可以自行选择, 主要的"架构" 是这样的, 用redis decr()命令去限流, 用mysql去记录各种需要的数据

    二, 红包算法 

    简便起见, 红包金额用整数表示, 假设每个红包里边有x个糖豆, 每个人最少一个豆

    一种: 每个红包的最大金额是: (剩余金额/剩余红包数)*2, 需要开始的时候预先分配给每个人一个豆

     1 function randBean($total_bean, $total_packet)
     2 {
     3     $min_bean = 1;
     4     $max_bean = 5000;
     5     $range = 2;
     6     
     7     $total_bean = $total_bean - $total_packet * $min_bean; //每个人预留一个最小值
     8 
     9     $list = [];
    10     $min = 1;
    11     while(count($list) < $total_packet){
    12         $max = floor($total_bean / $total_packet) * $range;
    13         $bean = rand($min, $max);
    14 
    15         if ($bean <= $max_bean - 1) {
    16             $list[] = $bean;
    17             $total_bean -= $bean;
    18         }
    19     }
    20 
    21     $list[] = $total_bean;//剩余的金豆作为最后一个红包
    22 
    23     //合并
    24     foreach ($list as $k => $v) {
    25         $list[$k] += $min_bean;
    26     }
    27 
    28     return $list;
    29 }

    多次统计

    第二种, 对其简单扩展一下, 每个红包的最大金额是: (剩余金额/剩余红包数)*3; 但是要求每次最少发2个红包

    第三种, 线段法, 随机生成几个数字, 将一个直线分成几段, 每段的长度(这个波动比较大, 不是很平均, 如果限制了每个红包的大小, 会比较麻烦)

     1 function abc ($total_bean, $total_packet)
     2 {    
     3     $min = 1;
     4     $max = $total_bean -1;
     5     $list = [];
     6     
     7     $maxLength = $total_packet - 1;
     8     while(count($list) < $maxLength) {
     9         $rand = mt_rand($min, $max);
    10         empty($list[$rand]) && ($list[$rand] = $rand);
    11     }
    12     
    13     $list[0] = 0; //第一个
    14     $list[$total_bean] = $total_bean; //最后一个
    15     
    16     sort($list); //不再保留索引
    17     
    18     $beans = [];
    19     for ($j=1; $j<=$total_packet; $j++) {
    20         $beans[] = $list[$j] - $list[$j-1];
    21     }
    22     
    23     // return $beans;
    24     echo '<pre>'; print_r($beans); echo array_sum($beans);
    25 }
    26 
    27 abc(100000, 3);

    第四种:

    因为每人最少1个豆, 那么每次随机生成豆数的时候要预留 剩余人数*1个豆;

    去掉这些必须剩余的豆数后, 以剩下的豆数的平均值为最大值进行随机生成本次豆数

    btw:

    抢红包时用redis的一些原子性函数去限流, 然后用MySQL去记录数据

    redis配合抢红包使用的函数(一个函数可以干两件事): 

    限制每个人只能抢一次

    getSet(): 设置值并返回原来的值

    setNx(): 如果不存在才设置

    红包数量有限, 不能抢超

    incr() incrBy() : 增加并返回增加后的值

    decr() decrBy(): 减少并返回减少后的值

    红包有效期

    expire, setTimeout, pexpire(毫秒)

    expireAt, pexpireAt(毫秒)

  • 相关阅读:
    https页面打不开
    Centos6.5安装步骤(U盘安装)
    利用Metrics+influxdb+grafana构建监控平台
    CentOS 7安装Oracle 11gR2以及设置自启动
    如何安装Oracle Instant Client
    (转)rlwrap真是一个好东西
    oracle数据库11g(11.2.0.1)安装报错:提示ins_ctx.mk编译错误。
    oracle查看所有表及各表行数
    dp hdu5653 xiaoxin and his watermelon candy
    C语言free函数的原理——————————【Badboy】
  • 原文地址:https://www.cnblogs.com/iLoveMyD/p/6285315.html
Copyright © 2020-2023  润新知