Допис
Діліться своїми знаннями.
Шаблони проектування та управління паралельністю для спільних об'єктів у Sui Move
Я намагаюся обгорнути голову правильний архітектурний візерунок під час роботи з спільними об'єктами у Sui Move, особливо коли декілька користувачів повинні взаємодіяти з ними одночасно (наприклад, на ігровій арені, відстежувачі голосів DAO або сховищі позики).
Я читав, що спільні об'єкти можуть спричинити проблеми синхронізації, але мені все ще незрозуміло:
- Коли саме я повинен використовувати
shared
об'єкт vs.owned
? - Як Sui обробляє одночасні спроби транзакцій на одному спільному об'єкті — чи потрібно вручну ставити в чергу/блокувати речі?
- Яка найкраща практика для проектування модулів, які підтримують високу паралельність, але уникають частих
ConflictTransaction
помилок? - Чи повинен я робити щось особливе (наприклад, розділяти змінювані поля на підоб'єкти), щоб зменшити суперечність?
- Sui
- Architecture
- NFT Ecosystem
- Move
Відповіді
13Коли ви створюєте DApp на Sui, де кілька користувачів повинні взаємодіяти з одним станом, наприклад, на ігровій арені, протоколі кредитування або DAO, вам слід використовуватиспільні об'єктизамість власних. Спільні об'єкти є загальнодоступними та змінюваними, тобто кожен може викликати функції введення на них, якщо вони знаходяться в глобальному графіку об'єктів. Навпаки, об'єкти, що належать, є приватними для користувача і ідеально підходять для особистих активів, таких як гаманці або інвентар. Отже, вам слід використовувати спільний об'єкт, коли оновлення стану повинні бути видимими та придатними для використання багатьма користувачами одночасно.
Sui обробляє одночасні транзакції на спільних об'єктах за допомогою механізму під назвоюперевірка причинного порядку, який вимагає від вас явно надати останню відому версію спільного об'єкта. Якщо два користувачі намагаються змінити один і той же спільний об'єкт одночасно із застарілими версіями, один буде успішним, а інші - ConflictTransaction
помилкою. Sui не встановлює черги і не блокує спільні об'єкти, тому вам потрібно розробити модулі Move, щоб мінімізувати перекриття записів. Одним з найкращих способів зменшити конфлікт єпроектування для паралелізму. Наприклад, замість того, щоб зберігати всі змінні стани в кореневому спільному об'єкті, ви можетерозділити поля високої суперечності на окремі дочірні об'єкти. Потім кожного з цих дітей можна написати самостійно, зменшуючи ймовірність конфліктів угод.
Чудовою практикою є збереження основного спільного об'єкта як каталогу та переміщення детальних, часто оновлюваних станів, таких як результати гравців, голоси чи залишки позик - у динамічні поля або менші підоб'єкти. Таким чином, користувачі оновлюють лише конкретну необхідну їм частину, а не весь спільний об'єкт. Також розумно розділяти компоненти, що важкі для читання та важкі для запису. Крім того, вам слід створювати чіткі та детерміновані потоки транзакцій, які завжди використовують найсвіжішу версію спільних об'єктів та логіку повторної спроби для клієнтів для обробки невдалих транзакцій.
Ви можете дізнатися більше про дизайн спільних об'єктів та пом'якшення конфліктів у документації Sui тут: https://docs.sui.io/concepts/objects#shared-objects.
Якщо ви керуєте таким чином, як відстежувач голосів, ось спрощений приклад блоку транзакцій, щоб зменшити конфлікт:
const tx = new TransactionBlock();
tx.moveCall({
target: `$ {PackageId} ::трекер голосів: :голос_голосу`,
аргументи: [
tx.SharedObject (VoteTrackerId),//посилання на спільний об'єкт
tx.pure (VoterId),//об'єкт власника або відкритий ключ
tx.pure (ідентифікатор пропозиції),//чисті дані
tx.pure (Голосовий показ)
]
});
У Sui Moveспільні об'єкти(позначеніkey + store
) є важливими для багатокористувацької взаємодії, але вимагають ретельного проектування паралельності. Використовуйте їх, коли стан повинен бути глобально змінним (наприклад, ігри, DAO), тоді як володані/незмінні об'єкти відповідають сценаріям одного користувача. Sui автоматично серіалізує транзакції на спільний об'єкт, але часті записи можуть викликати помилки. По ConflictTransaction
м'якшіть це за допомогоюрозділення гарячих поляна окремі дочірні об'єкти (наприклад, по одному на користувача) або пакетуючи оновлення. Для високої пропускної здатності застосовуйтешаблони пошуку подій: зберігайте дії як незмінні події та періодично агрегуйте стан. Завжди мінімізуйте змінювані спільні поля та віддайте перевагу атомним обмінам transfer::share_object
через прямі мутації.
У Sui Move ефективне поводження з спільними об'єктами та паралельністю вимагає ретельного проектування, щоб уникнути умов гонки та високої суперечності. Ось розбивка найкращих практик та архітектурних зразків:
1.Коли використовувати спільні та власні об'єкти:
*Спільні об'єкти: Використовується, коли декілька користувачів повинні взаємодіяти з одним і тим же об'єктом одночасно (наприклад, загальний стан гри, відстежувач голосів DAO). *Власні об'єкти: Використовуйте, коли об'єкт є специфічним для одного користувача або облікового запису, уникаючи спільного стану та зменшуючи проблеми паралельності.
2.Одночасне оброблення транзакцій у Sui:
- Sui обробляє паралельність автоматично за допомогоюЗамків транзакції, щоб запобігти одночасним змінам того ж об'єкта.
- Вамнепотрібновручну ставити в чергу або блокувати спільні об'єкти, оскільки Sui застосовує блокування на рівні об'єкта. Однакви можете отримати помилки ConflictTransaction, якщо декілька транзакцій конфліктують на одному об'єкті.
3.Найкращі практики для високої паралельності:
*Мінімізувати контент: Розділіть змінювані поля на окремі підоб'єкти, щоб дозволити паралельне оновлення різних частин об'єкта. *Уникайте гарячих потоків: розподіліть часто змінений стан між кількома об'єктами (наприклад, замість єдиної спільної книги, розділіть її на кілька відкладів або облікових записів). *Версія: Використовуйте об'єкти з версіями або створюйте нові об'єкти для відстеження оновлень замість того, щоб повторно змінювати один і той же об'єкт.
4.Управління суперечливістю:
- Розгляньте можливістьрозділити змінювані поля на менші об'єкти, щоб зменшити суперечність. Це дозволяє одночасно оновлювати різні частини об'єкта, зменшуючи ймовірність конфліктів.
- Використовуйтеатомні транзакції, щоб об'єднати пов'язані дії в одну, забезпечуючи узгодженість між пов'язаними об'єктами.
Приклад:
Якщо у вас єтрекер голосуюдля DAO:
- Замість того, щоб зберігати всі голоси в одному спільному об'єкті, розділіть їх на кілька об'єктів (наприклад, по одному на пропозицію), дозволяючи паралельно оновлювати кожну пропозицію, зменшуючи суперечності.
Висновок:
Для високої паралельності мінімізуйте суперечки, розподіляючи стан, використовуючи підоб'єкти та використовуючи автоматичну обробку транзакцій Sui. Переконайтеся, що ви розумієте свої шаблони доступу та структуруйте об'єкти, щоб мінімізувати точки конфлікту.
Розуміння шаблонів проектування та керування паралельністю спільних об'єктів у Sui Move
Під час роботи зспільними об'єктамиуSui Moveкерування паралельністю стає критичним, оскільки кільком користувачам може знадобитися взаємодія з одним об'єктом одночасно. Особливо це стосується випадків використання, таких якігрові арени,трекери голосування DAOтасховища для кредитування, де очікується висока паралельність. Мережа Sui надає деякі функції, які допомагають керувати паралельністю, але все одно вимагає ретельного проектування, щоб уникнути поширених підводних каменів, якConflictTransaction Errors.
1.Коли використовувати спільні об'єкти та об'єкти, що належати
*Власні об'єкти:
-
Об'єкт є власником**, якщо ним керує одна адреса, яка може передавати або змінювати його. ***Використовуйте об'єкти, що належать, коли ви очікуєте, що одна сутність контролюватиме об'єкт та взаємодіятиме з ним. Наприклад, якщо у вас є гаманець з монетами, кожен гаманець має право власності на власні монети. *Спільні об'єкти:
-
Спільні об'єкти можуть бути доступні та змінені кількома адресами одночасно. Sui дозволяє визначати об'єкти якспільними, роблячи їх змінними та надаючи доступ декільком сторонам. *Використовуйте спільні об'єктидля сценаріїв, коли кілька користувачів або адрес повинні взаємодіяти з одним об'єктом, наприклад:
*Відстежувачі голосів DAO: Кілька користувачів можуть голосувати за один і той же об'єкт. *Сховища для кредитування: Кілька користувачів можуть позичати та позичати з одного сховища. *Ігрові арени: Кілька користувачів взаємодіють із станом гри одночасно.
Ключове врахування: Спільні об'єкти слід використовувати обережно, оскільки вони можуть спричинитисуперечли— ситуації, коли кілька транзакцій намагаються отримати доступ до одного об'єкта та змінити одразу.
2.Спроби паралельності та транзакцій щодо спільних об'єктів
Sui гарантує, що одночаснітранзакціїна одномуспільному об'єктіобробляються правильно, застосовуючиізоляцію транзакції. Якщо кілька транзакцій намагаються одночасно мутувати один і той же спільний об'єкт, одна з них буденевдалачерезсуперечли.
Коли транзакція намагається змінити спільний об'єкт, який вже змінювався іншою транзакцією, Sui поверне помилкуConflictTransaction. ОднакSui обробляє більшість керування паралельністю внутрішнього, і вамне потрібно вручну ставити в чергу або блокуватиоб'єкти. Натомість вам потрібно розробити свій контракт, щоб мінімізувати суперечки та уникнути ситуацій, коли дві транзакції часто конфліктують.
3.Найкращі практики щодо високої паралельності та зменшення конфліктних помилок транзакції
Щоброзробити модулі, які можуть обробляти високу паралельність і уникати частих помилокConflictTransaction, дотримуйтесь наступних найкращих практик:
a.Мінімізуйте точки суперечки:
*Обмеження змінюваного доступу: Зберігайте кількість змінних полів у спільних об'єктах якомога меншою. Кожне змінне поле вводить потенційну точку суперечки. *Використовуйте об'єкти, що належать для незалежних даних: Замість того, щоб робити все спільним, зберігайте незалежні дані у власних об'єктах. Наприклад, якщо у вас є дані, специфічні для користувача (наприклад, баланс), зберігайте їх у власному об'єкті, а не у спільному.
б.Використовуйте шаблон «Розділення станів»:
-
Розділіть спільний об'єкт накілька підоб'єктів, щоб зменшити суперечність. Наприклад, замість того, щоб мати один спільний об'єкт, який відстежує весь стан гри, ви можете розділити його на кілька підоб'єктів:
-
По одному для кожного штатугравця.
-
Один дляналаштувань ігра.
-
Один дляданих таблиці лідерів.
-
Таким чином, транзакції, пов'язані з різними частинами системи, можуть відбуватися одночасно, не блокуючи один одного.
c.Пакетні операції:
- Під час роботи зі спільними об'єктами пакетуйте оновлення, щоб зменшити кількість транзакцій, які потребують взаємодії з об'єктом. Це може допомогти уникнути частих конфліктів. *Використовуйте колекції, як-от вектори або набори, щоб керувати кількома оновленнями в одній транзакції.
d.Використовуйте атомні операції:
- По можливості розробляйте свої модулі для використання атомних операцій, де це можливо. Наприклад, замість того, щоб мати окремі транзакції для перевірки умови, а потім оновлення поля, об'єднайте перевірки та оновлення в одну атомну операцію.
e.Логіка повторного спробування:
- Хоча Sui обробляє повторні спроби внутрішньо, ви можете реалізувати логіку повторної спроби на рівні програми, щоб обробляти випадкові помилки суперечок. Наприклад, якщо
ConflictTransaction
виникає помилка, ви можете просто повторити операцію або поставити її в чергу для подальшого виконання.
4.Зменшення суперечності шляхом розділення змінних полів на підоб'єкти
Це настійно рекомендована практика. Під час роботи зі спільними об'єктами, чим більше полів у спільному об'єкті**, які єзмінними, тим більша ймовірність того, що дві транзакції спробують одночасно змінити одне і те саме поле.
*Приклад 1: Якщо у вас є спільний об'єкт, що представляєсховищей, розділіть його на підоб'єкти:
- Один длядепозитів: Відстежуйте окремі депозити окремо.
- Один дляпозики: Відстежуйте індивідуальні позики окремо.
- Один длястану сховища: Відстежуйте загальну інформацію про стан (наприклад, загальна вартість, процентна ставка).
Таким чином, транзакція, яка змінює один підоб'єкт (наприклад, підоб'єктпозики), не суперечить транзакції, яка змінює інший (наприклад, підоб'єктдепозит).
*Приклад 2: Наігровій арену:
- Розділіть стан гри на підоб'єкти для кожного гравця, стан гри та статистику бою. Це знижує ризик конфліктів, коли різні гравці взаємодіють зі своїми окремими ігровими станами.
Розділивши змінювані поля напідоб'єкти, ви зменшуєте ймовірність того, що кілька користувачів намагатимуться змінити один і той же об'єкт одночасно.
5.Інші методи управління паралельністю в SUI
Блокування (явні блокування): Хоча Sui не вимагає від вас вручну обробляти блокування, у деяких випадках ви можете застосуватиявні замкиза допомогоюоб'єктівблокування об'єктів*(окремих об'єктів, які гарантують, що лише одна транзакція може отримати доступ до певного ресурсу одночасно).
*Тимчасова ізоляція: Якщо ваші об'єкти змінюються лише зрідка, подумайте про введенняізоляції на основі часу. Наприклад, якщо ви керуєте сховищем або системою голосування, встановітьперіоди голосуванняабовікна транзакцій, щоб обмежити взаємодію протягом певного часу.
6.Приклад коду управління паралельністю з підоб'єктами
Ось приклад, який ілюструє, як зменшити суперечність, розділившикредитний сховищена менші підоб'єкти:
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;
}
}
Короткий зміст
*Використовуйте спільні об'єкти, коли декілька користувачів повинні взаємодіяти з одним і тим же об'єктом одночасно (наприклад, голоси DAO, стан гри, сховища кредитування). *Мінімізуйте контент, розділивши великі спільні об'єкти на менші підоб'єкти та зменшивши кількість змінних полів. *Уникайте частих помилок ConflictTransaction, дотримуючись найкращих практик, таких як розподіл станів, операції пакетування та використання атомних операцій. *Логіка повторної спробаціїтаоптимістичний контроль паралельностіможна використовувати для витонченого вирішення конфліктів.
- Модель транзакцій Sui тавирішення конфліктівнадійні, аледизайнваших спільних об'єктів є ключовим для забезпечення ефективного одночасного доступу.
Дотримуючись цих принципів проектування, ви зможете керувати високою паралельністю у своїх модулах на основі MOVE, уникаючи типових підводних каменів, таких якконфліктитапомилки транзакції.
Використовуйтеспільні об'єктидля доступу до декількох записувачів (наприклад, ігри, DAO). Ключові візерунки:
1.Власність проти акції
- Власність: Однописьменник (швидше).
- Спільний: Одночасні записи (вищий газ).
2.Поводження з паралельною
- Sui послідовність спільних об'єктів TX автоматично (без ручних блокувань).
- Розділіть гарячі дані на підоб'єкти (наприклад, 1 на гравця), щоб зменшити конфлікти.
3.Пом'якшення конфліктів
- Ізолюйте поля з високим трафіком (наприклад,
Table<ID, PlayerData>
). - Використовуйте PTB для атомних багатооб'єктних операцій.
Слідкуйте за:
-ConflictTransaction
: Розділити дані або пакетні оновлення.
- Газові сплески на спільних об'єктах.
- (Час виконання Sui обробляє конфлікти - оптимізація за допомогою фрагментації даних. ) *
Використовуйтеспільні об'єкти(transfer::share_object
), коли кілька користувачів повинні мутувати один і той же об'єкт (наприклад, сховище, DAO, стан гри). Використовуйтевласнийінакше.
TransactionLockConflict
Sui обробляє паралельність за допомогоюконсенсусу Narwhal & Tusk: конфліктні транзакції на спільному об'єкті серіалізуються — лише одна досягає успіху за раунд; інші не вдаються. Ручне блокування не потрібно, алеви повинні проектувати для вилучення.
Кращі практики:
- Мінімізувати змінний стан спільних об'єктів; розділити гарячі точки на окремі підоб'єкти (наприклад, спільні ресурси сховища для кожного користувача).
- Використовуйте
VecMap
абоTable
для масштабованих відображень. - Уникайте тривалих обчислень у спільних функціях.
- Випускайте події замість зберігання ефемерного стану.
- Для систем з високою суперечливістю використовуйте схемипакетуванняабосхеми-розкриттядля зменшення конфліктів.
Спільні об'єкти є глобально доступними, але потребують більшої напруги та суперечності - оптимізовані для ідентифікації та логіки повторної спроби в клієнтському коді.
Дляспільних об'єктіву Sui Move використовуйте ці шаблони для керування паралельністю:
####1. Спільний проти власного?
-Спільний об'єкт (key + store
):
- Використовуйте дляглобального стану(наприклад, ігри, DAO).
- Дозволяєпаралельні записи(на відміну від серіалізованих TX EVM).
struct GameArena has key, store { id: UID, players: vector<address> }
-Власний об'єкт:
- Використовуйте дляданих, специфічних для користувача(наприклад, NFT, гаманці).
struct PlayerInventory has key { id: UID, items: vector<Item> }
####2. Обробка паралельності -Без ручних блокувань: Suiвирішує конфлікти автоматично(на відміну від EVM). -Розділити контент: Розбийте спільні об'єкти наменші підоб'єкти(наприклад, на гравця або на осколок).
struct PlayerScore has key, store { id: UID, points: u64 } // Less contention
####3. Зменшити ConflictTransaction
помилки
-Ізолювати записи: Оновитирізні поляв окремих TX.
-Використовуйте &mut
розумно: Уникайте широких мутацій.
public entry fun update_score(
arena: &mut GameArena,
player: address,
points: u64
) { /* ... */ } // Only touches 1 player’s data
####4. Найкращі практики -Пакетні оновлення: Групуйте неконфліктні операції (наприклад, голоси в DAO). -Керування подією: Випускайте події замість мутаційного стану, де це можливо.
struct VoteEvent has copy, drop { voter: address, choice: u8 }
Використовуйте спільні об'єкти для доступу до декількох записувачів (наприклад, ігри, DAO). Ключові візерунки:
Власний проти спільного
Власність: Однописьменник (швидше). Спільно: Одночасні записи (вищий газ). Обробка паралельності
Sui послідовно виконує спільні об'єкти TX автоматично (без ручних блокувань). Розділіть гарячі дані на підоб'єкти (наприклад, 1 на гравця), щоб зменшити конфлікти. Пом'якшення конфліктів
Ізолюйте поля з високим трафіком (наприклад, таблиця<ID, PlayerData>). Використовуйте PTB для атомних багатооб'єктних операцій. Слідкуйте за:
ConflictTransaction: розділити дані або пакетні оновлення. Газові сплески на спільних об'єктах. (Час виконання Sui обробляє конфлікти — оптимізуйте за допомогою фрагментації даних.)
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
Спільні та власні об'єкти: коли використовувати кожен
Використовуйте спільні об'єкти, коли:
- Кілька користувачів повинні мутувати один і той же стан
- Об'єкт представляє публічний ресурс (наприклад, ігрову арену або DAO)
- Вам потрібні шаблони доступу без дозволу
Використовуйте об'єкти, що належать, коли:
- Тільки одна адреса повинна контролювати об'єкт
- Ви хочете повністю використати паралельне виконання Суй
- Об'єкти представляють специфічні для користувача активи
Стратегії управління паралельністю
1. Шаблон підоб'єкта (зменшення суперечності)
Розділіть часто оновлювані поля на окремі об'єкти:
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. Пакетні оновлення за допомогою векторів/таблиць
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. Обробка на основі епохи
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);
}
Методи уникнення конфліктів
1.Розділення на рівні поля:
struct HighTrafficObject has key {
id: UID,
// Split into separate objects per "hot" field
stats_by_category: Table<u8, CategoryStats>
}
2.Черга затримки виконання:
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.Оптимістична паралельність з версіюванням:
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;
}
Практичні приклади CLI
Перевірка залежностей об'єктів перед подачею:
sui client inspect-transaction --serialize-unsigned <TX_BYTES>
Імітація сценаріїв суперечок:
sui move test --path <YOUR_PACKAGE> --gas-budget 10000
Підсумок найкращих практик
1.Мінімізація мутацій спільних об'єктів: Дизайн для нечастих записів до спільних об'єктів
2.Використовуйте дочірні об'єкти: Розкладіть стан, щоб зменшити точки суперечки
3.Пакетні операції: групуйте пов'язані зміни в окремі транзакції
4.Розглянемо гібридні моделі: Об'єднуйте об'єкти, що належать, з періодичною спільною координацією
5. sui-tool replay
Монітор гарячих потоків: Використовуйте для аналізу суперечок
Пам'ятайте, що час виконання Sui автоматично обробляє певну паралельність через свою об'єктну модель, але вам все одно потрібно розробити свої структури даних, щоб мінімізувати логічні конфлікти.
Ви повинні використовуватиспільний об'єкту Sui Move, коли декілька користувачів мають взаємодіяти з одним і тим же станом, і ці користувачі не перебувають під одним власником. Приклади включають ігрову арену, відкриту для всіх гравців, відстежувач голосів DAO, який збирає голоси з різних адрес, або кредитний пул, в який кожен може внести депозит. Спільні об'єкти є глобально доступними та оновлюваними через консенсус, на відміну відоб'єктів власності, які прив'язані до однієї адреси та змінені без повного консенсусу.
Sui обробляє паралельність спільних об'єктів, вимагаючи повного консенсусу для будь-якої транзакції, яка їх мутує. ConflictTransaction
Коли два користувачі намагаються змінити один і той же спільний об'єкт майже одночасно, лише одна транзакція досягає успіху, інші будуть відхилені з помилкою. Це робить спільні об'єкти потужними, але також створює проблеми суперечок, якщо вони не розроблені ретельно.
Щоб підтримувати високу паралельність, не стикаючись з частими ConflictTransaction
помилками, слід використатишаблони дизайну, які ізолюють змінний стан. Замість того, щоб зберігати всі змінювані дані в одному спільному об'єкті, розділіть їх на кілька дочірніх об'єктів, кожен з яких має власне право власності або спільний статус. Наприклад, на ігровій арені:
struct Arena has key, store {
game_id: u64,
players: vector<address>,
}
struct PlayerState has key, store {
hp: u64,
energy: u64,
}
Зробі Arena
ть спільним, але дайте кожному PlayerState
свій власний спільний об'єкт. Таким чином, різні гравці можуть оновлювати свій стан незалежно, не конфліктуючи.
Іншим шаблоном є стратегія** «index + bucket»**: зберігайте спільний об'єкт індексу, який вказує на окремі відра або записи. Доступ лише до індексу, щоб отримати правильний запис, а потім оперувати самим записом. Це зменшує кількість перекриття між транзакціями користувача.
Якщо вам потрібно суворе впорядкування (наприклад, для аукціонів), реалізуйтеручну чергу, використовуючи вектори або карти всередині спільного об'єкта, але знайте, що кожна мутація все ще потребує консенсусу і може вийти з ладу під навантаженням. У цих випадках розгляньте можливість розвантаження замовлення на інтерфейс або пакетування записів.
Підсумовуючи:
- Використовуйте спільні об'єкти, коли стан має бути доступний багатьом незалежним користувачам.
- Уникайте розміщення всіх змінних полів в один спільний об'єкт — розділіть їх на підоб'єкти.
- Використовуйте спільні + динамічні дочірні об'єкти для зниження рівня конфліктів.
- Очіку
ConflictTransaction
йте помилок під час високої суперечності та повторіть спробу на інтерфейсі. - Віддайте перевагу лише додаванню оновлень, де це можливо, а не мутації на місці.
Коли ви проектуєте спільні об'єкти в Sui Move, ви, по суті, обираєте між зручністю для багатокористувацького доступутаризиком суперечки**. Оскільки Sui використовує об'єктно-орієнтовану та ресурсоорієнтовану модель, правильна модель залежить від того, чи вимагає ваш випадок використання спільний доступ чи ізольований контроль. Ось структурований спосіб подумати про це:
###Коли використовувати спільні та власні об'єкти
*Власні об'єктинайкраще підходять, коли одному користувачеві потрібен повний контроль над активом (наприклад, монетами гаманця, інвентарем гравця або унікальним NFT). Транзакції, пов'язані з ними, не будуть конфліктувати, якщо той самий об'єкт не буде використаний повторно. *Спільні об'єктимають сенс, коли кільком користувачам потрібно читати або записувати в одному стані (наприклад, запис управління DAO, таблиця лідерів ігрової арени, сховище пулу кредитування). Вони забезпечують глобальну доступність без необхідності дозволених переказів, але вони мають проблеми з паралельністю.
###Управління паралельністю в SUI
ConflictTransaction
Виконання Sui автоматично серіалізує транзакції, які торкаються того самогозмінюваного спільного об'єкта, тобто якщо два користувачі спробують оновити один спільний об'єкт, один буде успішним, а інший отримає помилку. Вам не потрібно вручну кодувати блокування або черги — вирішення конфліктів обробляється на рівні виконання. Однак часті конфлікти можуть погіршити пропускну здатність, тому ваша робота полягає у створенні макетів стану, які мінімізують перекриття**.
###Найкращі практики уникнення частих конфліктів
*Розділіть змінний стан: Замість одного «мегаоб'єкта» розбийте його на менші дочірні об'єкти. Наприклад, у сховищі кредитування відокремте позицію кожного користувача як власного або частково спільного об'єкта, залишаючи сам сховище переважно статичним. Це зменшує суперечність письма. *Використовуйте незмінні поля, де це можливо: Зберігайте метадані або довідкові дані в незмінних підоб'єктах, щоб транзакції, які тільки читаються, не стикаються з тими, які записують. *Обережно проводити пакетні операції: Якщо ваш дизайн контракту вимагає декількох записів до одного спільного об'єкта, подумайте про об'єднання їх у один блок транзакцій, щоб уникнути кількох конфліктів. *Шаблони фрагментації: Для таких речей, як таблиці лідерів або DAO, розділіть стан за групою, раундом або ідентифікатором, щоб не всі транзакції потрапляли на точно той самий шлях об'єкта.
###Підводні камені, на які слід слідкути
*Монолітні спільні об'єкти: Розміщення всього в одному спільному об'єкті викликає високу суперечність та постійні конфлікти під навантаженням. *Надмірне використання спільних об'єктів: Якщо дані можна змоделювати як власні, віддайте перевагу цьому маршруту — він дешевший і рідше спричиняє вузьке місце. *Ігнорування шаблонів доступу: Якщо більшість взаємодій читаються з невеликою кількістю записів, проектуйте навколо незмінних знімків, а не одного змінного спільного стану.
###Практичний приклад
Уявіть, що створюєте відстежувач голосування DAO:
*Поганий шаблон: Єдиний спільний об'єкт, що зберігає кожен голос, оновлений усіма учасниками.
*Кращий шаблон: Кожен виборець створює власний Vote
об'єкт, що посилається на пропозицію, тоді як спільний об'єкт DAO лише періодично агрегує результати. Таким чином, паралельне голосування не стикається.
###Блок транзакції
Вхідні дані → Користувачі надсилають транзакції щодо спільних або власних об'єктів. Процес → Час виконання Sui серіалізує транзакції на тому ж змінюваному спільному об'єкті. Результат → Успішні записи виконуються, інші отримують конфліктні помилки; розщеплення об'єктів знижує ймовірність конфліктів.
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.
Ви знаєте відповідь?
Будь ласка, увійдіть та поділіться нею.
Sui is a Layer 1 protocol blockchain designed as the first internet-scale programmable blockchain platform.
Зароби свою частку з 1000 Sui
Заробляй бали репутації та отримуй винагороди за допомогу в розвитку спільноти Sui.

- Чому BCS вимагає точного порядку полів для десеріалізації, коли структури Move мають названі поля?65
- Помилки перевірки кількох джерел» у публікаціях модуля Sui Move - автоматичне вирішення помилок55
- Невдала операція Sui: об'єкти, зарезервовані для іншої транзакції49
- Як максимізувати прибуток від SUI: Sui Staking проти Liquid Staking313
- Помилка Sui Move - Неможливо обробити транзакцію Не знайдено дійсних газових монет для транзакції315