紅包演算法源碼
『壹』 微信紅包的隨機演算法是怎樣實現的
我們在一個20人的群中,自己發紅包以及結合其他人發出紅包的情況,整合成兩輪的數據。每次金額設置都是20塊並且有20個,第一輪是發了15次,第二輪是發了19次,總結成表格,然後為了避免突發的數據影響判斷,我們將兩輪數據雜糅從而生成了其他的三輪數據,一共是五輪數據。羅列如下表,高亮的數據為最佳手氣。每一列的數據最早搶到紅包的在最底端,越往上越晚搶。
從所有黃色的數值(最佳手氣金額)可看出,所有最佳手氣值都在平均值*2的前後附近(平均值=總金額/紅包總個數,這里平均值=20/20=1),事實上確實如此,可通過微信紅包分發演算法得到驗證,演算法具體見後文
然後我們選取部分數據開始製作散點圖。橫軸為1-20,分別表示搶到紅包的人的編號,隨遞增而越早。也就是20代表最早搶到的人。縱軸為金額。同樣的形狀顏色的點代表一次發紅包,然後我們抓取部分數據顯示為散點圖,越密集代表該順序位的用戶得到的金額越穩定。散點圖如下:
規律一:我們可以看到,所有紅包大多數金額分布在0.5到1.5元之間,顯示為圖中方框所示,大部分點都分布在這個位置。然後是順序位密集程度的對比,可以發現20、19,也就是最先搶到紅包的人,小圓圈所示基本的點都集中在小范圍,說明先搶紅包的人得到的金額會比較穩定,但同時最佳手氣的概率也比較低。大圓圈所示的是極不穩定,飄忽的金額分布,表示越晚搶紅包得到的金額會飄忽不穩,但同時,搶到最佳手氣等大金額的紅包概率也比早搶的高。
根據上面的分析,我們又寫了一個過濾計數函數,針對金額的分段的紅包個數進行統計:
比如2.0-2.5
得到如下金額分布:
折線圖:
規律二:絕大多數的紅包的金額都集中在1-1.5,也就是說20塊錢發20個紅包的金額分布集中在比平均數大一點點的附近,同時較大幅超過平均數金額的紅包大大少於低於於平均數的紅包數量。
那我們繼續擴大數據的規模,將幾輪數據的均值和標准差分別做成折線圖:
綜合上面各個折線圖的情況,我們可以得到越早搶紅包的標准差越小,越晚搶紅包的標准差越大,但同時,由均值和總額可以看出來,越早搶紅包的均值往往要更高,紅包金額得到最佳手氣概率也會相對較小,越晚搶紅包的人則得到最佳手氣等大手氣的概率更大。
為了得到更為趨近規律的曲線和規律,我們決定將兩輪真實數據合並起來,然後給出冪函數的趨近線(虛線),如下圖:
由於均值受極值波動影響較大,所以我們去除一些因為偶然差產生的極端點(圓圈的點)從而發現是遞增的趨勢。
規律三:可以很明顯的看到,均值是隨著搶紅包的越晚而緩慢遞減,標准差值同時也往上遞增,這個趨勢結合之前的分析,我們猜想,即標准差越大說明,領取到最大的紅包和最小紅包的風險越大,也就是說越晚搶標准差越大,對於冒險主義者來講是最好的,因為他有很大概率獲得最大的金額,但也大概率獲得最小的紅包,風險與收益並存;均值越大,說明每次都拿到一個不大不小的紅包,雖然獲得最小和最大金額紅包的概率很小,但起碼不虧本,也就是說越早搶,均值越穩定,這比較適合不喜歡冒險的人。
驗證預測結果:
21:24分發送預測結果到另一位同學微信:
隨後開始發紅包:
結果:
最佳手氣為第8個人且金額為1.13
與預測結果一致,規律基本正確!
總結:
(1)最佳手氣為1.13塊,根據我們推導的預測公式=總額/紅包總個數*2*隨機數(0-2的double數), 也就是說最佳手氣在總額/紅包總個數*2值的前後附近。這里我們判斷在0.8-1.3之間,推斷正確
(2)平均值為0.5元,0.5-0.8元的紅包有3個,小於0.5的紅包有6個,說明大於平均值的紅包個數多於小於平均值的個數。與我們的第二點預測完全正確
(3)最佳手氣位置:根據我們的散點圖發現,最先搶到紅包的人,得到的金額會比較穩定,但同時最佳手氣的概率也比較低。表示越晚搶紅包得到的金額波動較大,但同時搶到最佳手氣等大金額的紅包概率也比早搶的高。所以我們推斷,最佳手氣位置在最後20%-30%之間。
微信紅包隨機分發演算法c++模擬:
基本思路:每次搶到一個紅包金額等於:紅包剩餘金額/紅包剩餘個數*2*隨機數(0-1的double型),如果計算的結果小於等於0.01,則取0.01值
主要代碼:
double packages[50000];
double Luckiest_money=0;
void getPackage(int remainSize,double remainMoney){
srand((unsigned)time(NULL));
for(int i=0;i
『貳』 微信紅包5元隨機紅包隨機的金額
微信紅包隨機數字_微信隨機紅包數詳解和演算法代碼
1 需求
寫⼀個固定紅包 + 隨機紅包
固定紅包就是每個紅包⾦額⼀樣,有多少個就發多少個固定紅包⾦額就⾏。
隨機紅包的需求是。⽐如紅包總⾦額5元,需要發10個紅包。隨機范圍是 0.01到0.99;5元必需發完,⾦額需要有⼀定趨勢的正態分布。
(0.99可以任意指定,也可以是 avg * 2 - 0.01;⽐如avg = 5 / 10 = 0.5;(avg * 2 - 0.01 = 0.99))
2 需求分析
2.1 固定紅包
如果是固定紅包,則演算法是⼀條直線。t就是固定紅包的額度。如圖。
f(x) = t;(1 <= x <= num)
image.png
2.2 隨機紅包
如果我們使⽤隨機函數rand。rand(0.01,0.99);那麼10次隨機,如果最壞情況都是⾦額0.99,總⾦額就是9.9元。會超過5元。⾦額也會不正態分布。最後思考了⼀下藉助與數學函數來當作隨機紅包的發⽣器,可以⽤拋物線,三⾓函數。最後選定了等腰三⾓線性函數。
1 演算法原理
如果需要發紅包總⾦額是totalMoney,紅包個數是num個,⾦額范圍是[min,max],線性⽅程如圖。
image.png
三個點的坐標:
(x1,y1) = (1,min)
(x2,y2) = (num/2,max)
(x3,y3) = (num,min)
確定的線性⽅程:
$y = 1.0 * ($x - $x1) / ($x2 - $x1) * ($y2 - $y1) + $y1 ; (x1 <= x <= x2)
$y = 1.0 * ($x - $x2) / ($x3 - $x2) * ($y3 - $y2) + $y2; (x2 <= x <= x3)
修數據:
y(合) = y1 + y2 + y3 +...... ynum;
y(合)有可能 > totalMoney ,說明⽣成⾦額多了,需要修數據,則從(y1,y2,y3.....ynum)這些每次減少0.01。直到y(合) = totalMoney。
y(合)有可能 < totalMoney ,說明⽣成⾦額少了,需要修數據,則從(y1,y2,y3.....ynum)這些每次加上0.01。直到y(合) = totalMoney。
2 演算法原理樣例
如果需要發紅包總⾦額是11470,紅包個數是7400個,⾦額范圍是[0.01,3.09],線性⽅程如圖。
image.png
3 需求設計
3.1 類圖設計
image.png
3.2 源碼設計
/**
* 隨機紅包+固定紅包演算法[策略模式]
*/
//配置傳輸數據DTO
class OptionDTO
{
//紅包總⾦額
public $totalMoney;
//紅包數量
public $num;
//范圍開始
public $rangeStart;
//范圍結算
public $rangeEnd;
//⽣成紅包策略
public $builderStrategy;
//隨機紅包剩餘規則
public $randFormatType; //Can_Left:不修數據,可以有剩餘;No_Left:不能有剩餘public static function create($totalMoney,$num,$rangeStart,$rangEnd, $builderStrategy,$randFormatType = 'No_Left')
{
$self = new self();
$self->num = $num;
$self->rangeStart = $rangeStart;
$self->rangeEnd = $rangEnd;
$self->totalMoney = $totalMoney;
$self->builderStrategy = $builderStrategy;
$self->randFormatType = $randFormatType;
return $self;
}
}
//紅包⽣成器接⼝
interface IBuilderStrategy
{
//創建紅包
public function create();
//設置配置
public function setOption(OptionDTO $option);
//是否可以⽣成紅包
public function isCanBuilder();
//⽣成紅包函數
public function fx($x);
}
//固定等額紅包策略
class EqualPackageStrategy implements IBuilderStrategy {
//單個紅包⾦額
public $oneMoney;
//數量
public $num;
public function __construct($option = null)
{
if($option instanceof OptionDTO)
{
$this->setOption($option);
}
}
public function setOption(OptionDTO $option)
{
$this->oneMoney = $option->rangeStart;
$this->num = $option->num;
}
public function create()
{
$data = array();
if(false == $this->isCanBuilder())
{
return $data;
}
$data = array();
if(false == is_int($this->num) || $this->num <= 0) {
return $data;
}
for($i = 1;$i <= $this->num;$i++)
{
$data[$i] = $this->fx($i);
}
return $data;
}
/**
* 等額紅包的⽅程是⼀條直線
*
* @param mixed $x
* @access public
* @return void
*/
public function fx($x)
{
return $this->oneMoney;
}
/**
* 是否能固定紅包
*
* @access public
* @return void
*/
public function isCanBuilder()
{
if(false == is_int($this->num) || $this->num <= 0)
{
return false;
}
if(false == is_numeric($this->oneMoney) || $this->oneMoney <= 0)
{
return false;
}
//單個紅包⼩於1分
if($this->oneMoney < 0.01)
{
return false;
}
return true;
}
}
//隨機紅包策略(三⾓形)
class RandTrianglePackageStrategy implements IBuilderStrategy
{
//總額
public $totalMoney;
//紅包數量
public $num;
//隨機紅包最⼩值
public $minMoney;
//隨機紅包最⼤值
public $maxMoney;
//修數據⽅式:NO_LEFT: 紅包總額 = 預算總額;CAN_LEFT: 紅包總額 <= 預算總額public $formatType;
//預算剩餘⾦額
public $leftMoney;
public function __construct($option = null)
{
if($option instanceof OptionDTO)
{
$this->setOption($option);
}
}
public function setOption(OptionDTO $option) {
$this->totalMoney = $option->totalMoney;
$this->num = $option->num;
$this->formatType = $option->randFormatType; $this->minMoney = $option->rangeStart;
$this->maxMoney = $option->rangeEnd;
$this->leftMoney = $this->totalMoney;
}
/**
* 創建隨機紅包
*
* @access public
* @return void
*/
public function create()
{
$data = array();
if(false == $this->isCanBuilder())
{
return $data;
}
$leftMoney = $this->leftMoney;
for($i = 1;$i <= $this->num;$i++)
{
$data[$i] = $this->fx($i);
$leftMoney = $leftMoney - $data[$i];
}
//修數據
list($okLeftMoney,$okData) = $this->format($leftMoney,$data);
//隨機排序
shuffle($okData);
$this->leftMoney = $okLeftMoney;
return $okData;
}
/**
* 是否能夠發隨機紅包
* @access public
* @return void
*/
public function isCanBuilder()
{
if(false == is_int($this->num) || $this->num <= 0)
{
return false;
}
if(false == is_numeric($this->totalMoney) || $this->totalMoney <= 0) {
return false;
}
//均值
$avgMoney = $this->totalMoney / 1.0 / $this->num;
//均值⼩於最⼩值
if($avgMoney < $this->minMoney )
{
return false;
}
return true;
}
/**
* 獲取剩餘⾦額
* @access public
public function getLeftMoney()
{
return $this->leftMoney;
}
/**
* 隨機紅包⽣成函數。三⾓函數。[(1,0.01),($num/2,$avgMoney),($num,0.01)] * @param mixed $x,1 <= $x <= $this->num;
* @access public
* @return void
*/
public function fx($x)
{
if(false == $this->isCanBuilder())
{
return 0;
}
if($x < 1 || $x > $this->num)
{
return 0;
}
$x1 = 1;
$y1 = $this->minMoney;
//中間點
$x2 = ceil($this->num / 1.0 / 2);
//我的峰值
$y2 = $this->maxMoney;
//最後點
$x3 = $this->num;
$y3 = $this->minMoney;
//當x1,x2,x3都是1的時候(豎線)
if($x1 == $x2 && $x2 == $x3)
{
// '/_\'三⾓形狀的線性⽅程
//'/'部分
if($x1 != $x2 && $x >= $x1 && $x <= $x2)
{
、 $y = 1.0 * ($x - $x1) / ($x2 - $x1) * ($y2 - $y1) + $y1; return number_format($y, 2, '.', '');
}
//'\'形狀
if($x2 != $x3 && $x >= $x2 && $x <= $x3)
{
$y = 1.0 * ($x - $x2) / ($x3 - $x2) * ($y3 - $y2) + $y2; return number_format($y, 2, '.', '');
}
return 0;
}
/**
* 格式化修紅包數據
*
* @param mixed $leftMoney
* @param array $data
* @access public
* @return void
*/
private function format($leftMoney,array $data)
{
//不能發隨機紅包
if(false == $this->isCanBuilder())
{
return array($leftMoney,$data);
}
//紅包剩餘是0
if(0 == $leftMoney) //⽆需修數據
return array($leftMoney,$data);
}
//數組為空
if(count($data) < 1)
{
return array($leftMoney,$data);
}
//如果是可以有剩餘,並且$leftMoney > 0
if('Can_Left' == $this->formatType
&& $leftMoney > 0)
{
return array($leftMoney,$data);
}
// 如果還有餘錢,則嘗試加到⼩紅包⾥,如果加不進去,則嘗試下⼀個。while($leftMoney > 0)
{
$found = 0;
foreach($data as $key => $val)
{
//減少循環優化
if($leftMoney <= 0)
{
break;
}
//預判
$afterLeftMoney = (double)$leftMoney - 0.01;
$afterVal = (double)$val + 0.01;
if( $afterLeftMoney >= 0 && $afterVal <= $this->maxMoney)
{
$found = 1;
$data[$key] = number_format($afterVal,2,'.','');
$leftMoney = $afterLeftMoney;
//精度
}
}
//如果沒有可以加的紅包,需要結束,否則死循環
//也就是會出現每個紅包不分錢的情況,⽐如紅包都已經最⼤值。這時必須在分的時候給予標志,防⽌死循環。if($found == 0)
{
break;
}
}
//如果$leftMoney < 0 ,說明⽣成的紅包超過預算了,需要減少部分紅包⾦額
while($leftMoney < 0)
{
$found = 0;
foreach($data as $key => $val)
{
if($leftMoney >= 0)
{
break;
}
//預判
$afterLeftMoney = (double)$leftMoney + 0.01;
$afterVal = (double)$val - 0.01;
if( $afterLeftMoney <= 0 && $afterVal >= $this->minMoney)
{
$found = 1;
$data[$key] = number_format($afterVal,2,'.','');
$leftMoney = $afterLeftMoney;
$leftMoney = number_format($leftMoney,2,'.','');
}
}
//如果⼀個減少的紅包都沒有的話,需要結束,否則死循環
if($found == 0)
{
}
}
return array($leftMoney,$data);
}
}
//維護策略的環境類
class RedPackageBuilder
{
// 實例
protected static $_instance = null;
/**
* Singleton instance(獲取⾃⼰的實例)
*
* @return MemcacheOperate
*/
public static function getInstance()
{
if (null === self::$_instance)
{
self::$_instance = new self();
}
return self::$_instance;
}
/**
* 獲取策略【使⽤反射】
*
* @param string $type 類型
* @return void
*/
public function getBuilderStrategy($type) {
$class = $type.'PackageStrategy';
if(class_exists($class))
return new $class();
}
else
{
throw new Exception("{$class} 類不存在!");
}
}
public function getRedPackageByDTO(OptionDTO $optionDTO)
{
//獲取策略
$builderStrategy = $this->getBuilderStrategy($optionDTO->builderStrategy); //設置參數
$builderStrategy->setOption($optionDTO);
return $builderStrategy->create();
}
}
class Client
{
public static function main($argv)
{
//固定紅包
$dto = OptionDTO::create(1000,10,100,100,'Equal');
$data = RedPackageBuilder::getInstance()->getRedPackageByDTO($dto);
//print_r($data);
//隨機紅包[修數據]
$dto = OptionDTO::create(5,10,0.01,0.99,'RandTriangle');
$data = RedPackageBuilder::getInstance()->getRedPackageByDTO($dto); print_r($data);
//隨機紅包[不修數據]
$dto = OptionDTO::create(5,10,0.01,0.99,'RandTriangle','Can_Left');
$data = RedPackageBuilder::getInstance()->getRedPackageByDTO($dto);
//print_r($data);
}
¥
5.9
網路文庫VIP限時優惠現在開通,立享6億+VIP內容
立即獲取
微信紅包隨機數字_微信隨機紅包數詳解和演算法代碼
微信紅包隨機數字_微信隨機紅包數詳解和演算法代碼
1 需求
寫⼀個固定紅包 + 隨機紅包
固定紅包就是每個紅包⾦額⼀樣,有多少個就發多少個固定紅包⾦額就⾏。
隨機紅包的需求是。⽐如紅包總⾦額5元,需要發10個紅包。隨機范圍是 0.01到0.99;5元必需發完,⾦額需要有⼀定趨勢的正態分布。
(0.99可以任意指定,也可以是 avg * 2 - 0.01;⽐如avg = 5 / 10 = 0.5;(avg * 2 - 0.01 = 0.99))
第 1 頁
2 需求分析
2.1 固定紅包
如果是固定紅包,則演算法是⼀條直線。t就是固定紅包的額度。如圖。
f(x) = t;(1 <= x <= num)
image.png
2.2 隨機紅包
如果我們使⽤隨機函數rand。rand(0.01,0.99);那麼10次隨機,如果最壞情況都是⾦額0.99,總⾦額就是9.9元。會超過5元。⾦額也會不正態分布。最後思考了⼀下藉助與數學函數來當作隨機紅包的發⽣器,可以⽤拋物線,三⾓函數。最後選定了等腰三⾓線性函數。
第 2 頁
1 演算法原理
如果需要發紅包總⾦額是totalMoney,紅包個數是num個,⾦額范圍是[min,max],線性⽅程如圖。
image.png
三個點的坐標:
(x1,y1) = (1,min)
(x2,y2) = (num/2,max)
(x3,y3) = (num,min)
確定的線性⽅程:
$y = 1.0 * ($x - $x1) / ($x2 - $x1) * ($y2 - $y1) + $y1 ; (x1 <= x <= x2)
第 3 頁
$y = 1.0 * ($x - $x2) / ($x3 - $x2) * ($y3 - $y2) + $y2; (x2 <= x <= x3)
修數據:
y(合) = y1 + y2 + y3 +...... ynum;
y(合)有可能 > totalMoney ,說明⽣成⾦額多了,需要修數據,則從(y1,y2,y3.....ynum)這些每次減少0.01。直到y(合) = totalMoney。
y(合)有可能 < totalMoney ,說明⽣成⾦額少了,需要修數據,則從(y1,y2,y3.....ynum)這些每次加上0.01。直到y(合) = totalMoney。
第 4 頁
2 演算法原理樣例
如果需要發紅包總⾦額是11470,紅包個數是7400個,⾦額范圍是[0.01,3.09],線性⽅程如圖。
image.png
3 需求設計
3.1 類圖設計
image.png
3.2 源碼設計
/**
* 隨機紅包+固定紅包演算法[策略模式]
第 5 頁
*/
//配置傳輸數據DTO
class OptionDTO
{
//紅包總⾦額
public $totalMoney;
//紅包數量
public $num;
//范圍開始
public $rangeStart;
第 6 頁
//范圍結算
public $rangeEnd;
//⽣成紅包策略
public $builderStrategy;
//隨機紅包剩餘規則
public $randFormatType; //Can_Left:不修數據,可以有剩餘;No_Left:不能有剩餘public static function create($totalMoney,$num,$rangeStart,$rangEnd, $builderStrategy,$randFormatType = 'No_Left')
第 7 頁
{
$self = new self();
$self->num = $num;
$self->rangeStart = $rangeStart;
$self->rangeEnd = $rangEnd;
$self->totalMoney = $totalMoney;
$self->builderStrategy = $builderStrategy;
$self->randFormatType = $randFormatType;
return $self;
展開全文
App內免費讀全文
前往文庫APP簽到領暢讀卡,免費讀微信紅包隨機數字...全文
限免
導長圖
轉存到網盤
發送至微信
下載文檔
北京網路網訊科技有限公司 版本號8.0.70 隱私政策 許可權說明
版權說明:本文檔由用戶提供並上傳,收益專屬歸內容提供方,若內容存在侵權,請進行舉報或認領
第 8 頁
為您精選微信紅包隨機數字...會員文檔964篇
微信紅包隨機金額生成演算法模擬及應用
2537人閱讀
微信紅包隨機金額生成演算法模擬及應用
1455人閱讀
微信紅包金額真的是隨機分配的嗎?
2391人閱讀
微信紅包演算法分析及實現
2508人閱讀
獲取全部文檔4326人在看
基於你的瀏覽為你整理資料合集
微信紅包隨機數字_微信隨機紅包數詳解和演算法代碼
文件夾
微信紅包規律分析 - 網路文庫
3.6分
2906閱讀
人氣好文
五塊五個包怎麼猜紅包尾數 - 網路文庫
4.4分
1082閱讀
微信紅包隨機金額生成演算法模擬及應用 - 網路文庫
4.0分
1491閱讀
近期下載量飆升
剩餘10篇精選文檔
前往APP一鍵獲取全部合集
相關文檔
微信紅包隨機金額生成演算法模擬及應用
免費獲取全文
微信紅包隨機金額生成演算法模擬及應用
免費獲取全文
微信紅包金額真的是隨機分配的嗎?
免費獲取全文
微信紅包演算法分析及實現
免費獲取全文
微信發紅包數字含義大全課件.doc
2567人已閱讀
行業好評
微型計算機系統微機原理及應用試題庫及答案(可編輯)
2060人已閱讀
百里挑一
計算機網路系統投標書(技術部分)
1569人已閱讀
網路安全設備-網閘[整理版]
1108人已閱讀
ASP導出Excel數據的四種方法
2213人已閱讀
學校開展網路安全教育活動方案
1822人已閱讀
第3篇 綜合應用篇 綜合案例5 計算機網路應用綜合案例
2470人已閱讀
CPU針腳斷了怎麼焊接
1218人已閱讀
數據結構順序表的查找插入與刪除
1594人已閱讀
網路安全建設實施方案
1331人已閱讀
網路安全檢查自查表
1489人已閱讀
查看更多
推薦文檔集
『叄』 微信紅包122.5發怎麼成了122.50呢
這個系列文章已經整理了10篇,但都沒有涉及到具體的紅包演算法實現,主要有以下兩方面原因。
一方面是各社交/IM產品中的紅包功能同質化嚴重,紅包演算法的「可玩性」便是「核心競爭力所在」,這是同質化功能的差異化競爭思路,不會隨便公開。
另一方面,市場上還存在各種搶紅包插件這類灰產存在,一旦公開這些演算法,很可能又被這幫插件開發者們搞出什麼幺蛾子。
所以,這樣的情況下,如果要做社交/IM產品中的紅包功能,紅包隨便演算法該怎麼實現,基本上只能自已琢磨,很難找到大廠演算法直接套用。
本著即時通訊網一貫的im知識傳播精神,我收集整理並參考了大量的網上資料,綜合了比較靠譜的信息來源,便有了本文。本文根據有限的資料,分享了微信紅包隨機演算法實現中的一些技術要點,並整理了兩種比較靠譜的紅包演算法實現思路(含可運行的實現代碼),希望能給你的紅包演算法開發帶來啟發。
申明:本文資料整理自網路,僅供學習研究之用,如有不妥,請通知Jack Jiang。
學習交流:
- 移動端IM開發入門文章:《新手入門一篇就夠:從零開發移動端IM》
- 開源IM框架源碼:
https://github.com/JackJiang2011/MobileIMSDK
本文已同步發布於「即時通訊技術圈」公眾號。
2、系列文章
《社交軟體紅包技術解密(一):全面解密QQ紅包技術方案——架構、技術實現等》
《社交軟體紅包技術解密(二):解密微信搖一搖紅包從0到1的技術演進》
《社交軟體紅包技術解密(三):微信搖一搖紅包雨背後的技術細節》
《社交軟體紅包技術解密(四):微信紅包系統是如何應對高並發的》
《社交軟體紅包技術解密(五):微信紅包系統是如何實現高可用性的》
《社交軟體紅包技術解密(六):微信紅包系統的存儲層架構演進實踐》
《社交軟體紅包技術解密(七):支付寶紅包的海量高並發技術實踐》
《社交軟體紅包技術解密(八):全面解密微博紅包技術方案》
《社交軟體紅包技術解密(九):談談手Q春節紅包的設計、容災、運維、架構等》
《社交軟體紅包技術解密(十):手Q客戶端針對2020年春節紅包的技術實踐》
《社交軟體紅包技術解密(十一):最全解密微信紅包隨機演算法(含演示代碼)》(* 本文)
3、微信紅包演算法要點匯總
這是目前能找到的僅有的一份,有微信團隊人員參與的微信紅包演算法技術要點的討論資料。分享於2015年,差不多是微信紅包剛火沒多久,大概是微信技術團隊的人當時沒有現在這些技術之外的顧慮,所以作了有限的分享,資料難得,本次重新整理了一下,可以作為參考資料使用。以下是資料正文。
資料來源:來自InfoQ的某架構群的技術討論,由朱玉華整理(個人博客是:zhuyuhua.com(目前已無法訪問))。
資料背景:起因是有朋友在朋友圈咨詢微信紅包的架構,於是在微信團隊成員參與討論的情況下,我(指「朱玉華」)整理了這次討論的技術要點,也就是下面的內容(內容為問答形式)。
3.1、演算法實現的技術要點
【1】問:微信的金額什麼時候算?
答:微信金額是拆的時候實時算出來,不是預先分配的,採用的是純內存計算,不需要預算空間存儲。
為什麼採取實時計算金額?原因是:實時效率更高,預算才效率低下。預算還要佔額外存儲。因為紅包只佔一條記錄而且有效期就幾天,所以不需要多大空間。就算壓力大時,水平擴展機器是。
【2】問:關於實時實時性,為什麼明明搶到紅包,點開後發現沒有?
答:2014年的紅包一點開就知道金額,分兩次操作,先搶到金額,然後再轉賬。
2015年的紅包的拆和搶是分離的,需要點兩次,因此會出現搶到紅包了,但點開後告知紅包已經被領完的狀況。進入到第一個頁面不代表搶到,只表示當時紅包還有。
【3】問:關於分配演算法,紅包里的金額怎麼算?為什麼出現各個紅包金額相差很大?
答:隨機,額度在 0.01 和剩餘平均值 2 之間。 例如:發 100 塊錢,總共 10 個紅包,那麼平均值是 10 塊錢一個,那麼發出來的紅包的額度在 0.01元~20元之間波動。
當前面 3 個紅包總共被領了 40 塊錢時,剩下 60 塊錢,總共 7 個紅包,那麼這 7 個紅包的額度在:0.01~(60/7 * 2)=17.14之間。
注意:這里的演算法是每被搶一個後,剩下的會再次執行上面的這樣的演算法(Tim老師也覺得上述演算法太復雜,不知基於什麼樣的考慮)。
這樣算下去,會超過最開始的全部金額,因此到了最後面如果不夠這么算,那麼會採取如下演算法:保證剩餘用戶能拿到最低1分錢即可。
如果前面的人手氣不好,那麼後面的余額越多,紅包額度也就越多,因此實際概率一樣的。
【4】問:紅包的設計
答:微信從財付通拉取金額數據過來,生成個數/紅包類型/金額放到redis集群里,app端將紅包ID的請求放入請求隊列中,如果發現超過紅包的個數,直接返回。根據紅包的邏輯處理成功得到令牌請求,則由財付通進行一致性調用,通過像比特幣一樣,兩邊保存交易記錄,交易後交給第三方服務審計,如果交易過程中出現不一致就強制回歸。
【5】問:並發性處理:紅包如何計算被搶完?
答:cache會抵抗無效請求,將無效的請求過濾掉,實際進入到後台的量不大。cache記錄紅包個數,原子操作進行個數遞減,到 0 表示被搶光。財付通按照 20萬筆每秒入賬准備,但實際還不到 8萬每秒。
【6】問:通如何保持8w每秒的寫入?
答:多主sharding,水平擴展機器。
【7】問:數據容量多少?
答:一個紅包只佔一條記錄,有效期只有幾天,因此不需要太多空間。
【8】問:查詢紅包分配,壓力大不?
答:搶到紅包的人數和紅包都在一條cache記錄上,沒有太大的查詢壓力。
【9】問:一個紅包一個隊列?
答:沒有隊列,一個紅包一條數據,數據上有一個計數器欄位。
【10】問:有沒有從數據上證明每個紅包的概率是不是均等?
答:不是絕對均等,就是一個簡單的拍腦袋演算法。
【11】問:拍腦袋演算法,會不會出現兩個最佳?
答:會出現金額一樣的,但是手氣最佳只有一個,先搶到的那個最佳。
【12】問:每領一個紅包就更新數據么?
答:每搶到一個紅包,就cas更新剩餘金額和紅包個數。
【13】問:紅包如何入庫入賬?
答:資料庫會累加已經領取的個數與金額,插入一條領取記錄。入賬則是後台非同步操作。
【14】問:入帳出錯怎麼辦?比如紅包個數沒了,但余額還有?
答:最後會有一個take all操作。另外還有一個對賬來保障。
【15】問:既然在搶的時候有原子減了就不應該出現搶到了拆開沒有的情況?
答:這里的原子減並不是真正意義上的原子操作,是Cache層提供的CAS,通過比較版本號不斷嘗試。
【16】問:cache和db掛了怎麼辦?
答:主備 +對賬。
【17】問:為什麼要分離搶和拆?
答:總思路是設置多層過濾網,層層篩選,層層減少流量和壓力。
這個設計最初是因為搶操作是業務層,拆是入賬操作,一個操作太重了,而且中斷率高。 從介面層面看,第一個介面純緩存操作,搞壓能力強,一個簡單查詢Cache擋住了絕大部分用戶,做了第一道篩選,所以大部分人會看到已經搶完了的提示。
【18】問:搶到紅包後再發紅包或者提現,這里有什麼策略嗎?
答:大額優先入賬策略。
針對上面的技術要點,有人還畫了張原理圖(這是網上能找到的相對清晰的版本):
3.2、微信搶紅包的過程模擬
針對上節中整理的資料,當有人在微信群里發了一個 N 人的紅包、總金額 M 元,後台大概的技術邏輯如下。
3.2.1)發紅包後台操作:
1)在資料庫中增加一條紅包記錄,存儲到CKV,設置過期時間;
2)在Cache(可能是騰訊內部kv資料庫,基於內存,有落地,有內核態網路處理模塊,以內核模塊形式提供服務))中增加一條記錄,存儲搶紅包的人數N。
3.2.2)搶紅包後台操作:
1)搶紅包分為搶和拆:搶操作在Cache層完成,通過原子減操作進行紅包數遞減,到0就說明搶光了,最終實際進入後台拆操作的量不大,通過操作的分離將無效請求直接擋在Cache層外面。
這里的原子減操作並不是真正意義上的原子減操作,是其Cache層提供的CAS,通過比較版本號不斷嘗試,存在一定程度上的沖突,沖突的用戶會放行,讓其進入下一步拆的操作,這也解釋了為啥有用戶搶到了拆開發現領完了的情況。
2)拆紅包在資料庫完成:通過資料庫的事務操作累加已經領取的個數和金額,插入一條領取流水,入賬為非同步操作,這也解釋了為啥在春節期間紅包領取後在余額中看不到。
拆的時候會實時計算金額,其金額為1分到剩餘平均值2倍之間隨機數,一個總金額為M元的紅包,最大的紅包為 M * 2 /N(且不會超過M),當拆了紅包後會更新剩餘金額和個數。財付通按20萬筆每秒入賬准備,實際只到8萬每秒。
『肆』 微信偽造紅包代碼
微信偽造紅包代碼
假微信紅包代碼 - CSDN
[圖文] csdn已為您找到關於假微信紅包代碼相關內容,包含假微信紅包代碼相關文檔代碼介紹、相關教程視頻課程,以及相關假微信紅包代碼問答內容.為您解決當下相關問題,如果想了解...
CSDN技術社區
2022-03-21
微信偽造紅包代碼 - CSDN技術社區
模仿微信發紅包代碼_lufei_le的博客-CSDN博客
//紅包個數 int money = 100;// 金額 //獲取每個人大概平均錢數. List<Float> result = getAll(size, money); //檢查總錢數 float ...
2016-03-01
C++微信紅包模擬_微信假紅包生成代碼_天傷星-武松的博客-CSDN博客
2022-03-21
java微信紅包開發_java寫的偽微信紅包功能示例代碼_Linda Jiang的博客-CSDN博客
2021-02-16
CSDN技術社區
查看更多
微信可以點的假紅包代碼,微信紅包代碼 九塊九手游導航
[圖文] 微信,搶紅包,源代碼 name gitignore buildgradle gradleproperties gradlewbat qianghongbaoapk QiangHongBaoiml RE...
jiubaoyou.cn
2021-10-24
大家還在搜
代碼生成器
2023紅包封面領取碼
假紅包生成器
紅包轉賬生成器
紅包生成器在線製作
紅包代碼大全
二維碼紅包生成器
紅包代碼一鍵生成
假紅包代碼復制
紅包怎樣立即退還
假紅包代碼大全
微信紅包代碼大全
紅包代碼大全可復制
假紅包代碼生成器
微信紅包裝b生成器
微信裝b專用代碼
微信假紅包消息文字
微信假紅包生成器
微信紅包生成器
微信假紅包代碼復制
微信假紅包代碼整人
微信紅包特效代碼
微信假紅包代碼一鍵生成器
假紅包代碼復制微信
微信假紅包一鍵生成器
微信紅包惡搞代碼可復制
微信假紅包代碼鏈接
假微信紅包生成器
微信紅包惡搞生成器
代碼生成器
微信可以點的假紅包代碼
假紅包生成器
java寫的偽微信紅包功能示例代碼 - java - 腳本之家
這篇文章主要介紹了java寫的偽微信紅包功能示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學...
腳本之家
2019-08-08
模仿微信發紅包代碼 - 網路文庫
發布時間:2023-01-26
模仿微信發紅包代碼 import java.util.ArrayList; import java.util.List; /** * Description: <br> * * @author <a href=mailto:[email protected]>連樂</a> * @date 2016/3/1 12:10 */ public class ...
網路文庫
微信偽造紅包代碼_相關推薦
假紅包代碼復制
假紅包代碼大全
紅包代碼大全可復制
微信紅包裝b生成器
微信假紅包的代碼,知識教學,其他知識教學,好看視頻
微信假紅包的代碼,本視頻由不知名的小峰提供,0次播放,好看視頻是由網路團隊打造的集內涵和顏值於一身的專業短視頻聚合平台
好看視頻
2022-01-04
java寫的偽微信紅包功能示例代碼 - 編程語言 - 億速雲
// 紅包錢數(以分為單位),個數 wx.WXMoney(1000, 50); } public void WXMoney(int sum, int num) { // 創建一個hashmap,把分配出來的人和錢順序打亂 Map<Integer, Integer> ...
m.yisu.com
2020-10-21
仿微信隨機紅包代碼 - 編程語言 - 億速雲
public int num = 100; public int money = 2000; public int max = 88; public int min = 1; private void DataBing() { Random rd = new Random(); List<int> list_ten = new List<int>(); for (int i = ...
m.yisu.com
2020-07-28
java寫的偽微信紅包功能示例代碼 - java基礎 - 穀穀點程序
性能優化點:1 使用int不使用double.(單位用分不用元)也省去了還要用math round四捨五入,把double類型數據只留小數點後前兩位.2 random() 方法用於返回一個隨機數,隨...
www.3qphp.com
2023-01-24
模仿微信發紅包代碼 - iteye
NULL 博文鏈接:https://lufei-le.iteye.com/blog/2279750
www.iteye.com
2019-09-15
下一頁
相關搜索
代碼生成器
紅包轉賬生成器
假紅包生成器
紅包代碼一鍵生成
紅包生成器在線製作
假紅包代碼復制
2023紅包封面領取碼
紅包代碼
二維碼紅包生成器
假紅包代碼大全
紅包代碼大全可復制
微信裝b專用代碼
微信紅包裝b生成器
微信紅包生成器
紅包怎樣立即退還
微信假紅包消息文字
假紅包代碼生成器
微信紅包特效代碼
微信紅包代碼大全
假紅包代碼復制微信
微信假紅包代碼整人
微信假紅包一鍵生成器
微信假紅包代碼鏈接
微信紅包代碼
微信假紅包生成器
微信假紅包生成代碼
微信假紅包代碼復制
假紅包代碼
假微信紅包生成器
微信假紅包代碼
微信偽造紅包代碼
首頁-免責-用戶反饋
『伍』 C語言 微信紅包
#include<stdio.h>
#include<string.h>
#include<time.h>
#defineMAX_TOTAL_MONEY200//紅包的最大金額
#defineMIN_PER_PLAYER1//一個人搶到的的最小面額1元
#defineMAX_PLAYER_CNT(MAX_TOTAL_MONEY/MIN_PER_PLAYER)//最大搶紅包的游戲人數
typedefstructplayer
{
char*name;//標記玩家可以不填
unsignedintmoney_get;//搶到的紅包
}PLAYER_T;
//每個人領取到的紅包金額不等這個要求比較難搞暫時不考慮
intmain(intargc,char*argv[])
{
unsignedinttotal_money=0;//不考慮角和分浮點運算比較復雜
unsignedintplayer_cnt=0;
inton_off=0;
inti=0;
intj=0;
PLAYER_Tplayer[MAX_PLAYER_CNT]={0};
PLAYER_Ttmp={0};
printf("輸入紅包金額: ");
scanf("%u",&total_money);
printf("輸入游戲人數: ");
scanf("%u",&player_cnt);
printf("是否需要減小貧富差距(0為關閉其餘為開啟): ");
scanf("%u",&on_off);
//不符合規則的輸入判斷
if(total_money>MAX_TOTAL_MONEY||0==total_money||0==player_cnt||player_cnt*MIN_PER_PLAYER>total_money)
{
printf("紅包金額最小%u元最大%u元游戲人數最小1人最大%u人 ",MIN_PER_PLAYER,MAX_TOTAL_MONEY,MAX_PLAYER_CNT);
return0;
}
for(i=0;i<player_cnt;i++)
{
//設置隨機種子
srand(time(NULL)+i);
//根據隨機種子獲取一個偽隨機數作為搶到的紅包並通過余運算使其始終小於total_money
player[i].money_get=rand()%total_money;
//限制所有人所能搶到的最大紅包為當前金額池的1/5而不是全部
if(0!=on_off)
{
if(total_money>5)//5塊錢以上再限制
{
player[i].money_get=rand()%(total_money/5);
}
}
//最後一個人拿所有剩下的紅包
if(player_cnt-1==i)
{
player[i].money_get=total_money;
}
//運氣差隨機到0元給你最小面額
elseif(0==player[i].money_get)
{
player[i].money_get=MIN_PER_PLAYER;
}
//剩下的要保證每個人能搶到最小面額
elseif(total_money-player[i].money_get<(player_cnt-i-1)*MIN_PER_PLAYER)
{
player[i].money_get=total_money-(player_cnt-i-1)*MIN_PER_PLAYER;
}
//把搶到的金額從紅包池中減掉
total_money-=player[i].money_get;
//如果填了name可以把名字列印出來
printf("第%d個玩家搶到紅包:%u元 ",i+1,player[i].money_get);
}
//冒泡排序找出手氣最佳者
for(i=0;i<player_cnt;i++)
{
for(j=i+1;j<player_cnt;j++)
{
if(player[i].money_get<player[j].money_get)
{
memcpy(&tmp,&player[j],sizeof(PLAYER_T));
memcpy(&player[j],&player[i],sizeof(PLAYER_T));
memcpy(&player[i],&tmp,sizeof(PLAYER_T));
}
}
}
printf("手氣最佳者搶到紅包:%u元 ",player[0].money_get);//如果填了name可以把名字列印出來
return0;
}