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(毫秒)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM