Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Při zápisech do více oblastí může dojít ke konfliktům při zápisu více klientů do stejné položky. Pokud dojde ke konfliktu, můžete konflikt vyřešit pomocí různých zásad řešení konfliktů. Tento článek popisuje, jak spravovat zásady řešení konfliktů.
Tip
Zásady řešení konfliktů je možné zadat pouze při vytváření kontejneru a po vytvoření kontejneru je nejde upravit.
Vytvořte zásadu řešení konfliktů posledního zapisovače
Tyto ukázky ukazují, jak nastavit kontejner se zásadou posledního zapisovače pro řešení konfliktů. Výchozí cesta pro last-writer-wins je pole časového razítka nebo vlastnost _ts. Pro rozhraní API pro NoSQL může být tato cesta také nastavená na uživatelsky definovanou cestu s číselným typem. V konfliktu vyhraje nejvyšší hodnota. Pokud cesta není nastavená nebo je neplatná, výchozí hodnota je _ts. Konflikty vyřešené touto zásadou se v informačním kanálu konfliktů nezobrazují. Tato zásada může používat všechna rozhraní API.
.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();
sady SDK Java V2
Asynchronní 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)
Go SDK (vývojová sada pro Go)
db, _ := c.NewDatabase("demo_db")
_, err = db.CreateContainer(context.Background(), azcosmos.ContainerProperties{
ID: "demo_container",
PartitionKeyDefinition: azcosmos.PartitionKeyDefinition{
Paths: []string{"/id"},
Kind: azcosmos.PartitionKeyKindHash,
},
ConflictResolutionPolicy: &azcosmos.ConflictResolutionPolicy{
Mode: azcosmos.ConflictResolutionModeLastWriteWins,
ResolutionPath: "/myCustomId",
},
}, nil)
Vytvoření vlastní zásady řešení konfliktů pomocí uložené procedury
Tyto ukázky ukazují, jak nastavit kontejner s vlastní zásadou řešení konfliktů. Tato zásada používá logiku uložené procedury k vyřešení konfliktu. Pokud je uložená procedura určená k řešení konfliktů, konflikty se v informačním kanálu konfliktů nezobrazí, pokud v určené uložené proceduře nedojde k chybě.
Po vytvoření zásady s kontejnerem je potřeba vytvořit uloženou proceduru. Ukázka sady .NET SDK ukazuje příklad tohoto pracovního postupu. Tato zásada se podporuje jenom v rozhraní API pro NoSQL.
Ukázková vlastní uložená procedura pro řešení konfliktů
Uložené procedury vlastního řešení konfliktů musí být implementovány pomocí podpisu funkce uvedeného níže. Název funkce se nemusí shodovat s názvem použitým při registraci uložené procedury v kontejneru, ale zjednodušuje pojmenování. Tady je popis parametrů, které musí být pro tuto uloženou proceduru implementovány.
- incomingItem: Položka vložená nebo aktualizovaná v potvrzení, které generuje konflikty. Má hodnotu null pro operace odstranění.
- existingItem: Aktuálně potvrzená položka. Tato hodnota není null při aktualizaci a je null pro vložení nebo smazání.
- isTombstone: Logická hodnota označující, jestli příchozí položka koliduje s dříve odstraněnou položkou. Pokud je hodnota true, existingItem má také hodnotu null.
- conflictingItems: Pole závazné verze všech položek v kontejneru, které jsou v konfliktu s incomingItem podle ID nebo jakýchkoli jiných jedinečných vlastností indexu.
Important
Stejně jako jakákoli uložená procedura má vlastní postup řešení konfliktů přístup k jakýmkoli datům se stejným klíčem oddílu a může provádět jakoukoli operaci vložení, aktualizace nebo odstranění, aby se vyřešily konflikty.
Tato ukázková uložená procedura řeší konflikty výběrem nejnižší hodnoty z cesty /myCustomId.
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();
sady SDK Java V2
Asynchronní sada SDK pro Java V2 (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();
Po vytvoření kontejneru je nutné vytvořit uloženou proceduru resolver.
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`
}
}
);
Po vytvoření kontejneru je nutné vytvořit uloženou proceduru resolver.
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)
Po vytvoření kontejneru je nutné vytvořit uloženou proceduru resolver.
Vytvoření vlastní zásady řešení konfliktů
Tyto ukázky ukazují, jak nastavit kontejner s vlastní zásadou řešení konfliktů. Při této implementaci se každý konflikt zobrazí v informačním kanálu konfliktů. Je na vás, abyste konflikty řešili jednotlivě z kanálu konfliktů.
.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();
sady SDK Java V2
Asynchronní 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)
Čtení z kanálu konfliktů
Tyto ukázky ukazují, jak číst z kanálu konfliktů kontejneru. Konflikty se můžou v informačním kanálu konfliktů zobrazovat jenom z několika důvodů.
- Konflikt se automaticky nevyřešil.
- Konflikt způsobil chybu se specifikovanou uloženou procedurou.
- Zásada řešení konfliktů je nastavená na vlastní a neoznačí uloženou proceduru pro zpracování konfliktů.
.NET SDK
FeedResponse<Conflict> conflicts = await delClient.ReadConflictFeedAsync(this.collectionUri);
sady SDK Java
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)
Další kroky
Seznamte se s následujícími koncepty služby Azure Cosmos DB:
- Globální distribuce – pod kapotou
- Konfigurace zápisů do více oblastí v aplikacích
- Konfigurace klientů pro multihoming
- Přidání nebo odebrání oblastí z účtu služby Azure Cosmos DB
- Jak nakonfigurovat víceregionální zápisy ve vašich aplikacích
- Dělení a distribuce dat
- Indexování ve službě Azure Cosmos DB