スパイク設計アーキテクチャモデル

オリジナル: スパイクアーキテクチャモデルの設計

はじめに:私はキビの電話スパイク、多くの人々がこのようなJingdongはや淘宝網スパイクとして、スパイクのシステムを見ていると信じて、当時スパイクシステムは、それを達成する方法ですか?どのように我々はそれをスパイクするためにシステムを設計していますか?スパイクシステムでは何の問題は考慮すべき?スパイクする堅牢なシステムを設計するには?この問題は、我々はこの問題を調査するつもりです。

 

ブログのディレクトリ

考慮すべきスパイクシステムの問題:

II:デザインと技術的ソリューションスパイクシステム

3:システムアーキテクチャ

4:要約

:どのような問題がスパイクと見なされるべきです

1.1:売られ過ぎの問題

   分析スパイクビジネスシナリオは、最も重要なことは売られ過ぎの問題で、売られ過ぎた場合、一般的な、比較的低価格スパイクシステムでは、唯一の100が、最終的に売られ過ぎの200をストックすることは真剣に会社の財産上の利益に影響を与える場合したがって、問題の矢面に立つことは売られ過ぎの商品を解決することです。

1.2:高い同時実行

スパイクは、並行処理機能を大量に短い時間を持って、同社は通常、センセーショナルな効果を作成する一方で、わずか数分の期間をスパイク、ユーザーの参加は非常に飛びつかれます、ユーザーを引き付けるために、非常に低価格になります。短時間

データベースの問題を考慮する必要が敗北し、過度の破損や故障に起因するバックエンドのキャッシュの同時実行を防ぐためにどのように、多数の要求が殺到にあります。

1.3:アンチブラシインタフェース

今、それらのほとんどは、ソフトウェアに対応するスパイクスパイクのために出てくるだろう、このようなソフトウェアは常にシミュレートしますバックエンドサーバに要求を送信し、時間の一秒数百人が開始続けてリクエストを防ぐために、このようなソフトウェアの不正な要求を繰り返しを防ぐためにどのように、非常に一般的です我々はまた、標的に検討する必要があります

1.4:スパイクURL

平均的なユーザーのために、比較的簡単なスパイクページを参照してください、それが指定した時間に達すると、ボタンが、グレーアウトされてスパイク、指定した時間を満たしていない、灰色のボタンがクリック可能になります。それはユーザーのコンピュータの知識の少しがある場合は、このセクションでは、白のユーザーのためにある、ネットワークが表示されますブラウザもF12を介して達成することができる要求をスパイクするために特定のソフトウェアを介してURLスパイクを参照してください。スパイクを実施するための要求を指示し、事前にURLスパイクか知っています。私たちは、この問題が解決し検討する必要があります

1.5:データベース設計

敗北当社のサーバーのスパイクリスクは、同じデータベース内に当社の他の事業と、それならばと、一緒に結合された、それは非常に可能性意味合いであり、他の事業に影響を与えます。どのようにスパイクがダウンして発生しても、この問題の発生を防止サーバーの問題を立ち往生し、我々は彼がオンラインビジネスの通常の行動に影響を与えないようにしてくださいさせてください

1.6:リクエストの問題の数が多いです

1.2高並行処理の流れの影響に対処するのに十分ではない、まだキャッシュを使用して短時間であっても、検討することよります。アクセスのような巨大な量をホストする方法、安定した低レイテンシーを確保するためのサービスを提供しながら、直面する大きな課題です。私たちは、Redisのキャッシュを使用している場合、ユーザーのスパイクは、単一QPSは数十万人、またはモノマーのRedisに達する可能性が十二分にを集めている場合、単一のサーバは、RedisのQPSおそらくについて4Wに耐えることができ口座残高に来ますリクエストのような巨大な量をサポートするには不十分。キャッシュは、それによってmysqlのを倒す、直接DBに浸透し、故障になります。背景には、エラーの多くになります

II:デザインと技術的ソリューションスパイクシステム

2.1:スパイクシステムのデータベース設計

1.5データベースのスパイクが提起した質問については、スパイクは、したがって、個別にサイト全体の崩壊を引き起こしたので、アクティビティの高いスパイクの同時アクセスを防止するためのデータベースを設計する必要があります。それは2つだけのテーブル、スパイクOrdersテーブル、スパイク品テーブルでなければなりません

  

実際には、そこにいくつかのテーブル、商品テーブルでなければなりませんが:関連して見つけることができる特定の製品情報、製品画像、名前、通常価格、価格スパイク、などと同様に、ユーザテーブルをgoods_id:USER_IDユーザーは、ユーザーのニックネームを照会することができ、利用者の電話番号を他の追加情報は、配送先住所として、これの具体的な例を与えることはありません。

2.2:URLスパイクのデザイン

バックインターフェーススパイク商品に直接、単一のページのURLの下に人々が経験したアクセスすることを避けるために、我々は、URLが1がスタートする前に、URLのスパイクスパイクを知ることができ、システム全体のダイナミックな、でも発展を達成スパイクする必要があります。具体的なアプローチは、URLのスパイクとしてランダムな文字列のMD5暗号化された文字列を介して行われ、その後、フロントアクセスは、舞台裏の特定のURLのために、背景が通じチェックした後にスパイクを継続することができます。

2.3:スパイク静的なページ

静的ページに書き込まれた製品の説明、パラメータ、取引記録、画像、評価、およびすべてのは、ユーザーが最大の可能性を低減することができる、フロントエンドクライアントに直接生成されたデータベースを経由せずに、バックエンドサーバーにアクセスすることにより、要求する必要はありませんサーバー上の圧力。具体的な方法は、ページにテンプレートを作成してデータを記入して、ページをレンダリングし、FreeMarkerのテンプレート技術を使用することができます

2.4:クラスタのRedisのRedisの単量体へのアップグレード

スパイクは、読み書きはほとんどの場面で、非常に適切な使用のRedisのは、キャッシングを行います。しかし、考慮に降伏キャッシュの問題を取って、私たちは、Redisのは、パフォーマンスと可用性を向上させることができ、センチネルモードを使用して、Redisのクラスタを構築する必要があります。

 2.5:nginxのを使用して

nginx是一个高性能web服务器,它的并发能力可以达到几万,而tomcat只有几百。通过nginx映射客户端请求,再分发到后台tomcat服务器集群中可以大大提升并发能力。

2.6:精简sql

典型的一个场景是在进行扣减库存的时候,传统的做法是先查询库存,再去update。这样的话需要两个sql,而实际上一个sql我们就可以完成的。可以用这样的做法:update miaosha_goods  set stock =stock-1 where goos_id ={#goods_id} and  version = #{version} and sock>0;这样的话,就可以保证库存不会超卖并且一次更新库存,还有注意一点这里使用了版本号的乐观锁,相比较悲观锁,它的性能较好。

2.7:redis预减库存

很多请求进来,都需要后台查询库存,这是一个频繁读的场景。可以使用redis来预减库存,在秒杀开始前可以在redis设值,比如redis.set(goodsId,100),这里预放的库存为100可以设值为常量),每次下单成功之后,Integer stock = (Integer)redis.get(goosId); 然后判断sock的值,如果小于常量值就减去1;不过注意当取消的时候,需要增加库存,增加库存的时候也得注意不能大于之间设定的总库存数(查询库存和扣减库存需要原子操作,此时可以借助lua脚本)下次下单再获取库存的时候,直接从redis里面查就可以了。

2.8:接口限流

秒杀最终的本质是数据库的更新,但是有很多大量无效的请求,我们最终要做的就是如何把这些无效的请求过滤掉,防止渗透到数据库。限流的话,需要入手的方面很多:

2.9.1:前端限流

首先第一步就是通过前端限流,用户在秒杀按钮点击以后发起请求,那么在接下来的5秒是无法点击(通过设置按钮为disable)。这一小举措开发起来成本很小,但是很有效。

2.9.2:同一个用户xx秒内重复请求直接拒绝

具体多少秒需要根据实际业务和秒杀的人数而定,一般限定为10秒。具体的做法就是通过redis的键过期策略,首先对每个请求都从String value = redis.get(userId);如果获取到这个

value为空或者为null,表示它是有效的请求,然后放行这个请求。如果不为空表示它是重复性请求,直接丢掉这个请求。如果有效,采用redis.setexpire(userId,value,10).value可以是任意值,一般放业务属性比较好,这个是设置以userId为key,10秒的过期时间(10秒后,key对应的值自动为null)

2.7.3:令牌桶算法限流

接口限流的策略有很多,我们这里采用令牌桶算法。令牌桶算法的基本思路是每个请求尝试获取一个令牌,后端只处理持有令牌的请求,生产令牌的速度和效率我们都可以自己限定,guava提供了RateLimter的api供我们使用。以下做一个简单的例子,注意需要引入guava

public class TestRateLimiter {

    public static void main(String[] args) {
        //1秒产生1个令牌
        final RateLimiter rateLimiter = RateLimiter.create(1);
        for (int i = 0; i < 10; i++) {
            //该方法会阻塞线程,直到令牌桶中能取到令牌为止才继续向下执行。
            double waitTime= rateLimiter.acquire();
            System.out.println("任务执行" + i + "等待时间" + waitTime);
        }
        System.out.println("执行结束");
    }
}

   上面代码的思路就是通过RateLimiter来限定我们的令牌桶每秒产生1个令牌(生产的效率比较低),循环10次去执行任务。acquire会阻塞当前线程直到获取到令牌,也就是如果任务没有获取到令牌,会一直等待。那么请求就会卡在我们限定的时间内才可以继续往下走,这个方法返回的是线程具体等待的时间。执行如下;

可以看到任务执行的过程中,第1个是无需等待的,因为已经在开始的第1秒生产出了令牌。接下来的任务请求就必须等到令牌桶产生了令牌才可以继续往下执行。如果没有获取到就会阻塞(有一个停顿的过程)。不过这个方式不太好,因为用户如果在客户端请求,如果较多的话,直接后台在生产token就会卡顿(用户体验较差),它是不会抛弃任务的,我们需要一个更优秀的策略:如果超过某个时间没有获取到,直接拒绝该任务。接下来再来个案例:

public class TestRateLimiter2 {

    public static void main(String[] args) {
        final RateLimiter rateLimiter = RateLimiter.create(1);

        for (int i = 0; i < 10; i++) {
            long timeOut = (long) 0.5;
            boolean isValid = rateLimiter.tryAcquire(timeOut, TimeUnit.SECONDS);
            System.out.println("任务" + i + "执行是否有效:" + isValid);
            if (!isValid) {
                continue;
            }
            System.out.println("任务" + i + "在执行");
        }
        System.out.println("结束");
    }
}

其中用到了tryAcquire方法,这个方法的主要作用是设定一个超时的时间,如果在指定的时间内预估(注意是预估并不会真实的等待),如果能拿到令牌就返回true,如果拿不到就返回false.然后我们让无效的直接跳过,这里设定每秒生产1个令牌,让每个任务尝试在

0.5秒获取令牌,如果获取不到,就直接跳过这个任务(放在秒杀环境里就是直接抛弃这个请求);程序实际运行如下:

只有第1个获取到了令牌,顺利执行了,下面的基本都直接抛弃了,因为0.5秒内,令牌桶(1秒1个)来不及生产就肯定获取不到返回false了。

2.8:异步下单

为了提升下单的效率,并且防止下单服务的失败。需要将下单这一操作进行异步处理。最常采用的办法是使用队列,队列最显著的三个优点:异步、削峰、解耦。这里可以采用rabbitmq,在后台经过了限流、库存校验之后,流入到这一步骤的就是有效请求。然后发送到队列里,队列接受消息,异步下单。下完单,入库没有问题可以用短信通知用户秒杀成功。假如失败的话,可以采用补偿机制,重试。

2.9:服务降级

假如在秒杀过程中出现了某个服务器宕机,或者服务不可用,应该做好后备工作。之前的博客里有介绍通过Hystrix进行服务熔断和降级,可以开发一个备用服务,假如服务器真的宕机了,直接给用户一个友好的提示返回,而不是直接卡死,服务器错误等生硬的反馈。

三:总结

秒杀流程图:

      这就是我设计出来的秒杀流程图,当然不同的秒杀体量针对的技术选型都不一样,这个流程可以支撑起几十万的流量,如果是成千万破亿那就得重新设计了。比如数据库的分库分表、队列改成用kafka、redis增加集群数量等手段。通过本次设计主要是要表明的是我们如何应对高并发的处理,并开始尝试解决它,在工作中多思考、多动手能提升我们的能力水平,加油!如果本篇博客有任何错误,请麻烦指出来,不胜感激。

おすすめ

転載: www.cnblogs.com/lonelyxmas/p/11300668.html