Eine kurze Diskussion über verteilte Transaktionen und Lösungen | JD Logistics Technology Team

1. Hintergrund

Bevor wir das Konzept verteilter Transaktionen beschreiben, werfen wir zunächst einen Blick auf einige Konzepte im Zusammenhang mit Transaktionen.

1.1 Grundkonzepte von Transaktionen

Es handelt sich um eine Programmausführungseinheit, in der alle Operationen entweder erfolgreich ausgeführt werden oder alle Ausführungen fehlschlagen. Nur die Hälfte der Operationen ist erfolgreich und die andere Hälfte schlägt fehl. Wenn ein Transaktionscode beispielsweise zwei Datenbankaktualisierungsvorgänge ausführt, werden diese beiden Datenbankvorgänge entweder erfolgreich ausgeführt oder zurückgesetzt.

1.2 Grundlegende Merkmale von Transaktionen

Wir wissen, dass Transaktionen vier sehr wichtige Merkmale aufweisen, die wir oft als (ACID) bezeichnen.

  • Atomarität: Alle Vorgänge in einer Transaktion sind entweder vollständig abgeschlossen oder nicht abgeschlossen und enden in keiner Zwischenphase. Wenn während der Ausführung der Transaktion ein Fehler auftritt, wird diese auf den Zustand vor Beginn der Transaktion zurückgesetzt (Rollback), als ob die Transaktion nie ausgeführt worden wäre.
  • Konsistenz: Die Integrität der Datenbank wird vor Beginn und nach Ende der Transaktion nicht beeinträchtigt. Dies bedeutet, dass die geschriebenen Daten vollständig allen voreingestellten Regeln entsprechen müssen, einschließlich der Genauigkeit und Verkettung der Daten, und dass die nachfolgende Datenbank die vorgegebene Arbeit spontan abschließen kann.
  • Isolation: Die Fähigkeit der Datenbank, mehreren gleichzeitigen Transaktionen das gleichzeitige Lesen, Schreiben und Ändern ihrer Daten zu ermöglichen. Durch die Isolation können Dateninkonsistenzen aufgrund von Kreuzausführungen verhindert werden, wenn mehrere Transaktionen gleichzeitig ausgeführt werden. Die Transaktionsisolation ist in verschiedene Ebenen unterteilt, darunter nicht festgeschriebenes Lesen, festgeschriebenes Lesen, wiederholbares Lesen und serialisierbares Lesen.
  • Haltbarkeit: Nach Abschluss der Transaktion sind die Änderungen an den Daten dauerhaft und gehen auch bei einem Systemausfall nicht verloren.

2 Verteilte Transaktionen

Tatsächlich ist das Konzept verteilter Transaktionen im Wesentlichen dasselbe wie das Konzept von Datenbanktransaktionen. Da es sich um eine Transaktion handelt, muss sie die grundlegenden Merkmale von Transaktionen (ACID) erfüllen. Der Ausdruck verteilter Transaktionen unterscheidet sich jedoch stark von dem von lokale Transaktionen. .

Wenn wir im Zeitalter lokaler Transaktionen mehrere Datensätze der Datenbank gleichzeitig bearbeiten müssen und diese Vorgänge in eine Transaktion eingefügt werden können, können wir dies über den von der Datenbank bereitgestellten Transaktionsmechanismus erreichen.

Mit der Weiterentwicklung der Microservice-Architektur wurde eine lokale logische Ausführungseinheit in mehrere unabhängige Microservices aufgeteilt, und diese Microservices betreiben jeweils unterschiedliche Datenbanken und Tabellen.

Wenn Sie beispielsweise eine einzelne Transportaufgabe zuweisen, müssen Sie gleichzeitig Anforderungen, Pläne und Aufgaben generieren und auch Auskunftsdienste und Versicherungsdienste anrufen. Sobald dann eine Serviceausnahme auftritt, treten Transaktionsprobleme auf. Obwohl unsere aktuelle Logik durch Operationen außer Kraft gesetzt werden kann, wie sieht es nach der Automatisierung in der Zukunft aus?

Verteilte Transaktionen sollen das Datenkonsistenzproblem zwischen verschiedenen Knoten in der Microservice-Architektur lösen (alle Formen sind verteilte Systeme). Dieses Konsistenzproblem löst im Wesentlichen das Problem, das herkömmliche Transaktionen lösen müssen. Das heißt, wenn sich eine Anforderung in mehreren Mikroservice-Aufrufketten befindet, ist die Datenverarbeitung aller Dienste entweder erfolgreich oder wird zurückgesetzt. Natürlich kann sich die Form verteilter Transaktionsprobleme stark von herkömmlichen Transaktionen unterscheiden, aber der Kern der Probleme ist derselbe und sie alle erfordern die Lösung des Problems der Datenkonsistenz.

Es gibt viele Möglichkeiten, verteilte Transaktionen zu implementieren. Die repräsentativste davon ist das vom Oracle Tuxedo-System vorgeschlagene XA-Protokoll für verteilte Transaktionen. Das XA-Protokoll umfasst zwei Implementierungen: Zwei-Phasen-Commit (2PC) und Drei-Phasen-Commit (3PC). Als Nächstes werden wir die Prinzipien dieser beiden Implementierungsmethoden vorstellen.

3 Zweistufige Einreichung (2PC)

Zwei-Phasen-Commit wird auch 2PC (Two-Phase-Commit-Protokoll) genannt. 2PC ist ein sehr klassisches, stark konsistentes und zentralisiertes atomares Commit-Protokoll. Die hier erwähnte Zentralisierung bedeutet, dass es im Protokoll zwei Rollen gibt: eine ist der verteilte Transaktionskoordinator (Koordinator) und N Teilnehmer (Teilnehmer).

3.1 2PC-Funktionsprinzip

Die zweistufige Einreichung umfasst, wie der Name schon sagt, zwei Einreichungsphasen: die erste Phase, die Vorbereitungsphase (Abstimmungsphase), die zweite Phase, die Einreichungsphase (Ausführungsphase).

3.1.1 Vorbereitungsphase

  1. Der Initiator der verteilten Transaktion sendet eine Anfrage an den verteilten Transaktionskoordinator (Koordinator, auch Transaktionsmanagement-TransactionManager genannt).
  2. Der Koordinator sendet Anforderungen zur Transaktionsvorverarbeitung an Teilnehmer A bzw. Teilnehmer B mit der Bezeichnung „Vorbereiten“. Einige Daten werden auch als „Abstimmungsanfrage“ bezeichnet.
  3. Zu diesem Zeitpunkt öffnen diese Teilnehmerknoten im Allgemeinen lokale Datenbanktransaktionen und beginnen dann mit der Ausführung lokaler Datenbanktransaktionen. Jeder Datenbankteilnehmer führt Transaktionen lokal aus und schreibt lokale Undo/Redo-Protokolle (Undo-Protokolle zeichnen Daten vor der Änderung auf. Wird für Datenbank-Rollbacks verwendet, das Redo-Protokoll Zeichnet geänderte Daten auf und wird zum Schreiben der Datendatei nach dem Festschreiben der Transaktion verwendet. Nach Abschluss der Ausführung wird die lokale Transaktion der Datenbank jedoch nicht sofort übermittelt, sondern das „Vote Commit“ wird zuerst an den Koordinator ausgeführt. Feedback und Information über die Verarbeitungsergebnisse.
  4. Wenn alle Teilnehmer dem Koordinator ein „Vote Commit“-Feedback geben, geht der Prozess in die zweite Phase.

3.1.2 Commit-Phase

1) Wenn alle Teilnehmer Erfolg melden, sendet der Koordinator eine „Global-Commit-Bestätigungsbenachrichtigung (global_commit)“ an alle Teilnehmer, und der Teilnehmer schließt die Übermittlung seiner eigenen lokalen Datenbanktransaktion ab und antwortet mit dem Übermittlungsergebnis. ack“ Nachricht an den Koordinator-Koordinator, und dann gibt der Koordinator-Koordinator das Ergebnis des Abschlusses der verteilten Transaktionsverarbeitung an den Anrufer zurück. Wenn ein Teilnehmer einen Fehler meldet, wird die Transaktion zurückgesetzt.

2) Wenn der Teilnehmer die Nachricht „Vote_Abort“ an den Koordinator zurückmeldet, wird eine Fehlermeldung zurückgegeben. Zu diesem Zeitpunkt initiiert der verteilte Transaktionskoordinator eine Transaktions-Rollback-Nachricht („global_rollback“) an alle Teilnehmer. Zu diesem Zeitpunkt setzt jeder Teilnehmer die lokale Transaktion zurück, gibt Ressourcen frei und sendet „ack“ an den Koordinator. Bestätigen Sie die Nachricht, und der Koordinator gibt das Ergebnis des Fehlers bei der verteilten Transaktionsverarbeitung an den Anrufer zurück.

Das Obige stellt den grundlegenden Prozess der zweiphasigen Übermittlung dar. Kann also gemäß diesem zweiphasigen Übermittlungsprotokoll das Datenkonsistenzproblem verteilter Systeme gelöst werden?

3.2 Probleme mit 2PC

Tatsächlich löst 2PC das Datenkonsistenzproblem einer Transaktion in einem verteilten System über mehrere Dienste hinweg nur durch Hinzufügen der Rolle des Transaktionskoordinators (Koordinators) durch einen zweistufigen Verarbeitungsprozess.

Die folgenden Punkte sind einige der Probleme, die beim XA-Zweiphasen-Festschreibungsprotokoll auftreten:

  • Leistungsprobleme: Alle Teilnehmerknoten in 2PC blockieren Transaktionen. Wenn auf einem Teilnehmerknoten ein Kommunikations-Timeout auftritt, werden die anderen Teilnehmer passiv blockiert und belegen Ressourcen, die nicht freigegeben werden können.
  • Koordinator-Single-Point-of-Failure-Problem: Aufgrund der starken Abhängigkeit vom Koordinator befinden sich die Teilnehmer nach einem Koordinatorausfall immer noch in einem gesperrten Ressourcenzustand und können den Transaktions-Commit-Vorgang nicht abschließen. Obwohl ein Koordinator nach dem Scheitern des Koordinators wiedergewählt wird, kann dadurch das Problem der Blockierung von Teilnehmern aufgrund des Scheiterns des vorherigen Koordinators nicht gelöst werden.
  • Eine Netzwerkunterbrechung führt zu einer Spaltung des Gehirns: In der zweiten Phase, nachdem der Koordinator den Festschreibungsbefehl an die Teilnehmer gesendet hat, sobald zu diesem Zeitpunkt Netzwerkjitter auftritt, erhalten einige Teilnehmer die Festschreibungsanforderung und führen sie aus, andere Teilnehmer haben dies jedoch nicht erhalten Commit-Anfrage kann Transaktions-Commit nicht ausführen. Dies führt zu Dateninkonsistenzen im gesamten verteilten System.

4 Dreistufige Einreichung (3PC)

Die dreistufige Übermittlung, auch als 3PC bekannt, fügt die CanCommit-Stufe auf Basis von 2PC hinzu und führt einen Timeout-Mechanismus ein. Sobald der Transaktionsteilnehmer die Festschreibungsanforderung vom Koordinator nicht erhält, führt er automatisch eine lokale Festschreibung durch, wodurch das Problem des Single Point of Failure des Koordinators relativ effektiv gelöst wird.

4.1 3PC-Funktionsprinzip

4.1.1 CanCommit-Phase

  1. Der Koordinator gibt CanCommit an die Teilnehmer aus und führt Transaktionsabfragevorgänge durch. Erst nachdem alle Teilnehmer mit „Ja“ geantwortet haben, kann mit der nächsten Stufe begonnen werden. (Die Tabelle ist zu diesem Zeitpunkt nicht gesperrt, im Gegensatz zu 2pc, das in der ersten Stufe mit dem Sperren der Tabelle beginnt. Die erste Stufe von 3pc besteht darin, das Sperren der Tabelle unter der Voraussetzung zu vermeiden, dass einzelne Teilnehmer nicht in der Lage sind, Transaktionen durchzuführen.) In einfache Begriffe Überprüfen Sie einfach den Gesundheitszustand Ihres eigenen Staates.
  2. Wenn ein Teilnehmer mit „Nein“ antwortet, wird die gesamte verteilte Transaktion unterbrochen und der Koordinator sendet eine „Abbruch“-Anfrage an alle Teilnehmer.

4.1.2 PreCommit-Phase

  1. Wenn in Phase eins alle Teilnehmer „Ja“ zurücksenden, wird die PreCommit-Phase für die Transaktions-Pre-Commit-Phase eingeleitet. Zu diesem Zeitpunkt sendet der verteilte Transaktionskoordinator eine PreCommit-Anfrage an alle Teilnehmer. Nach Erhalt beginnen die Teilnehmer mit der Durchführung von Transaktionsvorgängen und zeichnen Rückgängig- und Wiederherstellungsinformationen im Transaktionsprotokoll auf. Nachdem der Teilnehmer den Transaktionsvorgang abgeschlossen hat (diesmal befindet er sich im Status einer nicht festgeschriebenen Transaktion), gibt er eine „Bestätigung“ an den Koordinator zurück, um anzuzeigen, dass er zur Übermittlung bereit ist, und wartet auf die nächste Anweisung des Koordinators.
  2. Das Ergebnis der Rückmeldung eines Teilnehmers ist „Nein“, oder der Koordinator hat eine Zeitüberschreitung, während er auf die Rückmeldung vom Teilnehmerknoten wartet (nur der Koordinator kann in 2PC eine Zeitüberschreitung haben, und es gibt keinen Zeitüberschreitungsmechanismus für Teilnehmer). Die gesamte verteilte Transaktion wird abgebrochen und der Koordinator sendet eine „Abbruch“-Anfrage an alle Teilnehmer.

4.1.3 DoCommit-Phase

  1. Wenn in Phase 2 alle Teilnehmer die PreCommit-Übermittlung durchführen können, wechselt der Koordinator von „PreCommit-Status“ -> „Commit-Status“. Senden Sie dann eine „doCommit“-Anfrage an alle Teilnehmer. Nach Erhalt der Commit-Anfrage führt der Teilnehmer den Transaktionsübermittlungsvorgang durch und gibt die „Ack“-Nachricht an den Koordinator zurück. Der Koordinator schließt die Transaktion ab, nachdem er die Ack-Nachricht von allen Teilnehmern erhalten hat.
  2. Wenn ein Teilnehmerknoten das PreCommit-Feedback nicht abschließt oder das Feedback abläuft, sendet der Koordinator in ähnlicher Weise Abbruchanfragen an alle Teilnehmerknoten und unterbricht so die Transaktion.

Im Vergleich zu 2PC legt 3PC sowohl für den Koordinator als auch für den Teilnehmer eine Zeitüberschreitung fest, wodurch das Problem gelöst wird, dass der Teilnehmer längere Zeit nicht mit dem Koordinatorknoten kommunizieren kann (der Koordinator legt auf). Das Problem der Ressourcenfreigabe liegt bei den Teilnehmern selbst verfügen über einen Timeout-Mechanismus und führen automatisch lokale Commits durch, um Ressourcen nach dem Timeout freizugeben. Dieser Mechanismus reduziert auch die Sperrzeit und den Umfang der gesamten Transaktion.
Darüber hinaus wird durch das Design der drei Stufen CanCommit, PreCommit und DoCommit im Vergleich zu 2PC eine zusätzliche Pufferstufe eingerichtet, um sicherzustellen, dass der Status jedes teilnehmenden Knotens vor der endgültigen Übermittlungsstufe konsistent ist.

Nachteile von 3PC:

Während 3PC die Blockierung aufhebt, führt es auch zu einem neuen Problem: Nachdem der Teilnehmer die Pre-Commit-Nachricht erhalten hat und eine Netzwerkpartition auftritt, können der Knoten, auf dem sich der Koordinator befindet, und der Teilnehmer nicht normal kommunizieren. In diesem Fall wird der Teilnehmer dies tun Die Transaktion wird dennoch festgeschrieben, was unweigerlich zu Dateninkonsistenzen führt.

5 Vergütungsangelegenheiten (TCC)

TCC ist wie 2PC und 3PC lediglich eine Implementierungslösung für verteilte Transaktionen.

5.1 TCC-Prinzip:

TCC (Try-Confirm-Cancel) wird auch Kompensationstransaktion genannt. Der Kerngedanke lautet: „Für jeden Vorgang muss eine entsprechende Bestätigung und Entschädigung (Widerrufsvorgang) registriert werden.“ Es ist in drei Operationen unterteilt:

  • Testphase: Hauptsächlich Testen des Geschäftssystems und Reservieren von Ressourcen, z. B. Einfrieren von Lagerbeständen.
  • Bestätigungsphase: Bestätigen Sie die Ausführung von Geschäftsvorgängen.
  • Phase abbrechen: Die Ausführung von Geschäftsvorgängen abbrechen.

Der Verarbeitungsablauf von TCC-Transaktionen ähnelt dem der zweistufigen 2PC-Übermittlung, 2PC befindet sich jedoch normalerweise auf datenbankübergreifender DB-Ebene, und TCC ist im Wesentlichen ein 2PC auf Anwendungsebene, der über Geschäftslogik implementiert werden muss. Der Vorteil dieser verteilten Transaktionsimplementierung besteht darin, dass Anwendungen die Granularität von Datenbankoperationen definieren können, wodurch Sperrkonflikte reduziert und der Durchsatz verbessert werden können.

Der Nachteil besteht darin, dass es sehr aufdringlich für die Anwendung ist und jeder Zweig der Geschäftslogik die drei Vorgänge „Versuchen“, „Bestätigen“ und „Abbrechen“ implementieren muss. Darüber hinaus ist die Implementierung relativ schwierig, und je nach Fehlerursache wie Netzwerkstatus und Systemfehler müssen unterschiedliche Rollback-Strategien implementiert werden. Um die Konsistenzanforderungen zu erfüllen, müssen die Bestätigungs- und Abbruchschnittstellen außerdem idempotent sein.

Das spezifische schematische Diagramm von TCC lautet wie folgt:

5.2 Hinweise:

1. Der Geschäftsbetrieb wird in zwei Phasen abgeschlossen:

Vor dem Zugriff auf TCC können Geschäftsvorgänge in nur einem Schritt abgeschlossen werden. Nach dem Zugriff auf TCC muss jedoch überlegt werden, wie dieser in zwei Phasen unterteilt werden kann. Die Überprüfung und Reservierung von Ressourcen erfolgt in der einstufigen Try-Operation. und der eigentliche Vorgang ist Die Ausführung von Geschäftsvorgängen erfolgt in der Bestätigungsoperation der zweiten Stufe.
Der TCC-Dienst muss sicherstellen, dass nach dem erfolgreichen Versuch der ersten Stufe die Bestätigungsoperation der zweiten Stufe erfolgreich sein muss.

2. Leeres Rollback zulassen;

Wenn der Transaktionskoordinator den einstufigen Try-Vorgang des TCC-Dienstes aufruft, kann aufgrund von Paketverlusten ein Netzwerk-Timeout auftreten. Zu diesem Zeitpunkt löst der Transaktionskoordinator ein zweistufiges Rollback aus und ruft den Cancel-Vorgang des TCC-Dienstes auf
. Eine Abbruchanforderung wird empfangen, wenn eine Versuchsanforderung gestellt wird. Dieses Szenario wird als leeres Rollback bezeichnet. Der TCC-Dienst sollte bei Implementierung die Ausführung eines leeren Rollbacks zulassen.

3. Anti-Suspendierungskontrolle;

Wenn der Transaktionskoordinator die einstufige Try-Operation des TCC-Dienstes aufruft, kann es aufgrund einer Netzwerküberlastung zu einer Zeitüberschreitung kommen. Zu diesem Zeitpunkt löst der Transaktionskoordinator ein zweistufiges Rollback aus und ruft anschließend die Cancel-Operation des TCC-Dienstes auf Das Try-Paket der ersten Stufe im Netzwerk wird vom TCC-Dienst empfangen und die Abbruchanforderung der zweiten Stufe wird vor der Try-Anfrage der ersten Stufe ausgeführt. Bei der Implementierung des TCC-Dienstes sollten Benutzer ein leeres Rollback
zulassen , verweigern aber die Ausführung eines leeren Rollbacks. Die nächste Phase der Try-Anfrage kommt;

4. Idempotente Kontrolle:

Unabhängig davon, ob es sich um die erneute Übertragung von Netzwerkdatenpaketen oder die Kompensationsausführung abnormaler Transaktionen handelt, werden die Vorgänge „Try“, „Bestätigen“ oder „Abbrechen“ des TCC-Dienstes wiederholt ausgeführt. Bei der Implementierung des TCC-Dienstes müssen Benutzer die idempotente Steuerung berücksichtigen, d. h Ausführung von „Versuchen“, „Bestätigen“ und „Abbrechen“ Die Geschäftsergebnisse sind die gleichen, wenn sie einmal und mehrmals ausgeführt werden.

5. Kontrolle der Sichtbarkeit von Geschäftsdaten;

Die Try-Operation der ersten Stufe des TCC-Dienstes reserviert Ressourcen. Bevor die Operation der zweiten Stufe ausgeführt wird und andere Transaktionen die reservierten Ressourcendaten lesen müssen, muss das Unternehmen wissen, wie die Geschäftsdaten im Zwischenstatus dem Benutzer angezeigt werden sollen Bei der Umsetzung klar denken; das übliche Designprinzip lautet: „Es ist besser, überhaupt nichts oder weniger anzuzeigen, als zu viel oder falsch anzuzeigen“;

6. Gleichzeitige Zugriffskontrolle auf Geschäftsdaten;

Nachdem die Ressourcen in der Try-Operation der ersten Stufe des TCC-Dienstes reserviert wurden, werden die reservierten Ressourcen erst freigegeben, wenn die Operation der zweiten Stufe ausgeführt wird. Wenn andere verteilte Transaktionen diese Geschäftsressourcen zu diesem Zeitpunkt ändern, treten Probleme mit der Parallelität verteilter Transaktionen auf auftreten;
Bei der Implementierung von TCC-Diensten müssen Benutzer die Parallelitätskontrolle von Geschäftsdaten berücksichtigen und versuchen, die Granularität der logischen Sperren zu minimieren, um die Parallelität verteilter Transaktionen zu maximieren.

6 Hmily

Hmily (Wie sehr ich dich liebe)
Hochleistungs-TCC-Open-Source-Framework für verteilte Transaktionen. Es wurde auf Basis der Java-Sprache (JDK1.8) entwickelt und unterstützt Dubbo, Springcloud, Motan und andere RPC-Frameworks für verteilte Transaktionen.

Rahmeneigenschaften

  • Unterstützen Sie verschachtelte Transaktionen (Unterstützung für verschachtelte Transaktionen).
  • Die Verwendung des Disruptor-Frameworks zum asynchronen Lesen und Schreiben von Transaktionsprotokollen hat keinen Leistungsunterschied zum RPC-Framework.
  • Unterstützt den Start von SpringBoot-Starter-Projekten und ist einfach zu verwenden.
  • Das RPC-Framework unterstützt: Dubbo, Motan, Springcloud.
  • Unterstützung für lokale Transaktionsspeicherung: Redis, Mongodb, Zookeeper, Datei, MySQL.
  • Unterstützung für die Serialisierung von Transaktionsprotokollen: Java, Hessian, Kryo, Protostuff.
  • Es übernimmt die Aspect-AOP-Aspektidee für eine nahtlose Integration in Spring und unterstützt natürlich Clustering.
  • Es verfügt über ein integriertes klassisches Demoprojekt für verteilte Transaktionsszenarien und eine visuelle Swagger-UI-Schnittstelle für schnelle Erfahrungen.

6.1 Hmily-Prinzip und Flussdiagramm

Schema:

Flussdiagramm:

7 Referenzen

  • https://dromara.org/website/zh-cn/docs/hmily/index.html
  • https://houbb.github.io/2018/10/30/hmily
  • https://developer.aliyun.com/article/609854
  • https://blog.csdn.net/bjweimengshu/article/details/86698036
  • https://blog.csdn.net/u014296316/article/details/90185589

Autor: JD Logistics Song Le

Quelle: JD Cloud Developer Community Ziyuanqishuo Tech Bitte geben Sie beim Nachdruck die Quelle an

 

Lei Jun: Die offizielle Version von Xiaomis neuem Betriebssystem ThePaper OS wurde verpackt. Das Popup-Fenster auf der Lotterieseite der Gome App beleidigt seinen Gründer. Ubuntu 23.10 ist offiziell veröffentlicht. Sie können den Freitag genauso gut für ein Upgrade nutzen! Ubuntu 23.10-Release-Folge: Das ISO-Image wurde dringend „zurückgerufen“, da es Hassreden enthielt. Ein 23-jähriger Doktorand behob den 22 Jahre alten „Ghost Bug“ in Firefox. RustDesk Remote Desktop 1.2.3 wurde veröffentlicht, verbessertes Wayland zur Unterstützung von TiDB 7.4 Release: Offiziell kompatibel mit MySQL 8.0. Nach dem Abziehen des Logitech USB-Empfängers stürzte der Linux-Kernel ab. Der Master verwendete Scratch, um den RISC-V-Simulator zu rubbeln, und führte den Linux-Kernel erfolgreich aus. JetBrains startete Writerside, ein Tool zur Erstellung technischer Dokumente.
{{o.name}}
{{m.name}}

Ich denke du magst

Origin my.oschina.net/u/4090830/blog/10119729
Empfohlen
Rangfolge