Verwenden Sie MQ zwischen dem Produkt und dem Bestellservice.
Wenn sich der Bestand des Produktservices ändert, wird der Bestellservice über MQ über die Bestandsänderung benachrichtigt.
Ursprünglicher Synchronisierungsprozess
// 原始的MySQL同步流程// 判断此代金券是否加入抢购SeckillVouchers seckillVouchers = seckillVouchersMapper.selectVoucher(voucherId);AssertUtil.isTrue(seckillVouchers == null, "该代金券并未有抢购活动");// 判断是否有效AssertUtil.isTrue(seckillVouchers.getIsValid() == 0, "该活动已结束");// 插入数据库seckillVouchersMapper.save(seckillVouchers);
Empfehlung (kostenlos): redis
Lagerbestand direkt abziehen, wenn eine Bestellung generiert wird. Es ist relativ einfach, aber es gibt
Probleme kann dazu führen, dass viele Bestellungen den Produktbestand ohne Zahlung abziehen. Dazu ist ein Hintergrundskript erforderlich, um den Bestand von Bestellungen freizugeben, die über einen bestimmten Zeitraum nicht bezahlt wurden, die Bestellung zu stornieren, den Lagerbestand sofort abzuziehen und die Differenz auszugeben
1. 3-stufiger Produktservice, Betriebsdatenbank für Produktdienstleistungen, 2-stufiger und 4-stufiger Bestellservice und Datenbank für Betriebsauftragsservices.MQ-Asynchronisierung
Erwägen Sie zunächst, nur Schritt 4 asynchron zu machen.
Analyse
2 und 4 sind alle Vorgänge auf der Datenbank. Es besteht keine Notwendigkeit, auf Schritt 4 zu warten. Dem Benutzer wird unmittelbar nach dem Erfolg der Schritte 1, 2 und 3 eine Rückmeldung gegeben. Danach wird die Bestellung asynchron über den Nachrichtenbenachrichtigungsdienst aufgegeben. Wenn die asynchrone Auftragserteilung in Schritt 4 fehlschlägt, versuchen Sie, die Bestellung erneut zu generieren. Nachdem die Bestellung erstellt wurde, befindet sie sich im Warteschlangenstatus und der Dienst veröffentlicht dann ein Ereignis Bestellung erstellt
in der Nachrichtenwarteschlange.
Wenn der Produktservice die Nachricht zur Auftragserstellung erhält, Es wird die Abzugsinventaroperation ausgeführt. Beachten Sie, dass der Bestandsabzug aufgrund einiger Faktoren höherer Gewalt fehlschlagen kann. Unabhängig von Erfolg oder Misserfolg sendet der Produktservice eine Bestandsabzugsnachricht an MQ, und der Inhalt der Nachricht ist das Ergebnis des Bestandsabzugs.
Der Bestellservice abonniert das Ergebnis des Lagerabzugs. Nach Erhalt der Nachricht: Order Created
到消息队列中。
即订单服务向外界发送消息:我创建了一个订单,由MQ 转发给订阅该消息的服务。
如果商品服务收到创建订单消息之后执行扣库存操作。注意,这里可能因为某些不可抗因素导致扣库存失败,无论成功与否,商品服务都会发送一个扣库存消息到 MQ,消息内容即扣库存的结果。
订单服务会订阅扣库存的结果,接收到该消息后:
已确认
,即下单成功已取消
,即下单失败欲实现上述模型要求,需可靠的消息投递。服务发出的消息,一定会被MQ收到。
商品/订单服务都变成异步化,适合秒杀类场景,当流量不大时,并不太适合。
异步设计
当订单支付成功后,会有一个出库过程,既然有这个过程,就有可能出库失败。
库存有两部分:
先扣redis库存
,如果扣除成功,则生成订单进行支付,这个过程不扣除mysql库存
。扣除redis库存成功后
,生成订单,进行支付,支付成功,返回我的订单中心, 会发现有一个出库过程。出库过程
扣除mysql库存
:redis库存和mysql库存
支付前是预扣
,是扣redis库存
,是锁定库存的过程
支付后是真正扣,扣mysql库存
Wenn der Lagerabzug erfolgreich ist, wird der Bestellstatus in Bestätigt
, also die Bestellung, geändert erfolgreich aufgegeben wurde.
Wenn der Bestandsabzug fehlschlägt, ändern Sie den Status der Bestellung auf Storniert
, d. h. die Bestellung ist fehlgeschlagen. Um die oben genannten Modellanforderungen zu erfüllen, ist eine zuverlässige Nachrichtenzustellung erforderlich. Vom Dienst gesendete Nachrichten werden definitiv von MQ empfangen.
Asynchrones Design
Der Bestand wird in Redis gespeichert
🎜Nach Erhalt der Anfrage ermittelt Redis, ob der Bestand ausreichend ist, und subtrahiert den Bestand in Redis🎜🎜Der Bestellservice erstellt die Bestellung und schreibt sie in die Datenbank , und sendet eine Nachricht🎜🎜🎜Wenn die Bestellung erfolgreich ist, wird es einen ausgehenden Prozess geben. Da es diesen Prozess gibt, kann der ausgehende Prozess fehlschlagen. 🎜 Das Inventar besteht aus zwei Teilen: 🎜🎜🎜Cache-Redis-Schicht 🎜🎜Datenbank-MySQL-Schicht 🎜🎜🎜🎜Wenn der Kundendienst 5 Inventare hinzufügt, müssen sowohl Cache-Redis- als auch Datenbank-MySQL-Schichten 5 Inventare hinzufügen, wobei die letztendliche Konsistenz verteilter Transaktionen verwendet wird. Zufriedenheit: Entweder wird der gesamte Bestand hinzugefügt oder keiner. 🎜🎜Wenn eine Bestellung generiert wird, muss der Lagerbestand von Redis abgezogen werden. Wenn der Abzug erfolgreich ist, wird bei diesem Vorgang kein MySQL-Bestand abgezogen . 🎜🎜Wenn der Redis-Bestand abgezogen wird, kann das Produkt nicht bestellt werden und die Bestellung schlägt fehl, sodass die äußere Schicht blockiert wird. 🎜🎜In Schritt 2Nachdem der Redis-Bestand erfolgreich abgezogen wurde
, generieren Sie die Bestellung, führen Sie die Zahlung durch, die Zahlung ist erfolgreich, kehren Sie zu meinem Bestellcenter zurück und Sie werden feststellen, dass es einen ausgehenden Prozess gibt. 🎜🎜Ausgehender Prozess
🎜 Eine asynchrone entkoppelte MQ-Aufgabenwarteschlange. Dieser Prozess ist MySQL-Inventar abziehen
: 🎜🎜🎜🎜Wenn das MySQL-Inventar erfolgreich abgezogen wurde, ist der ausgehende Prozess erfolgreich . Schließen Sie den gesamten Bestellvorgang ab und geben Sie den Lieferstatus ein. 🎜🎜Wenn der MySQL-Bestand nicht abgezogen werden kann und der Versand fehlschlägt, wird eine Reihe von Vorgängen ausgeführt. Der Bestellstatus wird in „Storniert“ geändert. Geben Sie den Redis-Bestand zurück 🎜🎜Rückerstattung🎜🎜🎜🎜🎜🎜Redis-Inventar und MySQL-Inventar🎜🎜🎜Vor der Zahlung erfolgt eine Einbehaltung
, also ein Abzug von Redis-Inventar
, also ein Sperrvorgang Inventar🎜 Nach der Zahlung handelt es sich um einen echten Abzug, bei dem MySQL-Inventar abgezogen
wird, um sicherzustellen, dass das Inventar letztendlich konsistent ist🎜🎜In extremen Fällen kommt es jedoch zu Dateninkonsistenzen🎜🎜🎜Wenn Redis-Inventar = MySQL-Inventar, Es wird kein Problem geben🎜🎜Wenn Redis-Inventar MySQL-Inventar, wird es überverkauft sein, und das Eine überverkaufte Bestellung schlägt während des Liefervorgangs fehl🎜🎜🎜Auf diese Weise wird sie insgesamt nicht versendet. Das Problem, die MySQL-Datenbankschicht, stellt sicher, dass es am Ende keine Probleme mit dem Lagerbestand gibt. 🎜🎜🎜Frage🎜🎜Der Datenbankinventar und der Redis-Inventar sind inkonsistent. Wie erkennt man das?
Wenn Inkonsistenzen festgestellt werden, wie kann man synchronisieren?
Ich habe mir keinen guten Plan ausgedacht.
Eine gewalttätigere Methode besteht darin, eine Zeit mit niedriger Spitzenlast zu finden, z. B. 1 Uhr morgens, und die Abdeckung regelmäßig zu erzwingen. In extremen Fällen kann es jedoch auch nach der Synchronisierung zu Ungenauigkeiten kommen. Beispielsweise wird während des Synchronisierungsvorgangs eine Bestellung bezahlt. Nachdem die Bestellung erfolgreich bezahlt wurde, wird der MySQL-Bestand beim ausgehenden Vorgang abgezogen Das Redis-Inventar wird nicht abgezogen.
Dies ist ein Problem mit dem Aktualisierungsmechanismus des Datenbanksynchronisierungscache.
Es ist ein Problem des konsistenten logischen Designs.缓存数 = 数据库库存数 - 待扣数
Natürlich gibt es andere Lösungen, und angesichts der Konsistenzanforderungen können Sie dies tun Verwenden Sie einfache oder komplexe. Die Lösung
hängt von der Komplexität des Systems ab. Je größer das System, desto detaillierter muss es beispielsweise in einer Warteschlange oder einem Cache abgelegt werden Lesen Sie die Zählungen einfach direkt ab. Geben Sie beispielsweise die Menge ein, die bezahlt wurde und versendet werden soll. Wenn Sie sie zählen, werden Sie nicht viel verlieren. Das allgemeine System kann nicht vollständig garantieren, dass die Datenverbindung keine Fehler verursacht, aber es muss eine Kompensation erfolgen, das heißt, Fehler können korrigiert werden geplant oder über MQ oder Überwachung von Inkonsistenz und Synchronisierung usw. . .
Wird auch als Sicherstellung der Aktualität der zwischengespeicherten Daten bezeichnet
Im Allgemeinen dauert es nicht zu lange, es kann eine halbe Stunde oder ein paar Minuten dauern. Die Anforderungen verschiedener Szenarien sind unterschiedlich Kaufen Sie sie nachts. Tickets, diese Zeit wird voraussichtlich für die Synchronisierung des Inventars und die Synchronisierung des Datenbankinventars mit dem Redis-Inventar verwendet. Beim Kauf von Bahntickets muss jedoch der tatsächliche Inventar abgezogen werden, bevor die Bestellung generiert wird, dh der MySQL-Inventar muss abgezogen werden.
denn beim Kauf von Bahntickets kann der Einkauf nach der Bezahlung versandt werden, bei Tickets muss man jedoch vor der Bezahlung das Lager verlassen. Daher muss der Versandvorgang vorangetrieben werden. Erst wenn der Versand erfolgreich ist, kann eine Bestellung generiert werden. Redis-Inventar muss ebenfalls eingeführt werden
Ziehen Sie zuerst das Inventar im Cache ab. Nachdem der Abzug erfolgreich war, können Sie das Inventar in MySQL abziehen.
Das Redis-Inventar stimmt nicht mit dem MySQL-Inventar überein. In extremen Fällen ist eine Synchronisierung des Inventars erforderlich.
Wenn das Cache-Inventar größer ist als das Datenbankinventar, wird ein Ticket angezeigt In der Abfrage konnte die Bestellung jedoch nicht aufgegeben werden. In diesem Fall wurde angegeben, dass der Lagerbestand nicht ausreicht. Allerdings sollte 12306 über andere Möglichkeiten verfügen, um dieses Problem zu vermeiden , ich bin darauf gestoßen, es gab ein Ticket, aber es konnte nicht in einer einzigen Situation platziert werden. Wenn der Cache-Bestand kleiner ist als der Datenbank-Cache, gibt es kein Problem. Es werden nur Tickets, aber keine Verkäufe vorhanden sein. Nach Abschluss der Inventarsynchronisierung wird es morgen wieder korrekt sein.Das obige ist der detaillierte Inhalt vonLösen Sie das Problem des überverkauften Redis-Bestands. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!