suchen
HeimPHP-FrameworkLaravelDesign des Flash-Kill-Systems

Design des Flash-Kill-Systems

Jun 25, 2019 pm 03:06 PM
秒杀系统设计

Design des Flash-Kill-Systems

Ich habe zuvor einen Artikel über das Design des Werbesystems geschrieben und Flash-Verkäufe/Direktrabatte/Juhuasuan erwähnt, aber in der eigentlichen Arbeit habe ich noch nie wirklich ein Flash-Verkaufssystem erstellt, also Ich habe hypothetisch ein einfaches Flash-Sale-System erstellt, um „das Verlangen zu stillen“, und die Werbeideen folgten immer noch dem Design des vorherigen Artikels.

Analyse

Während des Flash-Sales fließt eine große Menge an Traffic ein. Die Abfrage wird häufig aktualisiert, bevor der Flash-Sale beginnt. Wenn sofort eine große Menge an Traffic in die Datenbank gelangt, ist dies der Fall leicht zum Zusammenbruch der Datenbank führen. Daher besteht die Hauptaufgabe des Flash-Sales darin, den Traffic Schicht für Schicht zu filtern und schließlich so wenig und sanftem Traffic wie möglich in die Datenbank zuzulassen.

Übliche Flash-Verkäufe erfordern, dass eine große Anzahl von Benutzern eine kleine Menge an Waren kauft. Bei solchen Anforderungen kann das einfache Zwischenspeichern des Inventars eine große Menge an Datenverkehr filtern, bevor tatsächlich eine Bestellung erstellt wird.

Aber, aber, es scheint überhaupt keine Herausforderung zu sein! Um die Schwierigkeit ein wenig zu erhöhen, nehmen wir an, dass unser Flash-Sale so ist, als würden wir uns Xiaomi-Handys schnappen. Was wäre, wenn 1 Million Menschen sich 100.000 Handys schnappen würden? Das Anstehen bei Xiaomi-Eilverkäufen ist eine Methode (obwohl die Erfahrung nicht sehr gut ist), und unser Flash-Sale-Design wird in Zukunft auf dieser Idee basieren.

Wenn es um Xiaomi geht, muss ich sagen, dass es mir gezeigt hat, dass „Glück auch ein Teil der Stärke ist!“

Front-End-Strombegrenzungsmethode: zufällig( 0, 1) ? axios.post: wait(30, 'Alles fertig!')

Beginnen wir mit der Analyse einiger Codedetails. Grundsätzlich sollte die ursprüngliche Geschäftslogik möglichst wenig geändert werden wie möglich. Darüber hinaus gibt es im folgenden Artikel kein erweitertes Gameplay wie Service-Leistungsschalter oder mehrstufiges Caching, es handelt sich lediglich um ein relativ einfaches Geschäftsdesign.

Start

Der Betreiber fügt im Hintergrund eine Variante zur Flash-Sale-Aktion hinzu und legt den Lagerbestand/Flash-Sale-Rabattsatz/Startzeit und Endzeit usw. des Flash-Sales fest. Wir kann so etwas wie solche Daten bekommen.

// promotion_variant (促销和变体表「sku」的一个中间表)
{
    'id': 1,
    'variant_id': 1,
    'promotion_id': 1,
    'promotion_type': 'snap_up',
    'discount_rate': 0.5,
    'stock': 100, // 秒杀库存
    'sold': 0, // 秒杀销量
    'quantity_limit': 1, // 限购
    'enabled': 1,
    'product_id': 1,
    'rest': {
        variant_name: 'xxx', // 秒杀期间变体名称
        image: 'xxx', // 秒杀期间变体图片
    }
}

Der erste Schritt besteht darin, die Aktionsinformationen zwischenzuspeichern, nachdem die Flash-Sale-Aktion erfolgreich erstellt wurde

# PromotionVariantObserver.php

public function saved(PromotionVariant $promotionVariant)
{
  if ($promotionVariant->promotion_type === PromotionType::SNAP_UP) {
    $seconds = $promotionVariant->ended_at->getTimestamp() - time();

    \Cache::put(
      "promotion_variants:$promotionVariant->id",
      $promotionVariant,
      $seconds
    );
  }
}

Bestellung aufgeben

Die vorhandene Bestellschnittstelle nach Erhalt der Varianteninformationen Wir wissen nicht, welche der aktuellen Variantenlisten an der Aktion teilnimmt. Der Beurteilungsvorgang erfordert hier eine große Anzahl von Datenbankabfragevorgängen.

Hier schreiben wir also eine neue API für den Flash-Sale. Wenn das Frontend erkennt, dass sich die aktuelle Variante in der Flash-Sale-Aktion befindet, wechselt es zur Flash-Sale-Bestell-API.

Selbstverständlich verwenden wir weiterhin die ursprüngliche Bestell-API und es ist kein Problem, ein Logo im Frontend anzubringen.

Ein Punkt, der einer Erklärung bedarf, ist, dass das Aufgeben einer Bestellung normalerweise in zwei Schritte unterteilt ist.

Der erste Schritt ist „Zur Kasse gehen“, um eine Checkout-Bestellung zu generieren Adresse für die Kassenbestellung, Gutscheine, Zahlungsmethoden usw.

Der zweite Schritt ist „Bestätigen“. Zu diesem Zeitpunkt wird die Bestellung bestätigt, der Lagerbestand wird gesperrt und der Benutzer kann die Zahlung vornehmen. Wenn die Zahlung nicht innerhalb der vereinbarten Frist erfolgt, wird die Bestellung normalerweise storniert und der Lagerbestand entsperrt.

Im ersten Schritt werden die Benutzer also gefiltert und in die Warteschlange gestellt, um zu verhindern, dass sich nachfolgende Vorgänge wie die Auswahl von Adressen und Coupons auf die Datenbank auswirken.

# CheckoutController.php

/**
 * @param Request $request
 * @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
 * @throws StockException
 */
public function snapUpCheckout(Request $request)
{
    $variantId = $request->input('variant_id');
    $quantity = $request->input('quantity', 1);

    // 加锁防止超卖
    $lock = \Cache::lock('snap_up:' . $variantId, 10);

    try {
        // 未获取锁的消费者将阻塞在这里
        $lock->block(10);

        $promotionVariant = \Cache::get('promotion_variants:' . $variantId);

        if ($promotionVariant->quantity release();

            throw new StockException('库存不足');
        }

        $promotionVariant->quantity -= $quantity;

        $seconds = $promotionVariant->ended_at->getTimestamp() - time();
        \Cache::put(
            "promotion_variants:$promotionVariant->id",
            $promotionVariant,
            $seconds
        );

    } catch (LockTimeoutException $e) {
        throw new StockException('库存不足');

    } finally {
        optional($lock)->release();
    }

    CheckoutOrder::dispatch([
        'user_id' => \Auth::id(),
        'variant_id' => $variantId,
        'quantity' => $quantity
    ]);

    return response('结账订单创建中');
}

Sie können sehen, dass an der Flash-Sale-Checkout-API kein Datenbankvorgang beteiligt ist. Und die Aufgabe, eine Bestellung zu erstellen, wird durch den Versand an die Warteschlange verteilt, und Benutzer warten in der Reihenfolge, in der sie in die Warteschlange eintreten, für die entsprechende Zeit in der Warteschlange.

Die Frage ist nun, wie kann der Kunde benachrichtigt werden, nachdem die Bestellung erfolgreich erstellt wurde?

Client-Benachrichtigung

Die Lösung hier ist nichts anderes als Polling oder Websocket. Hier wählen wir einen Websocket, der weniger Serverleistung verbraucht, und verwenden Laravel-Echo, das von Laravel bereitgestellt wird (Laravel-Echo-Server). Wenn der Flash-Verkauf des Benutzers erfolgreich ist, stellen das Front-End und das Back-End eine Websocket-Verbindung her. Nachdem die Back-End-Kaufbestellung erfolgreich erstellt wurde, wird das Front-End benachrichtigt, mit dem nächsten Schritt fortzufahren.

Backend

Als nächstes muss das Backend ein „OrderChecked“-Ereignis an den entsprechenden Kanal des Websockets senden, um den Checkout anzuzeigen, nachdem die Bestellung im „CheckoutOrder“-Job erfolgt erfolgreich erstellt Die Bestellung wurde erstellt und der Benutzer kann mit dem nächsten Schritt fortfahren.

# Job/CheckoutOrder.php

// ...

public function handle()
{
  // 创建结账订单
  // ...

  // 通知客户端. websocket 编程本身就是以事件为导向的,和 laravel 的 event 非常契合。
  event(new OrderChecked($this->data->user_id));
}

// ...
# Event/OrderChecked.php

class OrderChecked implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    private $userId;

    /**
     * Create a new event instance.
     *
     * @param $userId
     */
    public function __construct($userId)
    {
        $this->userId = $userId;
    }

    /**
     * App.User.{id} 是 laravel 初始化时,默认的私有频道,直接使用即可
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        return new PrivateChannel('App.User.' . $this->userId);
    }
}

Angenommen, die Benutzer-ID, die gerade zum Kauf drängt, ist 1. Zusammenfassend besteht der obige Code darin, ein „OrderChecked“-Ereignis an den privaten Kanal „App.User.1“ des Websockets zu senden.

Frontend

Der folgende Code ist das Standardprojekt, das mit dem vue-cli-Tool initialisiert wurde.

// views/products/show.vue

<script>

import Echo from &#39;laravel-echo&#39;
import io from &#39;socket.io-client&#39;
window.io = io

export default {
  name: &#39;App&#39;,
  methods: {
    async snapUpCheckout () {
      try {
        // await post -> snap-up-checkout
        this.toCheckout()
      } catch (error) {
        // 秒杀失败
      }
    },
    toCheckout () {
      // 建立 websocket 连接
      const echo = new Echo({
        broadcaster: &#39;socket.io&#39;,
        host: &#39;http://api.e-commerce.test:6001&#39;,
        auth: {
          headers: {
            Authorization: &#39;Bearer &#39; + this.store.auth.token
          }
        }
      })

      // 监听私有频道 App.User.{id} 的 OrderChecked 事件
      echo.private(&#39;App.User.&#39; + this.store.user.id).listen(&#39;OrderChecked&#39;, (e) => {
        // redirect to checkou page
      })
    }
  }
}
</script>

Bei der Verwendung von Laravel-Echo ist zu beachten, dass Laravel-Echo aufgrund der Verwendung eines privaten Kanals standardmäßig eine Post-Anfrage an die Server-API /broadcasting/auth zur Authentifizierung sendet. Da jedoch die Front-End- und Back-End-Kategorien anstelle von Blade-Vorlagen verwendet werden, können wir das CSRF-Token und die Sitzung nicht einfach abrufen, um einige notwendige Authentifizierungen durchzuführen.

Daher muss die Konfiguration von Broadcast und Laravel-Echo-Server leicht geändert werden

# BroadcastServiceProvider.php

public function boot()
{
  // 将认证路由改为 /api/broadcasting/auth 从而避免 csrf 验证
  // 添加中间件 auth:api (jwt 使用 api.auth) 进行身份验证,避免访问 session ,并使 Auth::user() 生效。
  Broadcast::routes(["prefix" => "api", "middleware" => ["auth:api"]]);

  require base_path('routes/channels.php');
}
// laravel-echo-server.json

// 认证路由添加 api 前缀,与上面的修改对应
"authEndpoint": "/api/broadcasting/auth"

Inventar-Freischaltung

Wenn das „Inventar“ für diese Bestellung gesperrt wurde, wenn Wenn der Benutzer den WebSocket abtrennt oder ihn für längere Zeit verlässt, muss er das Inventar entsperren, um eine bedeutungslose Belegung des Inventars zu verhindern.

Das Inventar bezieht sich hier auf das Cache-Inventar, nicht auf das Datenbankinventar. Denn auch wenn die Bestellung zu diesem Zeitpunkt erfolgreich erstellt wurde, befindet sie sich noch im Checkout-Status (keine Adresse, Zahlungsart etc. ausgewählt) und ist im persönlichen Center nicht sichtbar. Der Datenbankbestand wird erst gesperrt, wenn der Benutzer die Bestellung bestätigt.

Die ideale Implementierung besteht hier also darin, den gesperrten Bestand für diese Bestellung zurückzugeben, nachdem der Benutzer die WebSocket-Verbindung getrennt hat. Nachdem die Checkout-Bestellung erstellt wurde, wird eine Verzögerungswarteschlange erstellt, um den Bestand an Bestellungen zurückzugeben, die längere Zeit nicht bearbeitet wurden.

Laravel-Echo ist jedoch ein Broadcast-System und bietet keine Rückrufe für Client-Trennungsereignisse. Es gibt einige Methoden zum Implementieren von Client-Ereignissen, die Laravel abhört, z. B. das Hinzufügen von Hooks zu Laravel-Echo-Server Notify Laravel , aber die Implementierung des Laravel-Echo-Servers muss hier nicht näher erläutert werden. Der Schwerpunkt liegt auf der Bereitstellung von Flash-Sale-Ideen.

Zusammenfassung

Design des Flash-Kill-Systems

Das Bild oben ist die logische Zusammenfassung des Flash-Kill-Systems. Zu diesem Zeitpunkt ist der gesamte Flash-Sale-Prozess abgeschlossen. Im Allgemeinen ist die Codemenge nicht groß und die Logik relativ einfach.

Wie aus der Abbildung ersichtlich ist, interagiert es im gesamten Prozess nur in der Warteschlange mit MySQL. Durch die Strombegrenzung der Warteschlange kann es sich an die Ausdauer von MySQL anpassen das maximale Ausmaß. Wenn die MySQL-Leistung ausreichend ist, können Benutzer Bestellungen über eine große Anzahl von Warteschlangen gleichzeitig verarbeiten, ohne dass der Benutzer den Warteschlangenvorgang überhaupt bemerkt.

Wenn Sie Fragen oder bessere Ideen haben, hinterlassen Sie bitte eine Nachricht zur Diskussion~

Weitere technische Artikel zu Laravel finden Sie in der Spalte Laravel-Tutorial, um mehr zu erfahren!

Das obige ist der detaillierte Inhalt vonDesign des Flash-Kill-Systems. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Die Illusion der Inklusion: Isolation und Einsamkeit in der entfernten Arbeit angehenDie Illusion der Inklusion: Isolation und Einsamkeit in der entfernten Arbeit angehenApr 25, 2025 am 12:28 AM

Tocombatisolationandloninessinremotework, CompaniessHouldImplementRegular, bedeutungsvolle Interaktionen, Bereitstellung von AusreichungstrowThopportunities, andusetechnology effective.) fostergenuineConnections ThroughvirtualCoffeebreaksandPersonalSharing.2) EnterurineConctions

Laravel für die Entwicklung voller Stapel: Ein umfassender LeitfadenLaravel für die Entwicklung voller Stapel: Ein umfassender LeitfadenApr 25, 2025 am 12:27 AM

Laravelispopularforfull-stackdevelopment

Videokonferenz -Showdown: Auswählen der richtigen Plattform für Remote -MeetingsVideokonferenz -Showdown: Auswählen der richtigen Plattform für Remote -MeetingsApr 25, 2025 am 12:26 AM

Zu den wichtigsten Faktoren für die Auswahl einer Videokonferenzplattform gehören die Benutzeroberfläche, die Sicherheit und die Funktionalität. 1) Die Benutzeroberfläche sollte intuitiv sein, z. B. Zoom. 2) Die Sicherheit muss beachtet werden, und Microsoft Teams bietet eine End-to-End-Verschlüsselung. 3) Funktionen müssen die Anforderungen entsprechen, Googlemeet eignet sich für kurze Besprechungen, und Ciscowebe bietet erweiterte Kollaborations -Tools.

Welche Datenbankversionen sind mit dem neuesten Laravel kompatibel?Welche Datenbankversionen sind mit dem neuesten Laravel kompatibel?Apr 25, 2025 am 12:25 AM

Die neueste Version von Laravel10 ist mit MySQL 5.7 und oben kompatibel, PostgreSQL 9.6 und höher, SQLite 3.8.8 und höher, SQLServer 2017 und höher. Diese Versionen werden ausgewählt, da sie die ORM -Funktionen von Laravel unterstützen, wie den JSON -Datentyp von MySQL5.7, der die Abfrage- und Speicher -Effizienz verbessert.

Die Vorteile der Verwendung von Laravel als Full-Stack-FrameworkDie Vorteile der Verwendung von Laravel als Full-Stack-FrameworkApr 25, 2025 am 12:24 AM

Laravelisanexzellentchoiceforfull-stackdevelopmentDuetoitsrobustFeaturesandeaseofuse.1) dotipliFies compextenswithitsmodernphpstaxandtoolslikeBladeForFront-EndandeloquentOmforback-End.2) Laravel-Ersecosystem, inkl

Was ist die neueste Version von Laravel?Was ist die neueste Version von Laravel?Apr 24, 2025 pm 05:17 PM

Laravel10, freigegebenes Februar 7.2023, iSthelatestversion.itFeatures: 1) AchtungserhandlingWithanewReportMethodinTheexceptionHandler, 2) EnhancedSupportForPhp8.1Features-ähnliche und 3) AneWlaravel \ EingabeaufforderungspackageforinteractiveCommandivePrompts.

Wie vereinfacht die neueste Laravel -Version die Entwicklung?Wie vereinfacht die neueste Laravel -Version die Entwicklung?Apr 24, 2025 pm 05:01 PM

ThelatestlaravelversionenHancesDevelopmentWith: 1) SimplifiedRoutingusedimplicitModelBinding, 2) EnhancedeloquentCapabilities WitheNewQueryMethods und 3) verbessert den SupportformodernphpfFeaturesLikeNaDarguments, machten die Kodierung von Kodeln moreffizemadern.

Wo finde ich die Versionshinweise für die neueste Laravel -Version?Wo finde ich die Versionshinweise für die neueste Laravel -Version?Apr 24, 2025 pm 04:53 PM

Die Versionshinweise finden Sie für die neueste Laravel -Version unter laravel.com/docs. 1) Versionshinweise bieten detaillierte Informationen zu neuen Funktionen, Fehlerbehebungen und Verbesserungen. 2) Sie enthalten Beispiele und Erklärungen, um die Anwendung neuer Funktionen zu verstehen. 3) Achten Sie auf die potenziellen Komplexitäts- und Rückwärtskompatibilitätsprobleme neuer Merkmale. 4) Eine regelmäßige Überprüfung der Versionshinweise kann es auf dem Laufenden halten und Innovationen inspirieren.

See all articles

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

Video Face Swap

Video Face Swap

Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heiße Werkzeuge

WebStorm-Mac-Version

WebStorm-Mac-Version

Nützliche JavaScript-Entwicklungstools

DVWA

DVWA

Damn Vulnerable Web App (DVWA) ist eine PHP/MySQL-Webanwendung, die sehr anfällig ist. Seine Hauptziele bestehen darin, Sicherheitsexperten dabei zu helfen, ihre Fähigkeiten und Tools in einem rechtlichen Umfeld zu testen, Webentwicklern dabei zu helfen, den Prozess der Sicherung von Webanwendungen besser zu verstehen, und Lehrern/Schülern dabei zu helfen, in einer Unterrichtsumgebung Webanwendungen zu lehren/lernen Sicherheit. Das Ziel von DVWA besteht darin, einige der häufigsten Web-Schwachstellen über eine einfache und unkomplizierte Benutzeroberfläche mit unterschiedlichen Schwierigkeitsgraden zu üben. Bitte beachten Sie, dass diese Software

SublimeText3 Englische Version

SublimeText3 Englische Version

Empfohlen: Win-Version, unterstützt Code-Eingabeaufforderungen!

EditPlus chinesische Crack-Version

EditPlus chinesische Crack-Version

Geringe Größe, Syntaxhervorhebung, unterstützt keine Code-Eingabeaufforderungsfunktion

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor