高い同時実行赤の全体的なデザイン

ビジネス側に基づいて同社いくつかの時間前には、オンライン、赤い封筒の活動をつかむか、多くの情報を検索するために行う必要があります。全体のデザインのアイデアや記録の過程における動作上の問題の様々な。

品へのニーズ:

1.赤支持配置開始時刻、終了時刻、タイプ(固定量又はランダム量)、単一赤色最小量、赤の最大の単一量

2.赤い封筒の経営状況を受け取ることができます(サービス情報に基づいて、いくつかの条件が人を指定満足つかむ場合があります)
QQのスクリーンショット20180507142703.png

アイデアを設計します。

問題1:アルゴリズムの赤(赤封筒構成設定最大値、最小量は、生成された資格の数に応じて)

赤色最大と赤単一構成の最小量は、完全にランダム使用量を割り当てることができないからです。

そこで彼は、要求されました:

    *シングル量に必要な最小量よりも赤も少ない最大量より
    *赤色の数と合計金額を正確に端点に記載されるように

* 单个红包精确到分,也就是小数点后两位

実装コード:

    /*
    * @todo 设置随机红包金额
    * return array
    */
    public function setRandMoney()
    {
        $result = [];
        //取小数点后两位将金额乘100
        $this->total = $this->total * 100;//红包总金额
        $this->min = $this->min * 100;//单个红包最小金额
        $this->max = $this->max * 100;//单个红包最大金额
        //获取红包平均金额
        $average = $this->total / $this->num;

        for ($i = 0; $i < $this->num; $i++) {
        //因为小红包的数量通常是要比大红包的数量要多的,因为这里的概率要调换过来。
        //当随机数>平均值,则产生小红包
        //当随机数<平均值,则产生大红包
            if (rand($this->min, $this->max) > $average) {
        // 在平均线上减钱
                $temp = $this->min + $this->xRandom($this->min, $average);
                $result[$i] = $temp;
                $this->total -= $temp;
            } else {
        // 在平均线上加钱
                $temp = $this->max - $this->xRandom($average, $this->max);
                $result[$i] = $temp;
                $this->total -= $temp;
            }
        }
        // 如果还有余钱,则尝试加到小红包里,如果加不进去,则尝试下一个。
        while ($this->total > 0) {
            for ($i = 0; $i < $this->num; $i++) {
                if ($this->total > 0 && $result[$i] < $this->max) {
                    $result[$i]++;
                    $this->total--;
                }
            }
        }
      // 如果钱是负数了,还得从已生成的小红包中抽取回来
        while ($this->total < 0) {
            for ($i = 0; $i < $this->num; $i++) {
                if ($this->total < 0 && $result[$i] > $this->min) {
                    $result[$i]--;
                    $this->total++;
                }
            }
        }
        if (!empty($result)) {
            //将红包放入队列之中
            foreach ($result as $val) {
                $this->redis->lPush($this->redpack_money_queue . $this->act_id, $val / 100);
            }
            return ['code' => '0', 'msg' => 'success'];
        }
        return ['code' => '1', 'msg' => '创建红包失败,请检查参数'];

    }


    /**
     * 生产min和max之间的随机数,但是概率不是平均的,从min到max方向概率逐渐加大。
     * 先平方,然后产生一个平方值范围内的随机数,再开方,这样就产生了一种“膨胀”再“收缩”的效果。
     */
    private function xRandom($bonus_min, $bonus_max)
    {
        $sqr = intval($this->sqr($bonus_max - $bonus_min));
        $rand_num = rand(0, ($sqr - 1));
        return intval(sqrt($rand_num));
    }

    private function sqr($n)
    {
        return $n * $n;
    }

次いで、100倍の時の処理量、前回とは100れ、加えて、その結果をキューにINTVAL()関数を使用して撮影した時間の最小値と最大量の間の乱数は、アルゴリズムは、整数を処理することができるさせるためそれは2桁まで正確です。

難易度2:高い同時実行サーバー上の圧力へのアクセス
と同様のグラブ赤い封筒、1元の購買、スパイクやその他のビジネスシナリオは、サーバーへのリクエストが多数の同じ時間蓄積全くあり、しかし、資源制約、ハンドルにプログラムへのサーバーの原因となります。私たちがしなければならないので、流れを制御するために、直接Webサーバのデータベース層を介して多数の要求を打つことではありません。その後、URLにアクセスするためのユーザーからの全体のプロセスの結果を返したが、それが何であるかを受け取りますか?

  • 客户端层、ユーザーがマイクロ手紙の中でURLを開き、DNSサーバは、ドメイン名を解決するには
  • web服务器层Apache、nginxのか、Tomcatの、など
  • 服务器层ロジック処理パラメータを受信するための、PHP-FPM割り当てプロセス、コード
  • 数据持续化层次MySQLやRedisのレベルに結果を保存します

クライアント層の最適化:(制限)

  1. 静的なHTMLページのコンテンツ使用してフロントエンドの表示URLサーバーの帯域幅の圧力を低下させる、可能な限り圧縮し、ページ表示画像を。推奨base64でデコードされたピクチャ
  2. 接続プールを使用してフロー制御をユーザーがクリックは、赤い封筒を取得するときに開始するために、ajax書き込みには、Javaを使用してコールバック要求redis incrバックグラウンド・コードと、そのキーに対処する際のインタフェース、キー+1の各呼び出し、およびインクリメントIDリターンを、失う、以来、incrエネルギー自給原子レベル、フロントエンドは、現在待機中で多くのユーザーを持つことができます。よると、自分のサーバーの構成およびビジネスシナリオはN複数の要求を予測Nに処理要求の数は現在、フロントエンドユーザーの作業を行うよう求めている待っているよりも大きい場合は「過剰現在のリクエスト、後でもう一度やり直してください」、サーバーで問題が発生し、またその逆できるが、通常の要求を開始することができます。

ウェブ最適化層(LUA + nginxの周波数制御)

  1. そこのアクセス制御の多様性を処理するために、nginxの方法、また達成するためにさまざまな効果、IPへのアクセス、制限されたコンテンツへのアクセス、アクセス制限の周波数を有します。

主に非常に同時環境すばやくアクセス制御のための需要のためにnginxの+のLua + Redisのを行うにはアクセス制限。

nginxの要求は、すなわち、11段階の合計に分かれて処理されます。

`post-read、server-rewrite、find-config、rewrite、post-rewrite、 preaccess、access、post-access、try-  files、content、log`.


在openresty中,可以找到:

`set_by_lua`,`access_by_lua`,`content_by_lua`,`rewrite_by_lua`等方法。

那么访问控制应该是,`access`阶段。


それは、特定のピークを超えた場合に、各領収書は、接続プールのIDでURLグラブ赤増分をRedisの後、要求のIPは、トラフィックを制御するために、ページジャンプが待機します。
特定のコンフィギュレーション手法を参照:HTTP://homeway.me/2015/08/11 / ...

(等髪複数を防止するために、繰り返し受け、パーミッション、)PHPコード層

  1. 使用redis queueスーパー、計算エンベロープの各々の制御にキューイングをlpushブロッキングモードをRedisのキューであるため、そうキューが空である場合、その都度最後封筒消費のための要求を受信した後キューにデータを返さない、赤い封筒が同時に発生したときに人に割り当てることはしないように保証することができます。
  2. 使用redis list状況の繰り返しを制御するコレクションは、要求がコレクションを受け取ったユーザIDを配置した後に受信されるたびに受け取る(これは重要である、なぜなら同時原因重複コレクションでは発生しません、消費者の目の前にキューにコレクションを置くことを確認してください)そして、消費がそれ以外の場合は、セットからそれを受信しています、成功したジャンプです。
  3. ビジネスはそれらに対処する必要があるため、あなたは人員配置のセットを受信するイベントに基づいてルールを作成する場合には、あなたがコントロールのセットを受信する権利の判断を使用することができ、非常に面倒です。

以下は、(サイドディッシュ、偉大な神はスプレーしない)を達成するために私のコードです

   /*
    * @todo 获取红包金额
    * @return array
    */
    public function doRush()
    {
        $act_info = $this->getPackInfo($this->act_id);
        if(empty($act_info)){
            return ['code'=>'1','msg'=>'活动信息错误,请联系管理员'];
        }
        if($act_info['start_time'] > now()){
            return ['code'=>'2','msg'=>"红包尚未开抢,请稍后再试"];
        }

        if($act_info['end_time'] <= now()){
            return ['code'=>'1','msg'=>'活动已结束'];
        }
         //将请求用户先放置已领取的集合中
        if(!$this->redis->sAdd($this->rushed_list_key,$this->user_id)){
            return ['code'=>'1','msg'=>'每个红包只能领取一次哦'];
        }
        $money = $this->redis->lPop($this->redpack_money_queue);
        if(empty($money)){
            $this->redis->sRem($this->rushed_list_key,$this->user_id);
            return ['code'=>'1','msg'=>'您来完了呦,红包已抢光'];
        }

        //将已抢的用户和金额记录至队列中
        $add_res = $this->amountAdd($money);
        if($add_res['code'] != 0){
            return ['code'=>'1','msg'=>'系统繁忙,请稍后再试'];
        }
        return ['code'=>'0','msg'=>'success','data'=>$money.'元'];

    }

(非同期の永続性を使用して)、データ層

  1. ユーザが預金の量のユーザID及び収集を受信していると、成功した受信後redis queue、非同期プロセスに従ってUSER_IDと貨幣価値は、MySQLテーブルにそのデータを更新します

--------------------------------------------------私はラインを割る悪でした-------------------------------------------- ----------------------

:追加情報
これは、すでに非常に良いおかずである私のために書き込みに私の最初の実際の開発プロセスだけでなく、アイデア、そして偉大な神は、スプレーしないことを祈ります。赤と、プログラムとの最初の接点であるいくつかの処理アルゴリズムは、情報のオンライン参照の多くは、多くのことを学びました。あなたが何かを持っている場合は、より良いソリューションより交流~~

                                                                                                                                ----PHP小菜一枚------





おすすめ

転載: www.cnblogs.com/homehtml/p/11931475.html