Deteksi dan Sinkronisasi Konflik - AWS AppSync

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

Deteksi dan Sinkronisasi Konflik

Sumber Data Berversioning

AWS AppSync saat ini mendukung versi pada sumber data DynamoDB. Operasi Deteksi Konflik, Resolusi Konflik, dan Sinkronisasi memerlukan sumberVersioned data. Ketika Anda mengaktifkan versi pada sumber data,AWS AppSync akan secara otomatis:

  • Tingkatkan item dengan metadata versi objek.

  • Rekam perubahan yang dilakukan pada item denganAWS AppSync mutasi ke tabel Delta.

  • Pertahankan item yang dihapus di tabel Dasar dengan “batu nisan” untuk jumlah waktu yang dapat dikonfigurasi.

Konfigurasi Sumber Data Berversi

Saat Anda mengaktifkan versioning di sumber data DynamoDB, Anda menentukan versioning berikut:

BaseTableTTL

Jumlah menit untuk mempertahankan item yang dihapus di tabel Dasar dengan “batu nisan” - bidang metadata yang menunjukkan bahwa item tersebut telah dihapus. Anda dapat mengatur nilai ini ke 0 jika Anda ingin item segera dihapus saat dihapus. Bidang ini wajib diisi.

DeltaSyncTableName

Nama tabel tempat perubahan yang dilakukan pada item denganAWS AppSync mutasi disimpan. Bidang ini wajib diisi.

DeltaSyncTableTTL

Jumlah menit untuk menyimpan item di meja Delta. Bidang ini wajib diisi.

Tabel Sinkronisasi Delta

AWS AppSync saat ini mendukung Delta Sync Logging untuk mutasi menggunakanPutItem,UpdateItem, dan operasiDeleteItem DynamoDB.

KetikaAWS AppSync mutasi mengubah item dalam sumber data berversi, catatan perubahan itu akan disimpan dalam tabel Delta yang dioptimalkan untuk pembaruan tambahan. Anda dapat memilih untuk menggunakan tabel Delta yang berbeda (misalnya satu per jenis, satu per area domain) untuk sumber data versi lain atau satu tabel Delta untuk API Anda. AWS AppSync merekomendasikan agar tidak menggunakan tabel Delta tunggal untuk beberapa API untuk menghindari tabrakan kunci primer.

Skema yang diperlukan untuk tabel ini adalah sebagai berikut:

ds_pk

Sebuah nilai string yang digunakan sebagai kunci partisi. Ini dibangun dengan menggabungkan nama sumber data Base dan format ISO 8601 dari tanggal perubahan terjadi (misalnyaComments:2019-01-01).

KetikacustomPartitionKey bendera dari template pemetaan VTL ditetapkan sebagai nama kolom kunci partisi (lihat Referensi Template Pemetaan Resolver untuk DynamoDB di PanduanAWS AppSync Pengembang), formatds_pk perubahan, dan string dibuat dengan menambahkan nilai kunci partisi dalam catatan baru di tabel Dasar. Misalnya, jika catatan dalam tabel Base memiliki nilai kunci partisi1a dan nilai kunci semacam2b, nilai baru dari string akan:Comments:2019-01-01:1a.

ds_sk

Sebuah nilai string yang digunakan sebagai kunci semacam. Ini dibangun dengan menggabungkan format ISO 8601 dari waktu perubahan terjadi, kunci utama item, dan versi item. Kombinasi bidang ini menjamin keunikan untuk setiap entri dalam tabel Delta (misalnya untuk waktu09:30:00 dan ID dari1a dan versi2, ini akan09:30:00:1a:2).

KetikacustomPartitionKey bendera dari template pemetaan VTL diatur ke nama kolom kunci partisi (lihat Referensi Template Pemetaan Resolver untuk DynamoDB di PanduanAWS AppSync Pengembang), formatds_sk perubahan, dan string dibuat dengan mengganti nilai tombol kombinasi dengan nilai kunci sortir di tabel dasar. Menggunakan contoh sebelumnya di atas, jika catatan dalam tabel Base memiliki nilai kunci partisi1a dan nilai kunci semacam2b, nilai baru dari string akan:09:30:00:2b:3.

_ttl

Nilai numerik yang menyimpan stempel waktu, dalam detik epoch, ketika item harus dihapus dari tabel Delta. Nilai ini ditentukan dengan menambahkanDeltaSyncTableTTL nilai yang dikonfigurasi pada sumber data ke momen ketika perubahan terjadi. Bidang ini harus dikonfigurasi sebagai Atribut TTL DynamoDB.

Peran IAM yang dikonfigurasi untuk digunakan dengan tabel Dasar juga harus berisi izin untuk beroperasi pada tabel Delta. Dalam contoh ini, kebijakan perizinan untuk tabel Base disebutComments dan tabel DeltaChangeLog disebut ditampilkan:

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "dynamodb:DeleteItem", "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:Query", "dynamodb:Scan", "dynamodb:UpdateItem" ], "Resource": [ "arn:aws:dynamodb:us-east-1:000000000000:table/Comments", "arn:aws:dynamodb:us-east-1:000000000000:table/Comments/*", "arn:aws:dynamodb:us-east-1:000000000000:table/ChangeLog", "arn:aws:dynamodb:us-east-1:000000000000:table/ChangeLog/*" ] } ] }

Metadata Sumber Data Berversi

AWS AppSync mengelola bidang metadata pada sumberVersioned data atas nama Anda. Memodifikasi bidang ini sendiri dapat menyebabkan kesalahan dalam aplikasi atau kehilangan data Anda. Bidang ini meliputi:

_version

Penghitung yang meningkat secara monoton yang diperbarui setiap saat perubahan terjadi pada item.

_lastChangedAt

Nilai numerik yang menyimpan stempel waktu, dalam milidetik epoch, saat item terakhir diubah.

_deleted

Sebuah Boolean “batu nisan” nilai yang menunjukkan bahwa item telah dihapus. Ini dapat digunakan oleh aplikasi untuk mengusir item yang dihapus dari toko data lokal.

_ttl

Nilai numerik yang menyimpan stempel waktu, dalam hitungan detik, ketika item harus dihapus dari sumber data yang mendasarinya.

ds_pk

Sebuah nilai string yang digunakan sebagai kunci partisi untuk tabel Delta.

ds_sk

Sebuah nilai string yang digunakan sebagai kunci semacam untuk tabel Delta.

gsi_ds_pk

Atribut nilai string yang dihasilkan untuk mendukung indeks sekunder global sebagai kunci partisi. Ini akan disertakan hanya jika keduapopulateIndexFields benderacustomPartitionKey dan diaktifkan dalam template pemetaan VTL (lihat Referensi Template Pemetaan Resolver untuk DynamoDB di PanduanAWS AppSync Pengembang). Jika diaktifkan, nilai akan dibangun dengan menggabungkan nama sumber data dasar dan format ISO 8601 dari tanggal di mana perubahan terjadi (misalnya jika tabel Dasar diberi nama Komentar, catatan ini akan ditetapkan sebagaiComments:2019-01-01).

gsi_ds_sk

Atribut nilai string yang dihasilkan untuk mendukung indeks sekunder global sebagai kunci semacam. Ini akan disertakan hanya jika keduapopulateIndexFields benderacustomPartitionKey dan diaktifkan dalam template pemetaan VTL (lihat Referensi Template Pemetaan Resolver untuk DynamoDB di PanduanAWS AppSync Pengembang). Jika diaktifkan, nilai akan dibangun dengan menggabungkan format ISO 8601 dari waktu di mana perubahan terjadi, kunci partisi item dalam tabel Dasar, kunci semacam item dalam tabel Dasar, dan versi item (misalnya untuk waktu09:30:00, nilai kunci partisi1a, nilai kunci semacam2b, dan versi3, ini akan09:30:00:1a#2b:3).

Bidang metadata ini akan memengaruhi ukuran keseluruhan item di sumber data yang mendasari. AWS AppSync merekomendasikan pemesanan 500 byte+Max Primary Key Size penyimpanan untuk metadata sumber data berversi saat merancang aplikasi Anda. Untuk menggunakan metadata ini dalam aplikasi klien, sertakan_version,_lastChangedAt, dan_deleted bidang pada jenis GraphQL Anda dan dalam pemilihan yang ditetapkan untuk mutasi.

Deteksi dan Resolusi Konflik

Ketika penulisan bersamaan terjadiAWS AppSync, Anda dapat mengonfigurasi strategi Deteksi Konflik dan Penyelesaian Konflik untuk menangani pembaruan dengan tepat. Deteksi Konflik menentukan apakah mutasi bertentangan dengan item tertulis yang sebenarnya di sumber data. Deteksi Konflik diaktifkan dengan menetapkan nilai SyncConfig diconflictDetection bidang untukVERSION.

Resolusi Konflik adalah tindakan yang diambil jika konflik terdeteksi. Hal ini ditentukan dengan menetapkan bidang Conflict Handler di SyncConfig. Ada tiga strategi Resolusi Konflik:

  • OPTIMISTIK_CONCURRENCY

  • AUTOMERGE

  • LAMBDA

Masing-masing strategi Resolusi Konflik ini dirinci secara mendalam di bawah ini.

Versi secara otomatis bertambah AppSync selama operasi tulis dan tidak boleh dimodifikasi oleh klien atau di luar resolver yang dikonfigurasi dengan sumber data yang diaktifkan versi. Melakukannya akan mengubah perilaku konsistensi sistem dan dapat mengakibatkan kehilangan data.

Konkurensi Optimis

Konkurensi Optimis adalah strategi resolusi konflik yangAWS AppSync menyediakan sumber data berversi. Ketika resolver konflik diatur ke Optimistic Concurrency, jika mutasi masuk terdeteksi memiliki versi yang berbeda dari versi sebenarnya dari objek, pengendali konflik hanya akan menolak permintaan yang masuk. Di dalam respons GraphQL, item yang ada di server yang memiliki versi terbaru akan disediakan. Klien kemudian diharapkan untuk menangani konflik ini secara lokal dan mencoba lagi mutasi dengan versi terbaru dari item.

Automerge

Automerge menyediakan pengembang cara mudah untuk mengkonfigurasi strategi resolusi konflik tanpa menulis logika sisi klien untuk menggabungkan konflik secara manual yang tidak dapat ditangani oleh strategi lain. Automerge mematuhi aturan ketat yang ditetapkan saat menggabungkan data untuk menyelesaikan konflik. Prinsip Automerge berputar di sekitar tipe data yang mendasari bidang GraphQL. Mereka adalah sebagai berikut:

  • Konflik pada bidang skalar: skalar GraphQL atau bidang apa pun yang bukan koleksi (yaitu List, Set, Map). Tolak nilai yang masuk untuk bidang skalar dan pilih nilai yang ada di server.

  • Konflik pada daftar: Jenis GraphQL dan tipe database adalah daftar. Menggabungkan daftar masuk dengan daftar yang ada di server. Nilai daftar dalam mutasi yang masuk akan ditambahkan ke akhir daftar di server. Nilai duplikat akan dipertahankan.

  • Konflik pada set: Jenis GraphQL adalah daftar dan jenis database adalah Set. Terapkan serikat set menggunakan masuk set dan set yang ada di server. Ini menganut properti Set, yang berarti tidak ada entri duplikat.

  • Ketika mutasi masuk menambahkan bidang baru untuk item atau dibuat terhadap bidang dengan nilainull, menggabungkan yang pada item yang ada.

  • Konflik pada peta: Ketika tipe data yang mendasari dalam database adalah Peta (yaitu dokumen kunci-nilai), terapkan aturan di atas saat mem-parsing dan memproses setiap properti Peta.

Automerge dirancang untuk secara otomatis mendeteksi, menggabungkan, dan mencoba kembali permintaan dengan versi terbaru, membebaskan klien dari kebutuhan untuk menggabungkan data yang saling bertentangan secara manual.

Untuk menunjukkan contoh bagaimana Automerge menangani Konflik pada tipe Skalar. Kami akan menggunakan catatan berikut sebagai titik awal kami.

{ "id" : 1, "name" : "Nadia", "jersey" : 5, "_version" : 4 }

Sekarang mutasi yang masuk mungkin mencoba memperbarui item tetapi dengan versi yang lebih lama karena klien belum disinkronkan dengan server. Terlihat seperti ini:

{ "id" : 1, "name" : "Nadia", "jersey" : 55, "_version" : 2 }

Perhatikan versi 2 yang sudah ketinggalan zaman dalam permintaan yang masuk. Selama alur ini, Automerge akan menggabungkan data dengan menolak pembaruan bidang 'jersey' ke '55' dan menjaga nilai pada '5' sehingga menghasilkan gambar berikut dari item yang disimpan di server.

{ "id" : 1, "name" : "Nadia", "jersey" : 5, "_version" : 5 # version is incremented every time automerge performs a merge that is stored on the server. }

Mengingat keadaan item yang ditunjukkan di atas pada versi 5, sekarang misalkan mutasi masuk yang mencoba untuk bermutasi item dengan gambar berikut:

{ "id" : 1, "name" : "Shaggy", "jersey" : 5, "interests" : ["breakfast", "lunch", "dinner"] # underlying data type is a Set "points": [24, 30, 27] # underlying data type is a List "_version" : 3 }

Ada tiga poin yang menarik dalam mutasi yang masuk. Nama, skalar, telah diubah tetapi dua bidang baru “kepentingan”, Set, dan “poin”, Daftar, telah ditambahkan. Dalam skenario ini, konflik akan terdeteksi karena ketidakcocokan versi. Automerge mematuhi sifat-sifatnya dan menolak perubahan nama karena itu menjadi skalar dan menambahkan pada bidang non-konflik. Ini menghasilkan item yang disimpan di server muncul sebagai berikut.

{ "id" : 1, "name" : "Nadia", "jersey" : 5, "interests" : ["breakfast", "lunch", "dinner"] # underlying data type is a Set "points": [24, 30, 27] # underlying data type is a List "_version" : 6 }

Dengan gambar item yang diperbarui dengan versi 6, sekarang misalkan mutasi yang masuk (dengan ketidakcocokan versi lain) mencoba mengubah item menjadi yang berikut:

{ "id" : 1, "name" : "Nadia", "jersey" : 5, "interests" : ["breakfast", "lunch", "brunch"] # underlying data type is a Set "points": [30, 35] # underlying data type is a List "_version" : 5 }

Di sini kita amati bahwa bidang masuk untuk “kepentingan” memiliki satu nilai duplikat yang ada di server dan dua nilai baru. Dalam hal ini, karena tipe data yang mendasarinya adalah Set, Automerge akan menggabungkan nilai-nilai yang ada di server dengan orang-orang dalam permintaan masuk dan strip keluar duplikat apapun. Demikian pula ada konflik pada bidang “poin” di mana ada satu nilai duplikat dan satu nilai baru. Tapi karena tipe data yang mendasari di sini adalah Daftar, Automerge hanya akan menambahkan semua nilai dalam permintaan yang masuk ke akhir nilai yang sudah ada di server. Gambar gabungan yang dihasilkan disimpan di server akan muncul sebagai berikut:

{ "id" : 1, "name" : "Nadia", "jersey" : 5, "interests" : ["breakfast", "lunch", "dinner", "brunch"] # underlying data type is a Set "points": [24, 30, 27, 30, 35] # underlying data type is a List "_version" : 7 }

Sekarang mari kita asumsikan item yang disimpan di server muncul sebagai berikut, pada versi 8.

{ "id" : 1, "name" : "Nadia", "jersey" : 5, "interests" : ["breakfast", "lunch", "dinner", "brunch"] # underlying data type is a Set "points": [24, 30, 27, 30, 35] # underlying data type is a List "stats": { "ppg": "35.4", "apg": "6.3" } "_version" : 8 }

Tetapi permintaan masuk mencoba memperbarui item dengan gambar berikut, sekali lagi dengan ketidakcocokan versi:

{ "id" : 1, "name" : "Nadia", "stats": { "ppg": "25.7", "rpg": "6.9" } "_version" : 3 }

Sekarang dalam skenario ini, kita dapat melihat bahwa bidang yang sudah ada di server hilang (minat, poin, jersey). Selain itu, nilai untuk “PPG” dalam peta “statistik” sedang diedit, nilai baru “rpg” sedang ditambahkan, dan “apg” dihilangkan. Automerge melestarikan bidang yang telah dihilangkan (catatan: jika bidang dimaksudkan untuk dihapus, maka permintaan harus dicoba lagi dengan versi yang cocok), dan sehingga mereka tidak akan hilang. Ini juga akan menerapkan aturan yang sama untuk bidang dalam peta dan oleh karena itu perubahan ke “PPG” akan ditolak sedangkan “apg” dipertahankan dan “rpg”, bidang baru”, ditambahkan pada. Item yang dihasilkan disimpan di server sekarang akan muncul sebagai:

{ "id" : 1, "name" : "Nadia", "jersey" : 5, "interests" : ["breakfast", "lunch", "dinner", "brunch"] # underlying data type is a Set "points": [24, 30, 27, 30, 35] # underlying data type is a List "stats": { "ppg": "35.4", "apg": "6.3", "rpg": "6.9" } "_version" : 9 }

Lambda

Opsi Penyelesaian Konflik:

  • RESOLVE: Ganti item yang ada dengan item baru yang disediakan dalam payload respons. Anda hanya dapat mencoba kembali operasi yang sama di satu item dalam satu waktu. Saat ini didukung untuk DynamoDBPutItem &UpdateItem.

  • REJECT: Tolak mutasi dan kembalikan kesalahan dengan item yang ada dalam respons GraphQL. Saat ini didukung untuk DynamoDBPutItem,UpdateItem, &DeleteItem.

  • REMOVE: Hapus item yang sudah ada. Saat ini didukung untuk DynamoDBDeleteItem.

Permintaan Doa Lambda

ResolverAWS AppSync DynamoDB memanggil fungsi Lambda yang ditentukan dalamLambdaConflictHandlerArn. Menggunakan samaservice-role-arn dikonfigurasi pada sumber data. Payload doa memiliki struktur berikut:

{ "newItem": { ... }, "existingItem": {... }, "arguments": { ... }, "resolver": { ... }, "identity": { ... } }

Bidang ditentukan sebagai berikut:

newItem

Item pratinjau, jika mutasi berhasil.

existingItem

Item yang saat ini berada di tabel DynamoDB.

arguments

Argumen dari mutasi GraphQL.

resolver

Informasi tentangAWS AppSync resolver.

identity

Informasi tentang penelepon. Bidang ini diatur ke null, jika akses dengan kunci API.

Contoh muatan:

{ "newItem": { "id": "1", "author": "Jeff", "title": "Foo Bar", "rating": 5, "comments": ["hello world"], }, "existingItem": { "id": "1", "author": "Foo", "rating": 5, "comments": ["old comment"] }, "arguments": { "id": "1", "author": "Jeff", "title": "Foo Bar", "comments": ["hello world"] }, "resolver": { "tableName": "post-table", "awsRegion": "us-west-2", "parentType": "Mutation", "field": "updatePost" }, "identity": { "accountId": "123456789012", "sourceIp": "x.x.x.x", "username": "AIDAAAAAAAAAAAAAAAAAA", "userArn": "arn:aws:iam::123456789012:user/appsync" } }

Respon Doa Lambda

UntukPutItem dan resolusiUpdateItem konflik

RESOLVEmutasi. Respons harus dalam format berikut.

{ "action": "RESOLVE", "item": { ... } }

itemBidang mewakili objek yang akan digunakan untuk mengganti item yang ada di sumber data yang mendasarinya. Kunci primer dan metadata sinkronisasi akan diabaikan jika disertakanitem.

REJECTmutasi. Respons harus dalam format berikut.

{ "action": "REJECT" }

Untuk resolusiDeleteItem konflik

REMOVEitem. Respons harus dalam format berikut.

{ "action": "REMOVE" }

REJECTmutasi. Respons harus dalam format berikut.

{ "action": "REJECT" }

Contoh fungsi Lambda di bawah memeriksa siapa yang membuat panggilan dan nama resolver. Jika dibuat olehjeffTheAdmin,REMOVE objek untuk DeletePost resolver atauRESOLVE konflik dengan item baru untuk resolver Update/Put. Jika tidak, mutasi adalahREJECT.

exports.handler = async (event, context, callback) => { console.log("Event: "+ JSON.stringify(event)); // Business logic goes here. var response; if ( event.identity.user == "jeffTheAdmin" ) { let resolver = event.resolver.field; switch(resolver) { case "deletePost": response = { "action" : "REMOVE" } break; case "updatePost": case "createPost": response = { "action" : "RESOLVE", "item": event.newItem } break; default: response = { "action" : "REJECT" }; } } else { response = { "action" : "REJECT" }; } console.log("Response: "+ JSON.stringify(response)); return response; }

Kesalahan

ConflictUnhandled

Deteksi konflik menemukan ketidakcocokan versi dan pengendali konflik menolak mutasi.

Contoh: Resolusi konflik dengan pengendali konflik Konkurensi Optimis. Atau, Lambda konflik handler kembali denganREJECT.

ConflictError

Terjadi kesalahan internal saat mencoba untuk menyelesaikan konflik.

Contoh: Penangan konflik Lambda mengembalikan respons yang salah. Atau, tidak dapat memanggil Lambda konflik handler karena sumber daya yangLambdaConflictHandlerArn disediakan tidak ditemukan.

MaxConflicts

Upaya coba ulang maks dicapai untuk penyelesaian konflik.

Contoh: Terlalu banyak permintaan bersamaan pada objek yang sama. Sebelum konflik diselesaikan, objek diperbarui ke versi baru oleh klien lain.

BadRequest

Klien mencoba memperbarui bidang metadata (_version,_ttl,_lastChangedAt,_deleted).

Contoh: Klien mencoba memperbarui _version objek dengan mutasi pembaruan.

DeltaSyncWriteError

Gagal menulis rekaman sinkronisasi delta.

Contoh: Mutasi berhasil, tetapi terjadi kesalahan internal saat mencoba menulis ke tabel sinkronisasi delta.

InternalFailure

Terjadi eror internal.

CloudWatch Log

JikaAWS AppSync API telah mengaktifkan CloudWatch Log dengan pengaturan logging disetel ke Log Tingkat Lapanganenabled dan tingkat log untuk Log Tingkat Lapangan yang disetelALL, makaAWS AppSync akan memancarkan informasi Deteksi Konflik dan Resolusi ke grup log. Untuk informasi tentang format pesan log, lihat dokumentasi untuk Deteksi Konflik dan Pencatatan Sinkronisasi.

Sinkronisasi Operasi

Sumber data berversi mendukungSync operasi yang memungkinkan Anda mengambil semua hasil dari tabel DynamoDB dan kemudian hanya menerima data yang diubah sejak kueri terakhir Anda (pembaruan delta). KetikaAWS AppSync menerima permintaan untukSync operasi, ia menggunakan bidang yang ditentukan dalam permintaan untuk menentukan apakah tabel Dasar atau tabel Delta harus diakses.

  • JikalastSync bidang tidak ditentukan,Scan pada tabel Base dilakukan.

  • JikalastSync bidang ditentukan, tetapi nilai sebelumcurrent moment - DeltaSyncTTL,Scan pada tabel Base dilakukan.

  • JikalastSync bidang ditentukan, dan nilai pada atau setelahcurrent moment - DeltaSyncTTL,Query pada tabel Delta dilakukan.

AWS AppSync mengembalikanstartedAt bidang ke template pemetaan respon untuk semuaSync operasi. startedAtBidang adalah momen, dalam milidetik epoch, ketikaSync operasi dimulai yang dapat Anda simpan secara lokal dan gunakan dalam permintaan lain. Jika token pagination disertakan dalam permintaan, nilai ini akan sama dengan yang dikembalikan oleh permintaan untuk halaman pertama hasil.

Untuk informasi tentang format templateSync pemetaan, lihat referensi template pemetaan.