Ütközésfeloldási szabályzatok kezelése az Azure Cosmos DB-ben
A KÖVETKEZŐRE VONATKOZIK: NoSQL
Többrégiós írás esetén, ha több ügyfél is ugyanarra az elemre ír, ütközések léphetnek fel. Ütközés esetén az ütközést különböző ütközésfeloldási szabályzatok használatával oldhatja fel. Ez a cikk az ütközésfeloldási szabályzatok kezelését ismerteti.
Tipp.
Az ütközésfeloldási szabályzat csak a tároló létrehozásakor adható meg, és a tároló létrehozása után nem módosítható.
Last-writer-wins ütközésfeloldási szabályzat létrehozása
Ezek a minták bemutatják, hogyan állíthat be egy tárolót egy utolsó író-wins ütközésfeloldási szabályzattal. A last-writer-wins alapértelmezett elérési útja az időbélyegmező vagy a _ts
tulajdonság. A NoSQL-hez készült API esetében ez egy felhasználó által megadott, numerikus típusú elérési útra is beállítható. Ütközés esetén a legmagasabb érték nyer. Ha az elérési út nincs beállítva, vagy érvénytelen, az alapértelmezés szerint a következő lesz _ts
. Az ezzel a szabályzattal feloldott ütközések nem jelennek meg az ütközéscsatornában. Ezt a szabályzatot az összes API használhatja.
.NET SDK
DocumentCollection lwwCollection = await createClient.CreateDocumentCollectionIfNotExistsAsync(
UriFactory.CreateDatabaseUri(this.databaseName), new DocumentCollection
{
Id = this.lwwCollectionName,
ConflictResolutionPolicy = new ConflictResolutionPolicy
{
Mode = ConflictResolutionMode.LastWriterWins,
ConflictResolutionPath = "/myCustomId",
},
});
Java V4 SDK
Java SDK V4 (Maven com.azure::azure-cosmos) Async API
ConflictResolutionPolicy policy = ConflictResolutionPolicy.createLastWriterWinsPolicy("/myCustomId");
CosmosContainerProperties containerProperties = new CosmosContainerProperties(container_id, partition_key);
containerProperties.setConflictResolutionPolicy(policy);
/* ...other container config... */
database.createContainerIfNotExists(containerProperties).block();
Java V2 SDK-k
Async Java V2 SDK (Maven com.microsoft.azure::azure-cosmosdb)
DocumentCollection collection = new DocumentCollection();
collection.setId(id);
ConflictResolutionPolicy policy = ConflictResolutionPolicy.createLastWriterWinsPolicy("/myCustomId");
collection.setConflictResolutionPolicy(policy);
DocumentCollection createdCollection = client.createCollection(databaseUri, collection, null).toBlocking().value();
Node.js/JavaScript/TypeScript SDK
const database = client.database(this.databaseName);
const { container: lwwContainer } = await database.containers.createIfNotExists(
{
id: this.lwwContainerName,
conflictResolutionPolicy: {
mode: "LastWriterWins",
conflictResolutionPath: "/myCustomId"
}
}
);
Python SDK
database = client.get_database_client(database=database_id)
lww_conflict_resolution_policy = {'mode': 'LastWriterWins', 'conflictResolutionPath': '/regionId'}
lww_container = database.create_container(id=lww_container_id, partition_key=PartitionKey(path="/id"),
conflict_resolution_policy=lww_conflict_resolution_policy)
Egyéni ütközésfeloldási szabályzat létrehozása tárolt eljárással
Ezek a minták bemutatják, hogyan állíthat be egyéni ütközésfeloldási szabályzatot egy tárolóhoz. Ez a szabályzat egy tárolt eljárás logikáját használja az ütközés feloldásához. Ha egy tárolt eljárás van kijelölve az ütközések feloldására, az ütközések csak akkor jelennek meg az ütközési hírcsatornában, ha hiba van a kijelölt tárolt eljárásban.
Miután létrehozta a házirendet a tárolóval, létre kell hoznia a tárolt eljárást. Az alábbi .NET SDK-minta erre a munkafolyamatra mutat példát. Ez a szabályzat csak a NoSQL API-ban támogatott.
Egyéni ütközésfeloldási tárolt eljárásminta
Az egyéni ütközésfeloldási tárolt eljárásokat az alább látható függvény-aláírással kell implementálni. A függvény nevének nem kell egyeznie a tárolóval a tárolt eljárás regisztrálásakor használt névvel, de leegyszerűsíti az elnevezést. Íme a tárolt eljáráshoz implementálandó paraméterek leírása.
- incomingItem: Az ütközéseket létrehozó véglegesítésbe beszúrt vagy frissített elem. A törlési műveletek null értékűek.
- existingItem: Az aktuálisan véglegesített elem. Ez az érték nem null értékű egy frissítésben, és null értékű a beszúrások vagy törlések esetében.
- isTombstone: Logikai érték, amely azt jelzi, hogy a bejövő elem ütközik-e egy korábban törölt elemet. Ha igaz, a existingItem is null értékű.
- conflictingItems: A tárolóban lévő összes elem véglegesített verziójának tömbje, amely ütközik az id-beli incomingItem azonosítójával vagy bármely más egyedi indextulajdonságtal.
Fontos
A tárolt eljárásokhoz hasonlóan az egyéni ütközésfeloldási eljárások is hozzáférhetnek az azonos partíciókulcsú adatokhoz, és bármilyen beszúrási, frissítési vagy törlési műveletet végrehajthatnak az ütközések feloldásához.
Ez a minta tárolt eljárás úgy oldja fel az ütközéseket, hogy kiválasztja a legalacsonyabb értéket az /myCustomId
elérési útból.
function resolver(incomingItem, existingItem, isTombstone, conflictingItems) {
var collection = getContext().getCollection();
if (!incomingItem) {
if (existingItem) {
collection.deleteDocument(existingItem._self, {}, function (err, responseOptions) {
if (err) throw err;
});
}
} else if (isTombstone) {
// delete always wins.
} else {
if (existingItem) {
if (incomingItem.myCustomId > existingItem.myCustomId) {
return; // existing item wins
}
}
var i;
for (i = 0; i < conflictingItems.length; i++) {
if (incomingItem.myCustomId > conflictingItems[i].myCustomId) {
return; // existing conflict item wins
}
}
// incoming item wins - clear conflicts and replace existing with incoming.
tryDelete(conflictingItems, incomingItem, existingItem);
}
function tryDelete(documents, incoming, existing) {
if (documents.length > 0) {
collection.deleteDocument(documents[0]._self, {}, function (err, responseOptions) {
if (err) throw err;
documents.shift();
tryDelete(documents, incoming, existing);
});
} else if (existing) {
collection.replaceDocument(existing._self, incoming,
function (err, documentCreated) {
if (err) throw err;
});
} else {
collection.createDocument(collection.getSelfLink(), incoming,
function (err, documentCreated) {
if (err) throw err;
});
}
}
}
.NET SDK
DocumentCollection udpCollection = await createClient.CreateDocumentCollectionIfNotExistsAsync(
UriFactory.CreateDatabaseUri(this.databaseName), new DocumentCollection
{
Id = this.udpCollectionName,
ConflictResolutionPolicy = new ConflictResolutionPolicy
{
Mode = ConflictResolutionMode.Custom,
ConflictResolutionProcedure = string.Format("dbs/{0}/colls/{1}/sprocs/{2}", this.databaseName, this.udpCollectionName, "resolver"),
},
});
//Create the stored procedure
await clients[0].CreateStoredProcedureAsync(
UriFactory.CreateStoredProcedureUri(this.databaseName, this.udpCollectionName, "resolver"), new StoredProcedure
{
Id = "resolver",
Body = File.ReadAllText(@"resolver.js")
});
Java V4 SDK
Java SDK V4 (Maven com.azure::azure-cosmos) Async API
ConflictResolutionPolicy policy = ConflictResolutionPolicy.createCustomPolicy("resolver");
CosmosContainerProperties containerProperties = new CosmosContainerProperties(container_id, partition_key);
containerProperties.setConflictResolutionPolicy(policy);
/* ...other container config... */
database.createContainerIfNotExists(containerProperties).block();
Java V2 SDK-k
Async Java V2 SDK (Maven com.microsoft.azure::azure-cosmosdb)
DocumentCollection collection = new DocumentCollection();
collection.setId(id);
ConflictResolutionPolicy policy = ConflictResolutionPolicy.createCustomPolicy("resolver");
collection.setConflictResolutionPolicy(policy);
DocumentCollection createdCollection = client.createCollection(databaseUri, collection, null).toBlocking().value();
A tároló létrehozása után létre kell hoznia a resolver
tárolt eljárást.
Node.js/JavaScript/TypeScript SDK
const database = client.database(this.databaseName);
const { container: udpContainer } = await database.containers.createIfNotExists(
{
id: this.udpContainerName,
conflictResolutionPolicy: {
mode: "Custom",
conflictResolutionProcedure: `dbs/${this.databaseName}/colls/${
this.udpContainerName
}/sprocs/resolver`
}
}
);
A tároló létrehozása után létre kell hoznia a resolver
tárolt eljárást.
Python SDK
database = client.get_database_client(database=database_id)
udp_custom_resolution_policy = {'mode': 'Custom' }
udp_container = database.create_container(id=udp_container_id, partition_key=PartitionKey(path="/id"),
conflict_resolution_policy=udp_custom_resolution_policy)
A tároló létrehozása után létre kell hoznia a resolver
tárolt eljárást.
Egyéni ütközésfeloldási szabályzat létrehozása
Ezek a minták bemutatják, hogyan állíthat be egyéni ütközésfeloldási szabályzatot egy tárolóhoz. Ezzel a megvalósítással minden ütközés megjelenik az ütközési hírcsatornában. Önön múlik, hogy az ütközéseket egyenként kezelje az ütközéscsatornából.
.NET SDK
DocumentCollection manualCollection = await createClient.CreateDocumentCollectionIfNotExistsAsync(
UriFactory.CreateDatabaseUri(this.databaseName), new DocumentCollection
{
Id = this.manualCollectionName,
ConflictResolutionPolicy = new ConflictResolutionPolicy
{
Mode = ConflictResolutionMode.Custom,
},
});
Java V4 SDK
Java SDK V4 (Maven com.azure::azure-cosmos) Async API
ConflictResolutionPolicy policy = ConflictResolutionPolicy.createCustomPolicy();
CosmosContainerProperties containerProperties = new CosmosContainerProperties(container_id, partition_key);
containerProperties.setConflictResolutionPolicy(policy);
/* ...other container config... */
database.createContainerIfNotExists(containerProperties).block();
Java V2 SDK-k
Async Java V2 SDK (Maven com.microsoft.azure::azure-cosmosdb)
DocumentCollection collection = new DocumentCollection();
collection.setId(id);
ConflictResolutionPolicy policy = ConflictResolutionPolicy.createCustomPolicy();
collection.setConflictResolutionPolicy(policy);
DocumentCollection createdCollection = client.createCollection(databaseUri, collection, null).toBlocking().value();
Node.js/JavaScript/TypeScript SDK
const database = client.database(this.databaseName);
const {
container: manualContainer
} = await database.containers.createIfNotExists({
id: this.manualContainerName,
conflictResolutionPolicy: {
mode: "Custom"
}
});
Python SDK
database = client.get_database_client(database=database_id)
manual_resolution_policy = {'mode': 'Custom'}
manual_container = database.create_container(id=manual_container_id, partition_key=PartitionKey(path="/id"),
conflict_resolution_policy=manual_resolution_policy)
Olvasás az ütközéscsatornából
Ezek a minták bemutatják, hogyan lehet olvasni egy tároló ütközéscsatornájából. Az ütközések csak néhány okból jelenhetnek meg az ütközési hírcsatornában:
- Az ütközés nem lett automatikusan feloldva
- Az ütközés hibát okozott a kijelölt tárolt eljárással kapcsolatban
- Az ütközésfeloldási szabályzat egyénire van állítva, és nem jelöl ki tárolt eljárást az ütközések kezelésére
.NET SDK
FeedResponse<Conflict> conflicts = await delClient.ReadConflictFeedAsync(this.collectionUri);
Java SDK-k
Java V4 SDK (Maven com.azure::azure-cosmos)
int requestPageSize = 3;
CosmosQueryRequestOptions options = new CosmosQueryRequestOptions();
CosmosPagedFlux<CosmosConflictProperties> conflictReadFeedFlux = container.readAllConflicts(options);
conflictReadFeedFlux.byPage(requestPageSize).toIterable().forEach(page -> {
int expectedNumberOfConflicts = 0;
int numberOfResults = 0;
Iterator<CosmosConflictProperties> pageIt = page.getElements().iterator();
while (pageIt.hasNext()) {
CosmosConflictProperties conflictProperties = pageIt.next();
// Read the conflict and committed item
CosmosAsyncConflict conflict = container.getConflict(conflictProperties.getId());
CosmosConflictResponse response = conflict.read(new CosmosConflictRequestOptions()).block();
// response.
}
});
Node.js/JavaScript/TypeScript SDK
const container = client
.database(this.databaseName)
.container(this.lwwContainerName);
const { result: conflicts } = await container.conflicts.readAll().toArray();
Python
conflicts_iterator = iter(container.list_conflicts())
conflict = next(conflicts_iterator, None)
while conflict:
# Do something with conflict
conflict = next(conflicts_iterator, None)
Következő lépések
Ismerje meg a következő Azure Cosmos DB-fogalmakat:
- Globális disztribúció – a motorháztető alatt
- Többrégiós írások konfigurálása az alkalmazásokban
- Ügyfelek konfigurálása többtényezős használatra
- Régiók hozzáadása vagy eltávolítása az Azure Cosmos DB-fiókból
- Hogyan konfigurálhatja a régió írásait az alkalmazásokban.
- Particionálás és adatelosztás
- Indexelés az Azure Cosmos DB-ben