Beitrag
Teile dein Wissen.
Entwurfsmuster und Parallelitätsmanagement für gemeinsam genutzte Objekte in Sui Move
Ich versuche, das richtige Architekturmuster zu verstehen, wenn ich mit gemeinsam genutzten Objekten in Sui Move arbeite, vor allem, wenn mehrere Benutzer gleichzeitig mit ihnen interagieren müssen (z. B. in einer Spielarena, einem DAO-Abstimmungs-Tracker oder einem Kredittresor).
Ich habe gelesen, dass gemeinsame Objekte zu Synchronisationsproblemen führen können, aber ich bin mir immer noch nicht sicher, was Folgendes angeht:
- Wann genau sollte ich ein
shared
Objekt verwendenowned
? - Wie geht Sui mit gleichzeitigen Transaktionsversuchen auf demselben gemeinsamen Objekt um — muss ich Dinge manuell in die Warteschlange stellen/sperren?
ConflictTransaction
* Was ist die beste Methode für den Entwurf von Modulen, die eine hohe Parallelität unterstützen, aber häufige Fehler vermeiden? - Sollte ich etwas Besonderes tun (z. B. veränderbare Felder in Unterobjekte aufteilen), um Konflikte zu reduzieren?
- Sui
- Architecture
- NFT Ecosystem
- Move
Antworten
13Wenn du eine DApp auf Sui erstellst, bei der mehrere Benutzer mit demselben Staat interagieren müssen, wie in einer Spielarena, einem Leihprotokoll oder einer DAO, solltest dugemeinsam genutzte Objekteanstelle von eigenen verwenden. Gemeinsam genutzte Objekte sind öffentlich zugänglich und veränderbar, was bedeutet, dass jeder Eingabefunktionen für sie aufrufen kann, solange sie sich im globalen Objektdiagramm befinden. Im Gegensatz dazu sind eigene Objekte für einen Benutzer privat und eignen sich ideal für persönliche Vermögenswerte wie Brieftaschen oder Inventar. Sie sollten also ein gemeinsam benutztes Objekt verwenden, wenn Statusaktualisierungen für viele Benutzer gleichzeitig sichtbar und nutzbar sein müssen.
Sui verarbeitet gleichzeitige Transaktionen mit gemeinsam genutzten Objekten über einen Mechanismus namensCausal Order Validation, bei dem Sie explizit die neueste bekannte Version eines gemeinsam genutzten Objekts angeben müssen. ConflictTransaction
Wenn zwei Benutzer versuchen, dasselbe gemeinsame Objekt mit veralteten Versionen gleichzeitig zu ändern, ist einer erfolgreich, während die anderen mit einem Fehler fehlschlagen. Sui stellt gemeinsam genutzte Objekte nicht nativ in die Warteschlange oder sperrt sie nicht. Sie müssen also Ihre Move-Module so gestalten, dass überlappende Schreibvorgänge minimiert werden. Eine der besten Möglichkeiten, Konflikte zu reduzieren, ist dasDesign auf Parallelität ausgelegt. Anstatt beispielsweise den gesamten veränderlichen Status im gemeinsamen Stammobjekt zu speichern, können SieFelder mit hohem Streitwert in separate untergeordnete Objekte aufteilen. Jedes dieser untergeordneten Elemente kann dann unabhängig geschrieben werden, wodurch die Wahrscheinlichkeit von Transaktionskonflikten reduziert wird.
Es empfiehlt sich, das gemeinsame Hauptobjekt als Verzeichnis beizubehalten und detaillierte, häufig aktualisierte Statusinformationen — wie Spielergebnisse, Stimmen oder Kreditsalden — in dynamische Felder oder kleinere Unterobjekte zu verschieben. Auf diese Weise aktualisieren Benutzer nur den Teil, den sie benötigen, und nicht das gesamte gemeinsame Objekt. Es ist auch klug, leseintensive und schreibintensive Komponenten zu trennen. Darüber hinaus sollten Sie klare und deterministische Transaktionsabläufe erstellen, die immer die neueste Version gemeinsam genutzter Objekte verwenden. Außerdem sollten Sie die Logik wiederholen, mit der Clients fehlgeschlagene Transaktionen verarbeiten können.
Weitere Informationen zum gemeinsamen Objektdesign und zur Konfliktminderung finden Sie in der Sui-Dokumentation hier: https://docs.sui.io/concepts/objects#shared-objects.
Wenn du so etwas wie einen Abstimmungs-Tracker verwaltest, findest du hier ein vereinfachtes Beispiel für einen Transaktionsblock, um Konflikte zu reduzieren:
const tx = new TransactionBlock();
tx.moveCall({
target: `$ {packageId} ::vote_tracker: :cast_vote`,
Argumente: [
tx.sharedObject (votTrackerId),//Referenz für gemeinsam genutzte Objekte
tx.pure (voterId),//eigenes Objekt oder öffentlicher Schlüssel
tx.pure (proposAid),//reine Daten
tx.pure (VoteChoice)
]
});
In Sui Move sindgemeinsam genutzte Objekte(mit markiertkey + store
) unerlässlich für die Interaktion mit mehreren Benutzern, erfordern jedoch ein sorgfältiges Parallelitätsdesign. Verwenden Sie sie, wenn der Status global veränderbar sein muss (z. B. Spiele, DAOs), wohingegen besitze/unveränderliche Objekte für Einzelbenutzer-Szenarien geeignet sind. Sui serialisiert Transaktionen pro gemeinsam genutztem Objekt automatisch, aber häufige Schreibvorgänge können ConflictTransaction
Fehler auslösen — mildern Sie dies, indem Sie Hotfieldsin separate untergeordnete Objekte aufteilen (z. B. eines pro Benutzer) oder Aktualisierungen stapelweise durchführen. Für einen hohen Durchsatz sollten SieMuster zur Ereignisquellen**verwenden: Speichern Sie Aktionen als unveränderliche Ereignisse und aggregieren Sie den Status regelmäßig. transfer::share_object
Minimiere immer die Anzahl veränderbarer gemeinsam genutzter Felder und bevorzuge atomare Swaps gegenüber direkten Mutationen.
In Sui Move erfordert der effektive Umgang mit gemeinsam genutzten Objekten und Parallelität ein sorgfältiges Design, um Rennbedingungen und hohe Konflikte zu vermeiden. Hier ist eine Aufschlüsselung der bewährten Methoden und architektonischen Muster:
1.Wann sollten gemeinsam genutzte oder eigene Objekte verwendet werden:
*Geteilte Objekte: Wird verwendet, wenn mehrere Benutzer gleichzeitig mit demselben Objekt interagieren müssen (z. B. gemeinsam genutzter Spielstatus, DAO-Abstimmungs-Tracker). *Eigene Objekte: Wird verwendet, wenn das Objekt spezifisch für einen einzelnen Benutzer oder Account ist. Dadurch wird ein gemeinsamer Status vermieden und Parallelitätsprobleme werden reduziert.
2.Gleichzeitige Transaktionsabwicklung in Sui:
- Sui behandelt Parallelität automatisch, indem esTransaktionssperrenverwendet, um gleichzeitige Änderungen desselben Objekts zu verhindern.
- Sie müssen gemeinsam genutzte Objektenichtmanuell in die Warteschlange stellen oder sperren, da Sui eine Sperre auf Objektebene erzwingt. Allerdings könnenSie möglicherweise ConflictTransaction-Fehlererhalten, wenn mehrere Transaktionen für dasselbe Objekt miteinander in Konflikt geraten.
3.Bewährte Methoden für hohe Parallelität:
*Konflikte minimieren: Teilen Sie veränderbare Felder in separate Unterobjekte auf, um parallele Aktualisierungen an verschiedenen Teilen des Objekts zu ermöglichen. *Hotspots vermeiden: Verteilen Sie häufig geänderte Statusinformationen auf mehrere Objekte (z. B. teilen Sie es in mehrere Buckets oder Konten auf, anstatt ein einziges gemeinsames Ledger zu haben). *Versionierung: Verwenden Sie versionierte Objekte oder erstellen Sie neue Objekte, um Aktualisierungen nachzuverfolgen, anstatt dasselbe Objekt wiederholt ändern zu müssen.
4.Verwaltung von Konflikten:
- Erwägen Sie,veränderbare Felder in kleinere Objekte aufteilen, um Konflikte zu vermeiden. Dadurch können verschiedene Teile des Objekts gleichzeitig aktualisiert werden, wodurch die Wahrscheinlichkeit von Konflikten verringert wird.
- Verwenden Sieatomare Transaktionen, um verwandte Aktionen zu einer einzigen zu bündeln und so die Konsistenz zwischen verwandten Objekten sicherzustellen.
Beispiel:
Wenn du einenVote-Trackerfür ein DAO hast:
- Anstatt alle Stimmen in einem einzigen gemeinsamen Objekt zu speichern, teilen Sie sie in mehrere Objekte auf (z. B. eines pro Vorschlag), sodass parallele Aktualisierungen für jeden Vorschlag möglich sind und gleichzeitig Konflikte vermieden werden.
Fazit:
Bei hoher Parallelität sollten Sie Konflikte minimieren, indem Sie den Status verteilen, Unterobjekte verwenden und die automatische Transaktionsverarbeitung von Sui nutzen. Stellen Sie sicher, dass Sie Ihre Zugriffsmuster verstehen, und strukturieren Sie die Objekte, um Konfliktpunkte zu minimieren.
Grundlegendes zu Entwurfsmustern und Parallelitätsmanagement für gemeinsam genutzte Objekte in Sui Move
Beim Umgang mitgemeinsam genutzten ObjekteninSui Moveist die Verwaltung der Parallelität von entscheidender Bedeutung, da möglicherweise mehrere Benutzer gleichzeitig mit demselben Objekt interagieren müssen. Dies gilt insbesondere für Anwendungsfälle wieSpielarenen,DAO-Abstimmungs-TrackerundLeihtresore, bei denen eine hohe Parallelität erwartet wird. Das Sui-Netzwerk bietet einige Funktionen zur Verwaltung der Parallelität, erfordert aber dennoch ein sorgfältiges Design, um häufige Fallstricke wieConflictTransaction-Fehlerzu vermeiden.
1.Wann sollten gemeinsame Objekte und eigene Objekte verwendet werden
*Eigene Objekte:
-
Ein Objekt istBesitz, wenn es von einer einzigen Adresse verwaltet wird, die es übertragen oder ändern kann. *Verwenden Sie eigene Objekte, wenn Sie erwarten, dass eine einzelne Entität ein Objekt kontrolliert und mit ihm interagiert. Wenn Sie beispielsweise ein Wallet mit Coins haben, besitzt jedes Wallet das Eigentum an seinen eigenen Coins. *Geteilte Objekte:
-
Auf gemeinsam genutzte Objekte kann von mehreren Adressen gleichzeitig zugegriffen und diese geändert werden. Sui ermöglicht es Ihnen, Objekte alsgemeinsam genutztzu definieren, indem Sie sie veränderbar machen und mehreren Parteien Zugriff gewähren. *Verwenden Sie gemeinsam genutzte Objektefür Szenarien, in denen mehrere Benutzer oder Adressen mit demselben Objekt interagieren müssen, wie zum Beispiel:
*DAO-Abstimmungs-Tracker: Mehrere Benutzer können über dasselbe Objekt abstimmen. *Ausleihtresore: Mehrere Benutzer können Kredite und Kredite aus demselben Tresor aufnehmen. *Spielaren: Mehrere Benutzer interagieren gleichzeitig mit dem Spielstatus.
Wichtiger Überlegung: Gemeinsam genutzte Objekte sollten mit Vorsicht verwendet werden, da sie zuKonfliktführen können — Situationen, in denen mehrere Transaktionen versuchen, auf dasselbe Objekt gleichzeitig zuzugreifen und es zu ändern.
2.Parallelität und Transaktionsversuche für gemeinsam genutzte Objekte
Sui stellt sicher, dass gleichzeitigeTransaktionenauf demselbengemeinsamen Objektkorrekt behandelt werden, indem dieTransaktionsisolationerzwungen wird. Wenn mehrere Transaktionen gleichzeitig versuchen, dasselbe gemeinsame Objekt zu mutieren, wird eine von ihnen aufgrund vonKonflikt****fehlschlag.
Wenn eine Transaktion versucht, ein gemeinsames Objekt zu ändern, das bereits durch eine andere Transaktion geändert wird, gibt Sui den FehlerConflictTransactionzurück.Sui kümmert sich jedoch um den Großteil der Parallelitätsverwaltung intern, sodass Sie Objekte nicht manuell in die Warteschlange stellen oder sperren**müssen. Stattdessen müssen Sie Ihren Vertrag so gestalten, dass Konflikte minimiert werden und Situationen vermieden werden, in denen zwei Transaktionen häufig miteinander in Konflikt geraten.
3.Bewährte Methoden für hohe Parallelität und Reduzierung von Konflikttransaktionsfehlern
Gehen Sie wie folgt vor, um Module zu entwerfen, die hohe Parallelität verarbeiten und häufigeConflictTransaction-Fehler vermeiden können:
a.Streitpunkte minimieren:
*Veränderbaren Zugriff einschränken: Halten Sie die Anzahl der veränderbaren Felder in gemeinsam genutzten Objekten so gering wie möglich. Jedes veränderbare Feld führt zu einem potenziellen Streitpunkt. *Eigene Objekte für unabhängige Daten: Anstatt alles gemeinsam zu nutzen, speichern Sie unabhängige Daten in eigenen Objekten. Wenn Sie beispielsweise benutzerspezifische Daten (wie Saldo) haben, speichern Sie diese in einem eigenen Objekt und nicht in einem gemeinsam genutzten Objekt.
b.Verwenden Sie das Muster „State Partitioning“:
-
Teilen Sie Ihr gemeinsames Objekt inmehrere Unterobjekteauf, um Konflikte zu vermeiden. Anstatt beispielsweise ein gemeinsames Objekt zu haben, das den gesamten Spielstatus verfolgt, könntest du es in mehrere Unterobjekte aufteilen:
-
Eines für den Status jedesSpieler.
-
Eine für dieSpieleinstellungen.
-
Eine fürLeaderboard-Daten.
-
Auf diese Weise können Transaktionen, die sich auf verschiedene Teile des Systems beziehen, gleichzeitig ausgeführt werden, ohne sich gegenseitig zu blockieren.
c.Batch-Betriebe:
- Wenn Sie mit gemeinsam genutzten Objekten arbeiten, sollten Sie Ihre Aktualisierungen stapelweise durchführen, um die Anzahl der Transaktionen zu reduzieren, die mit dem Objekt interagieren müssen. Dies kann dazu beitragen, häufige Konflikte zu vermeiden. *Verwenden Sie Sammlungenwie Vektoren oder Sets, um mehrere Aktualisierungen in einer einzigen Transaktion zu verwalten.
d.Verwenden Sie atomare Operationen:
- Wenn möglich, entwerfen Sie Ihre Module so, dass sie nach Möglichkeit atomare Operationen verwenden. Anstatt beispielsweise separate Transaktionen für die Überprüfung einer Bedingung und die anschließende Aktualisierung eines Feldes zu haben, bündeln Sie die Prüfungen und Aktualisierungen in einer einzigen atomaren Operation.
e.Logik wiederholen:
- Während Sui Wiederholungen intern verarbeitet, können Sie eine Wiederholungslogik auf Anwendungsebene implementieren, um gelegentliche Konfliktfehler zu behandeln. Wenn beispielsweise ein
ConflictTransaction
Fehler auftritt, können Sie die Transaktion einfach wiederholen oder sie zur späteren Ausführung in die Warteschlange stellen.
4.Reduzierung von Konflikten durch Aufteilen veränderbarer Felder in Unterobjekte
Diese Vorgehensweise wird dringend empfohlen. Bei gemeinsamen Objekten gilt: Je mehr Felder in einem gemeinsamen Objekt vorhanden sind**, dieveränderbarsind, desto höher ist die Wahrscheinlichkeit, dass zwei Transaktionen versuchen, dasselbe Feld gleichzeitig zu ändern.
*Beispiel 1: Wenn Sie ein gemeinsames Objekt haben, das einenLeihtresordarstellt, teilen Sie es in Unterobjekte auf:
- Eines fürEinlagen: Verfolgen Sie einzelne Einzahlungen separat.
- Eine fürKredite: Verfolgen Sie einzelne Kredite separat.
- Eine fürTresorzustand: Verfolgen Sie allgemeine Statusinformationen (z. B. Gesamtwert, Zinssatz).
Auf diese Weise steht eine Transaktion, die ein Unterobjekt ändert (z. B. das UnterobjektDarlehen), nicht in Konflikt mit einer Transaktion, die ein anderes ändert (z. B. das UnterobjektEinzahlung).
*Beispiel 2: In einerSpielarena:
- Teile den Spielstatus in Unterobjekte für jeden Spieler, Spielstatus und Gefechtsstatistiken auf. Dadurch wird das Konfliktrisiko reduziert, wenn verschiedene Spieler mit ihren individuellen Spielzuständen interagieren.
Indem Sie veränderbare Felder inUnterobjekteaufteilen, verringern Sie die Wahrscheinlichkeit, dass mehrere Benutzer versuchen, dasselbe Objekt gleichzeitig zu ändern.
5.Andere Techniken zur Verwaltung der Parallelität in Sui
*Sperren (explizite Sperren): Bei Sui müssen Sie Sperren zwar nicht manuell handhaben, aber in einigen Fällen möchten Sie vielleichtexplizite Sperrenerzwingen, indem Sie**Objekte sperren (separate Objekte, die sicherstellen, dass jeweils nur eine Transaktion auf eine bestimmte Ressource zugreifen kann).
*Zeitliche Isolation: Wenn sich Ihre Objekte nur gelegentlich ändern, sollten Sie erwägen,zeitbasierte Isolationeinzuführen. Wenn Sie beispielsweise einen Tresor oder ein Abstimmungssystem verwalten, legen SieAbstimmungszeitraumeoderTransaktionsfensterfest, um Interaktionen zu bestimmten Zeiten einzuschränken.
6.Beispielcode für die Verwaltung der Parallelität mit Unterobjekten
Hier ist ein Beispiel, das veranschaulicht, wie Konflikte reduziert werden können, indem einKredittresorin kleinere Unterobjekte aufgeteilt wird:
module LendingVault {
struct Deposit has store {
amount: u64,
depositor: address,
}
struct Loan has store {
amount: u64,
borrower: address,
}
struct VaultState has store {
total_value: u64,
interest_rate: u64,
}
struct LendingVault has store {
deposits: vector<Deposit>,
loans: vector<Loan>,
vault_state: VaultState,
}
// Function to add a deposit
public fun add_deposit(vault: &mut LendingVault, depositor: address, amount: u64) {
let deposit = Deposit { amount, depositor };
Vector::push_back(&mut vault.deposits, deposit);
vault.vault_state.total_value = vault.vault_state.total_value + amount;
}
// Function to add a loan
public fun add_loan(vault: &mut LendingVault, borrower: address, amount: u64) {
let loan = Loan { amount, borrower };
Vector::push_back(&mut vault.loans, loan);
vault.vault_state.total_value = vault.vault_state.total_value - amount;
}
}
Zusammenfassung
*Verwende gemeinsam genutzte Objekte, wenn mehrere Benutzer gleichzeitig mit demselben Objekt interagieren müssen (z. B. DAO-Abstimmungen, Spielstatus, Leihtresore). *Minimiere Konflikt, indem du große gemeinsam genutzte Objekte in kleinere Unterobjekte aufteilst und die Anzahl der veränderbaren Felder reduzierst. *Vermeiden Sie häufige ConflictTransaction-Fehler, indem Sie bewährte Methoden wie Zustandspartitionierung, Batch-Operationen und atomare Operationen befolgen. *WiederholungslogikundOptimistic Concurrency Controlkönnen verwendet werden, um Konflikte elegant zu lösen.
- DasTransaktionsmodellund dieKonfliktlösungvon Sui sind robust, aber dasDesignIhrer gemeinsam genutzten Objekte ist entscheidend für einen effizienten gleichzeitigen Zugriff.
Wenn Sie diese Entwurfsprinzipien befolgen, werden Sie in der Lage sein, eine hohe Parallelität in Ihren MOVE-basierten Modulen zu bewältigen und gleichzeitig die typischen Fallstricke wieKonflikteundTransaktionsfehlerzu vermeiden.
Verwenden SieShared Objectsfür den Zugriff mehrerer Autoren (z. B. Spiele, DAOs). Wichtige Muster:
1.Besessen oder geteilt
- Besessen: Single-Writer (schneller).
- Geteilt: Gleichzeitige Schreibvorgänge (höherer Gasverbrauch).
2.Behandlung von Parallelität
- Sui sequenziert die TXs gemeinsam genutzter Objekte automatisch (keine manuellen Sperren).
- Teilen Sie aktuelle Daten in Unterobjekte auf (z. B. eines pro Spieler), um Konflikte zu vermeiden.
3.Konfliktminderung
Table<ID, PlayerData>
- Isolieren Sie stark frequentierte Felder (z. B.).
- Verwenden Sie PTBs für atomare Operationen mit mehreren Objekten.
Achten Sie auf:
-ConflictTransaction
: Geteilte Daten oder Batch-Updates.
- Gasspitzen an gemeinsam genutzten Objekten.
- (Die Runtime von Sui behandelt Konflikte — optimieren Sie sie mithilfe von Daten-Sharding. ) *) *
Verwenden Sieshared objects(transfer::share_object
), wenn mehrere Benutzer dasselbe Objekt ändern müssen (z. B. Tresor, DAO, Spielstatus). Verwenden Sie andernfallsOwned.
TransactionLockConflict
Sui behandelt Parallelität perKonsensusvon Narwhal & Tusk: widersprüchliche Transaktionen an einem gemeinsamen Objekt werden serialisiert — pro Runde ist nur eine erfolgreich; andere schlagen fehl. Es ist kein manuelles Sperren erforderlich, aberSie müssen das Design für Wiederholungen konzipieren.
Bewährte Methoden:
- Minimiert den veränderlichen Status von gemeinsam genutzten Objekten; teilt Hotspots in separate Unterobjekte auf (z. B. Tresorfreigaben pro Benutzer).
VecMap
- Verwenden SieTable
oder für skalierbare Mappings. - Vermeiden Sie lang andauernde Berechnungen in gemeinsam genutzten Funktionen.
- Ereignisse ausgeben, anstatt kurzlebige Zustände zu speichern.
- Verwenden Sie bei Systemen mit hoher KonfliktsituationBatching- oderCommit-Reveal-Schema, um Konflikte zu reduzieren.
Gemeinsam genutzte Objekte sind zwar global zugänglich, verursachen aber mehr Probleme und Konflikte — optimieren Sie die Idempotenz und die Wiederholungslogik im Client-Code.
Verwenden Sie fürgemeinsam genutzte Objektein Sui Move diese Muster, um die Parallelität zu verwalten:
####1. Geteilt oder besessen?
-Gemeinsames Objekt (key + store
):
- Wird fürglobalen Statusverwendet (z. B. Spiele, DAOs).
- Erlaubtparallele Schreibvorgänge(im Gegensatz zu den serialisierten TXs von EVM).
struct GameArena has key, store { id: UID, players: vector<address> }
-Eigenes Objekt:
- Wird fürbenutzerspezifische Datenverwendet (z. B. NFTs, Wallets).
struct PlayerInventory has key { id: UID, items: vector<Item> }
####2. Behandlung von Parallelität -Keine manuellen Sperren: Suilöst Konflikte automatisch(im Gegensatz zu EVM). -Streit aufteilen: Teilen Sie gemeinsam genutzte Objekte inkleinere Unterobjekteauf (z. B. pro Spieler oder pro Shard).
struct PlayerScore has key, store { id: UID, points: u64 } // Less contention
####3. Fehler ConflictTransaction
reduzieren
-Schreibvorgänge isolieren: Aktualisiereverschiedene Felderin separaten TXs.
&mut
-Mit Bedacht verwenden: Vermeiden Sie weitreichende Mutationen.
public entry fun update_score(
arena: &mut GameArena,
player: address,
points: u64
) { /* ... */ } // Only touches 1 player’s data
####4. Bewährte Verfahren -Batch-Aktualisierungen: Gruppieren Sie Operationen, die keinen Konflikt verursachen (z. B. Abstimmungen in einer DAO). -Event-Driven: Gibt Ereignisse aus, anstatt den Status zu ändern, wenn möglich.
struct VoteEvent has copy, drop { voter: address, choice: u8 }
Verwenden Sie gemeinsam genutzte Objekte für den Zugriff mehrerer Autoren (z. B. Spiele, DAOs). Wichtige Muster:
Im Besitz oder gemeinsam genutzt
Gehört: Single-Writer (schneller). Geteilt: Gleichzeitige Schreibvorgänge (höhere Auslastung). Umgang mit Parallelität
Sui sequenziert die TXs gemeinsam genutzter Objekte automatisch (keine manuellen Sperren). Teilen Sie aktuelle Daten in Unterobjekte auf (z. B. eines pro Spieler), um Konflikte zu reduzieren. Konfliktminderung
<ID, PlayerData>Isolieren Sie stark frequentierte Felder (z. B. Tabelle). Verwenden Sie PTBs für atomare Operationen mit mehreren Objekten. Achten Sie auf:
ConflictTransaction: Geteilte Daten oder Batch-Aktualisierungen. Gasspitzen an gemeinsam genutzten Objekten. (Die Laufzeit von Sui behandelt Konflikte — optimieren Sie sie mithilfe von Daten-Sharding.)
In Sui Move, shared objects (marked with key + store) are essential for multi-user interaction but require careful concurrency design. Use them when state must be globally mutable (e.g., games, DAOs), while owned/immutable objects suit single-user scenarios. Sui serializes transactions per shared object automatically, but frequent writes may trigger ConflictTransaction errors—mitigate this by splitting hot fields into separate child objects (e.g., one per user) or batching updates. For high throughput, adopt event-sourcing patterns: store actions as immutable events and aggregate state periodically. Always minimize mutable shared fields and prefer atomic swaps via transfer::share_object over direct mutations
Geteilte Objekte im Vergleich zu eigenen Objekten: Wann sollte jedes verwendet werden
Verwenden Sie gemeinsam genutzte Objekte, wenn:
- Mehrere Benutzer müssen denselben Status ändern
- Das Objekt stellt eine öffentliche Ressource dar (wie eine Spielarena oder ein DAO)
- Sie benötigen Zugriffsmuster ohne Zugriffsrechte
Verwenden Sie eigene Objekte, wenn:
- Nur eine Adresse sollte das Objekt steuern
- Sie möchten die parallele Ausführung von Sui voll ausschöpfen
- Objekte stellen benutzerspezifische Vermögenswerte dar
Strategien zur Verwaltung der Parallelität
1. Unterobjektmuster (Konflikte reduzieren)
Teilen Sie häufig aktualisierte Felder in separate Objekte auf:
struct GameArena has key {
id: UID,
// Immutable or rarely changed fields
config: ArenaConfig,
// Split mutable state
player_state: Table<address, PlayerState>,
leaderboard: Leaderboard
}
struct PlayerState has key, store {
id: UID,
health: u8,
score: u64
}
2. Batch-Updates mit Vektoren/Tabellen
struct DAOVault has key {
id: UID,
// Store multiple pending actions
pending_votes: Table<ID, Vote>,
pending_deposits: Table<address, Deposit>
}
public entry fun batch_process(
vault: &mut DAOVault,
ctx: &mut TxContext
) {
// Process all pending items at once
let votes = table::remove_all(&mut vault.pending_votes);
process_votes(votes);
}
3. Epochenbasierte Verarbeitung
struct LendingPool has key {
id: UID,
current_epoch: u64,
next_epoch_data: EpochData,
current_epoch_data: EpochData
}
public entry fun advance_epoch(pool: &mut LendingPool) {
let finished = pool.current_epoch_data;
pool.current_epoch_data = pool.next_epoch_data;
pool.next_epoch_data = new_epoch_data();
process_finished_epoch(finished);
}
Techniken zur Konfliktvermeidung
1.Partitionierung auf Feldebene:
struct HighTrafficObject has key {
id: UID,
// Split into separate objects per "hot" field
stats_by_category: Table<u8, CategoryStats>
}
2.Warteschlange mit verzögerter Ausführung:
struct ActionQueue has key {
id: UID,
pending: VecMap<u64, Action>
}
public entry fun execute_ready_actions(
queue: &mut ActionQueue,
ready_up_to: u64
) {
// Processes actions in batches
}
3.Optimistische Parallelität mit der Versionierung:
struct Versioned has key {
id: UID,
version: u64,
data: vector<u8>
}
public entry fun update(
obj: &mut Versioned,
new_data: vector<u8>,
expected_version: u64
) {
assert!(obj.version == expected_version, EBAD_VERSION);
obj.data = new_data;
obj.version = expected_version + 1;
}
Praktische CLI-Beispiele
Objektabhängigkeiten vor dem Absenden überprüfen:
sui client inspect-transaction --serialize-unsigned <TX_BYTES>
Simulation von Konfliktszenarien:
sui move test --path <YOUR_PACKAGE> --gas-budget 10000
Zusammenfassung der Best Practices
1.Mutationen gemeinsam genutzter Objekte minimieren: Design für seltene Schreibvorgänge in gemeinsam genutzte Objekte
2.Untergeordnete Objekte verwenden: Zerlegen Sie den Status, um Streitpunkte zu reduzieren
3.Batch-Operationen: Gruppieren Sie alle Änderungen in einzelnen Transaktionen
4.Erwägen Sie Hybridmodelle: Kombinieren Sie eigene Objekte mit gelegentlicher gemeinsamer Koordination
5. sui-tool replay
Hotspots überwachen: Wird zur Analyse von Konflikten verwendet
Denken Sie daran, dass die Laufzeit von Sui über ihr Objektmodell automatisch einen Teil der Parallelität verarbeitet. Sie müssen Ihre Datenstrukturen jedoch trotzdem so gestalten, dass logische Konflikte minimiert werden.
Sie sollten einShared Objectin Sui Move verwenden, wenn mehrere Benutzer mit demselben Status interagieren müssen und diese Benutzer nicht alle demselben Besitzer unterstehen. Beispiele hierfür sind eine Spielarena, die allen Spielern offen steht, ein DAO-Abstimmungs-Tracker, der Stimmen von verschiedenen Adressen sammelt, oder ein Kreditpool, in den jeder einzahlen kann. Geteilte Objekte sind global zugänglich und können im Konsens aktualisiert werden, im Gegensatz zueigenen Objekten, die an eine einzige Adresse gebunden sind und ohne vollständigen Konsens geändert werden.
Sui behandelt die Parallelität bei gemeinsam genutzten Objekten, indem es für jede Transaktion, die sie verändert, einen vollständigen Konsens verlangt. ConflictTransaction
Wenn zwei Benutzer fast gleichzeitig versuchen, dasselbe gemeinsame Objekt zu ändern, ist nur eine Transaktion erfolgreich — andere werden mit einem Fehler abgelehnt. Dies macht gemeinsame Objekte leistungsfähig, führt aber auch zu Konflikten, wenn sie nicht sorgfältig entworfen werden.
Um hohe Parallelität ohne häufige ConflictTransaction
Fehler zu unterstützen, sollten SieEntwurfsmuster verwenden, die den veränderlichen Zustand isolieren. Anstatt alle veränderbaren Daten in einem einzigen gemeinsamen Objekt zu speichern, teilen Sie es in mehrere untergeordnete Objekte auf, von denen jedes seinen eigenen Besitzer oder gemeinsamen Status hat. Zum Beispiel in einer Spielarena:
struct Arena has key, store {
game_id: u64,
players: vector<address>,
}
struct PlayerState has key, store {
hp: u64,
energy: u64,
}
Machen Sie es Arena
gemeinsam, aber geben Sie jedem ein PlayerState
eigenes gemeinsames Objekt. Auf diese Weise können verschiedene Spieler ihren Status unabhängig voneinander aktualisieren, ohne dass es zu Konflikten kommt.
Ein anderes Muster ist die Strategie** „Index + Bucket“**: Behalte ein gemeinsames Indexobjekt bei, das auf einzelne Buckets oder Einträge verweist. Greifen Sie nur auf den Index zu, um den richtigen Eintrag abzurufen, und bearbeiten Sie dann den Eintrag selbst. Dadurch wird das Ausmaß der Überschneidung zwischen Benutzertransaktionen reduziert.
Wenn Sie eine strikte Reihenfolge benötigen (z. B. für Auktionen), implementieren Siemanuelles Warteschlangenmithilfe von Vektoren oder Maps innerhalb des gemeinsamen Objekts. Beachten Sie jedoch, dass für jede Mutation immer noch ein Konsens erforderlich ist und unter Last fehlschlagen kann. In diesen Fällen sollten Sie erwägen, die Reihenfolge an das Frontend zu verlagern oder Schreibvorgänge stapelweise durchzuführen.
Zusammengefasst:
- Verwenden Sie gemeinsam genutzte Objekte, wenn viele unabhängige Benutzer auf den Status zugreifen müssen.
- Vermeiden Sie es, alle veränderbaren Felder in einem einzigen gemeinsamen Objekt zusammenzufassen — teilen Sie sie in Unterobjekte auf.
- Verwenden Sie gemeinsam genutzte und dynamische untergeordnete Objekte, um die Konfliktrate zu senken.
- Erwarten Sie
ConflictTransaction
Fehler bei hohen Konflikten und versuchen Sie es erneut im Frontend. - Bevorzugen Sie nach Möglichkeit Updates, die nur angehängt werden, anstatt Mutationen an Ort und Stelle vorzunehmen.
Wenn Sie in Sui Move mit gemeinsam genutzten Objekten entwerfen, müssen Sie im Grunde zwischenKomfort für den Zugriff mehrerer Benutzerund demKonfliktrisikowählen. Da Sui ein objektzentriertes und ressourcenorientiertes Modell verwendet, hängt das richtige Muster davon ab, ob Ihr Anwendungsfall kollaborativen Zugriff oder isolierte Steuerung erfordert. Hier ist eine strukturierte Art, darüber nachzudenken:
###Wann sollten geteilte oder eigene Objekte verwendet werden
*Eigene Objekteeignen sich am besten, wenn ein einzelner Benutzer die volle Kontrolle über einen Vermögenswert benötigt (z. B. die Münzen einer Brieftasche, das Inventar eines Spielers oder ein einzigartiges NFT). Transaktionen, an denen sie beteiligt sind, werden nicht in Konflikt geraten, es sei denn, dasselbe Objekt wird wiederverwendet. *Geteilte Objektesind sinnvoll, wenn mehrere Benutzer dasselbe Bundesland lesen oder schreiben müssen (z. B. ein DAO-Führungsrekord, eine Bestenliste in einer Spielarena, ein Tresor aus dem Kreditpool). Sie ermöglichen globalen Zugriff, ohne dass autorisierte Übertragungen erforderlich sind, aber sie sind mit Problemen bei der Parallelität verbunden.
###Parallelitätsmanagement in Sui
ConflictTransaction
Die Laufzeit von Sui serialisiert automatisch Transaktionen, die dasselbeveränderbare gemeinsame Objektberühren. Das heißt, wenn zwei Benutzer versuchen, dasselbe gemeinsame Objekt zu aktualisieren, wird einer erfolgreich sein und der andere erhält eine Fehlermeldung. Sperren oder Warteschlangen müssen nicht manuell codiert werden — die Konfliktlösung erfolgt auf der Ausführungsebene. Häufige Konflikte können jedoch den Durchsatz beeinträchtigen. Daher besteht Ihre Aufgabe darin,Zustandslayouts so zu entwerfen, dass Überschneidungen minimiert werden.
###Bewährte Methoden zur Vermeidung häufiger Konflikte
*Veränderbarer Status aufteilen: Anstatt eines einzelnen „Mega-Objekts“, teilen Sie es in kleinere untergeordnete Objekte auf. Trennen Sie beispielsweise in einem Kredittresor die Position jedes Benutzers als eigenes oder teilweise gemeinsam genutztes Objekt, sodass der Tresor selbst größtenteils statisch bleibt. Dadurch werden Schreibkonflikte reduziert. *Verwenden Sie nach Möglichkeit unveränderliche Felder: Speichern Sie Metadaten oder Referenzdaten in unveränderlichen Unterobjekten, sodass Transaktionen, die nur lesen, nicht mit denen kollidieren, die schreiben. *Vorsichtiges Stapeln von Vorgängen: Wenn Ihre Vertragsgestaltung mehrere Schreibvorgänge in dasselbe gemeinsame Objekt erfordert, sollten Sie erwägen, sie in einem einzigen Transaktionsblock zusammenzufassen, um mehrere Konflikte zu vermeiden. *Sharding-Muster: Bei Dingen wie Bestenlisten oder DAOs solltest du den Status nach Gruppe, Runde oder Identifier teilen, sodass nicht alle Transaktionen den exakt gleichen Objektpfad erreichen.
###Fallstricke, auf die Sie achten müssen
*Monolithische gemeinsame Objekte: Wenn Sie alles in einem gemeinsamen Objekt zusammenfassen, kommt es unter Last zu starken Konflikten und ständigen Konflikten. *Überbeanspruchung gemeinsam genutzter Objekte: Wenn die Daten als Eigentum modelliert werden können, ziehen Sie diesen Weg vor — das ist billiger und es ist weniger wahrscheinlich, dass es zu Engpässen kommt. *Zugriffsmuster ignorieren: Wenn es sich bei den meisten Interaktionen um Lesevorgänge mit wenigen Schreibvorgängen handelt, sollten Sie bei der Entwicklung auf unveränderliche Snapshots und nicht auf einen veränderbaren gemeinsamen Zustand achten.
###Praxisbeispiel
Stellen Sie sich vor, Sie bauen einen DAO-Vote-Tracker:
*Schlechtes Muster: Ein einziges gemeinsames Objekt, das jede Abstimmung speichert und von allen Teilnehmern aktualisiert wird.
*Besseres Muster: Jeder Wähler erstellt ein eigenes Vote
Objekt, das auf den Vorschlag verweist, während das gemeinsame DAO-Objekt die Ergebnisse nur in regelmäßigen Abständen aggregiert. Auf diese Weise kollidieren parallele Abstimmungen nicht.
###Transaktionsblock
Eingaben → Benutzer senden Transaktionen für gemeinsam genutzte oder eigene Objekte. Prozess → Die Laufzeit von Sui serialisiert Transaktionen auf demselben veränderbaren gemeinsamen Objekt. Ergebnis → Erfolgreiche Schreibvorgänge werden ausgeführt, andere erhalten Konfliktfehler; das Aufteilen von Objekten verringert die Wahrscheinlichkeit von Konflikten.
Great questions—this is exactly the crux of building “high-fanout” apps on Sui. Here’s a practical playbook you can follow.
🧭 When to use a shared object (vs owned)
Use a shared object only when multiple independent parties must mutate the same piece of state and you need one canonical result (e.g., AMM pool reserves, an arena’s match registry, a DAO proposal’s tally). Prefer owned objects when the state is per-user, per-position, or per-item and can evolve independently (inventories, user balances, open positions).
Rule of thumb: put the coordination surface in a shared object, and everything else in owned objects that can run in parallel.
⚙️ What Sui does with concurrent access
- Any tx that mutates a shared object goes through consensus and is totally ordered. Conflicting writes to the same fields are serialized; others proceed in parallel.
- You don’t manually lock; you design to avoid hotspots. Conflicts show up as
ConflictTransaction
when many txs try to bump the same version.
🏗️ High-concurrency design patterns (with Move tips)
1) Root-manager + owned positions
Keep a minimal shared root; put user/position state in owned objects so deposits/claims mostly touch owned data.
module example::vault {
use sui::tx_context::TxContext;
struct Vault has key { /* config only; no growing vectors */ }
struct Position has key { owner: address, /* state */ }
/// Shared root only needed to mint/close positions or checkpoint.
public entry fun open_position(v: &mut Vault, ctx: &mut TxContext): Position { /* ... */ }
/// Hot path touches owned Position only → parallel.
public entry fun deposit(pos: &mut Position, amount: u64) { /* ... */ }
}
Why it scales: most traffic avoids the shared root altogether.
2) Shard by key (dynamic fields / tables)
Instead of one big shared map, create N shard objects (shared) under a registry and route by hash(key) % N
. Each shard is a separate contention domain.
/// registry is shared; it stores IDs of shard objects
struct Registry has key { shards: vector<ID> }
/// choose shard once and keep it stable for that key
fun shard_for(reg: &Registry, key: &vector<u8>): ID { /* hash(key) % len */ }
Tip: don’t update the registry on every user op; mutate only the target shard.
3) Dynamic fields on a shared “anchor”, not growing vectors
Avoid vector.push
on a shared object (resizes = conflicts). Use dynamic fields (key → value) so each entry mutates independently.
SharedAnchor
└─ df[key=user] = tiny record (or pointer to owned object)
Move APIs: sui::dynamic_field::{add, borrow_mut, remove}
.
4) Two-phase “ticket” pattern
Have the shared object mint a ticket/capability (owned) that authorizes a later operation done off the hot path.
- Light touch on shared root → mint
Ticket
. - User completes heavy work by presenting the
Ticket
and mutating only owned/child objects.
Reduces churn on the shared root, and gives you idempotency (ticket can be one-time-use).
5) Append-only events, deferred aggregation
If you’re tempted to keep a total_*
counter on the shared root (a hotspot), emit events on each action and aggregate off-chain or in a periodic checkpoint entry that rolls up per-shard totals.
6) Split mutable fields into sub-objects
If one field changes much more frequently (e.g., queue head), peel it into its own child object (owned or shared as needed). Then updates don’t bump the root’s version.
🧪 Avoiding ConflictTransaction
in practice
- Keep the cut set small: Each entry function should touch as few objects as possible.
- No growing vectors on shared roots; use dynamic fields or sharded children.
- Stable routing: Deterministic key→shard mapping; never rehash live keys.
- Idempotency: Use tickets/nonces so retries don’t double-apply.
- Batch carefully: If you must touch multiple entries atomically, use a PTB—but keep it within a single shard when possible.
- Backoff & retry: On the client, exponential backoff for known conflict aborts.
🔍 Minimal conflict checklist
- Shared root is configuration + pointers only.
- Hot paths mutate owned positions or sharded children.
- Per-user/per-item state is not inside the root.
- No
vector.push
on shared; use dynamic fields. - Periodic checkpoint function consolidates, not every tx.
🛡️ Security & correctness notes
- Gate privileged ops with capabilities (e.g.,
AdminCap
,MintCap
); store caps in owned objects, not globals. - Validate invariants in shared entry points (sum of shard totals, proposal status transitions, etc.).
- Emit events for auditability; they are cheap and conflict-free.
Quick templates by use case
- Game arena: Shared
Arena
(config/match index) + ownedPlayer
/Loadout
. Match joins go toShard[hash(match_id)]
. - DAO voting: Shared
Proposal
(immutable metadata) + dynamic fields per voter or ownedBallot
tickets. Tally via periodic checkpoint. - Lending vault: Shared
Registry
+ ownedPosition
s; price/oracle reads are immutable; rebalances via sharded pools.
Weißt du die Antwort?
Bitte melde dich an und teile sie.
Sui is a Layer 1 protocol blockchain designed as the first internet-scale programmable blockchain platform.
Verdiene deinen Anteil an 1000 Sui
Sammle Reputationspunkte und erhalte Belohnungen für deine Hilfe beim Wachstum der Sui-Community.

- Warum benötigt BCS eine genaue Feldreihenfolge für die Deserialisierung, wenn Move-Strukturen benannte Felder haben?65
- Fehler bei der Überprüfung mehrerer Quellen“ in den Veröffentlichungen des Sui Move-Moduls — Automatisierte Fehlerbehebung55
- Sui-Transaktion schlägt fehl: Objekte sind für eine andere Transaktion reserviert49
- So maximieren Sie Ihre Gewinnbeteiligung SUI: SUI Staking vs Liquid Staking313
- Sui Move Error - Transaktion kann nicht verarbeitet werden Keine gültigen Gasmünzen für die Transaktion gefunden315