PHPは微信のランダムなお年玉のアルゴリズムと微信のお年玉のアーキテクチャの設計の紹介を実現します

5900 ワード

微信お年玉のアーキテクチャ設計の概要:
原文:https://www.zybuluo.com/yulin718/note/93148
 
@QConのある高可用性アーキテクチャ群の整理、朱玉華の整理に由来する.
背景:ある友达が友达の輪で微信のお年玉の構造を聞いて、そこで下の文字がありました(間違いがあったら提出してください、ありがとうございます)
概況:2014年の微信のお年玉はデータベースを使って全体の流量に抵抗し、2015年にcacheを使って流量に抵抗した.
1、微信の金額はいつ計算しますか. 
答え:微信の金額は分解時にリアルタイムで算出され、予め割り当てられたものではなく、純メモリ計算を採用しており、予算空間の記憶は必要ありません. 
リアルタイム計算金額の考慮:予算はストレージを占有する必要があり、リアルタイム効率が高く、予算は効率が低い.
2、リアルタイム性:どうしてお年玉を手に入れたのに、注文してから気づいたの? 
答え:2014年のお年玉は少し開くと金額がわかり、2回に分けて操作し、まず金額を奪ってから振り替えます. 
2015年のお年玉の取り外しと奪い合いは分離されており、2回注文する必要があるため、お年玉が奪われることになりますが、注文してからお年玉が受け取られた状況をお知らせします.最初のページに入ると、奪ったわけではありません.お年玉がまだあったことを示しています.
3、分配:お年玉の金額はどう計算しますか.どうして各お年玉の金額が大きく異なるのですか? 
答え:ランダムで、額は0.01と残りの平均値*2の間にあります. 
例えば、100元で、全部で10個のお年玉を出すと、平均値は10元で、そのお年玉の額は0.01元~20元の間で変動します. 
前の3つのお年玉が全部で40元受け取ったとき、60元残って、全部で7つのお年玉が残っていると、この7つのお年玉の額は0.01~(60/7*2)=17.14の間にあります. 
注意:ここのアルゴリズムは1つ奪われるたびに、残りは再び上記のようなアルゴリズムを実行します(Tim先生も上記のアルゴリズムが複雑すぎて、どのような考えに基づいているのか分かりません).
このように計算すると、最初の全金額を超えるため、最後尾で計算が足りなければ、残りのユーザーが最低1銭を受け取ることを保証すればよいというアルゴリズムが取られます.
前の人が調子が悪いと、後ろの残高が多ければ多いほど、お年玉の額も多くなるので、実際の確率は同じです.
4、お年玉のデザイン 
答:微信は财付通から金额データ郭莱を引き出し、个数/お年玉タイプ/金额を生成してredisクラスタに入れ、app端はお年玉IDの要求を要求キューに入れ、お年玉を超える个数を见つけたら、直接返す.お年玉の裸祭処理によってトークン要求が成功すると、財付通が一致性呼び出しを行い、ビットコインのように両側に取引記録を保存することで、取引後に第三者サービス監査に渡し、取引中に一致しなければ強制的に復帰する.
5、発性処理:お年玉はどのように計算して奪われたのですか? 
答え:cacheは無効な要求に抵抗し、無効な要求をフィルタリングし、実際にバックグラウンドに入る量は大きくありません.Cacheはお年玉の個数を記録し,原子操作は個数を減らし,0になると奪われたことを示す.財付通は20万件の毎秒入金準備をしているが、実際には8万件にも満たない.
6、通はどのように8 w毎秒の書き込みを維持しますか? 
答え:マルチマスターsharding、水平拡張マシン.
7、容量はいくらですか. 
答え:お年玉は1つの記録しか占めておらず、有効期間は数日しかないので、あまりスペースは必要ありません.
8、お年玉の配分を聞いて、プレッシャーは大きいですか? 
答え:お年玉を奪った人数とお年玉はすべて1本のcache記録の上で、あまりクエリーの圧力がありません.
9、お年玉一つ、行列一つ? 
答え:キューがなく、お年玉とデータがあり、データにはカウンタフィールドがあります.
10、お年玉ごとの確率が均等であることをデータから証明していますか? 
答え:絶対均等ではなく、簡単な頭を叩くアルゴリズムです.
11、頭を叩くアルゴリズム、2つの最適なものが現れますか? 
答え:金額は同じですが、手加減が一番いいのは一つだけで、先に奪ったほうがいいです.
12、お年玉をもらうたびにデータを更新しますか? 
答え:お年玉を1つ奪うたびに、casは残りの金額とお年玉の個数を更新します.
13、お年玉はどうやって入庫しますか. 
データベースはすでに受け取った個数と金額を加算し、受け取り記録を挿入します.入金はバックグラウンド非同期操作です.
14、入金ミスはどうしますか.例えばお年玉の数がなくなったが、残高はまだありますか? 
答え:最後にtake all操作があります.もう一つの対帳で保障されています.
 
 
PHPを使ってお年玉を出して、私达がお年玉の数量と総金额を入力する时、PHPはこの2つの値によってランダムに各金额を分配して、すべての人がすべて1つのお年玉を受け取ることができることを保证して、各お年玉の金额は等しくなくて、お年玉の金额に差があることを要求して、すべてのお年玉の総额は総金额に等しいはずです.
まず法則を分析します.
総金額を10元に設定し、N人がランダムに受け取る.
N=1先頭
お年玉の金額=X元です.
N=2 2 2番目
2番目のお年玉が正常に発行されることを保証するために、1番目のお年玉の金額=0.01から9.99の間のランダムな数です.
2番目のお年玉=10-最初のお年玉の金額;
N=3番目
お年玉1=0.01~9.99のランダム数
お年玉2=0.01から(10-お年玉1-0.01)までのランダム数
お年玉3=10-お年玉1-お年玉2
……
そこで、現在のお年玉の金額を割り当てるときに、残りの紅白に必要な最低限の金額を予約し、0.01から総金額-予約金額の間で乱数を取り、得られた乱数が現在のお年玉の金額であるという法則を得た.
実際の応用の中で、プログラムはまずお年玉の金額を分配して、つまりお年玉を出す時、お年玉の個数と各お年玉の金額はすべて分配して、それではユーザーがお年玉を奪い取りに来た時、私達はランダムにユーザーに1つのお年玉を返します.
微信お年玉分配アルゴリズムコード:
$total=19.5;//     
$num=9;//   10   ,  10     
$min=0.01;//        0.01 
$money_arr=array(); //          
for ($i=1;$i<$num;$i++)
{
    $safe_total=($total-($num-$i)*$min)/($num-$i);//      
    $money= mt_rand($min*100,$safe_total*100)/100;
    $total=$total-$money;
    $money_arr[]= $money;
    echo ' '.$i.'   :'.$money.'  ,  :'.$total.'   '."
"; } echo ' '.$num.' :'.round($total,2).' , :0 '; $money_arr[] = round($total,2); dd($money_arr);

 
上記のコードを実行すると、次の結果が出力されます.
1つ目のお年玉:2.15元、残高:17.35元 第2個のお年玉:1.46元、残高:15.89元 3つ目のお年玉:2.23元、残高:13.66元 4つ目のお年玉:2.43元、残高:11.23元 5番目のお年玉:2.37元、残高:8.86元 6番目のお年玉:0.1元、残高:8.76元 7番目のお年玉:2.26元、残高:6.5元 8番目のお年玉:2.09元、残高:4.41元 9番目のお年玉:4.41元、残高:0元
以上phpを使って微信のお年玉を出すプログラムを実現して、みんなに役に立つことを望みます!