ملاحظة
يتطلب الوصول إلى هذه الصفحة تخويلاً. يمكنك محاولة تسجيل الدخول أو تغيير الدلائل.
يتطلب الوصول إلى هذه الصفحة تخويلاً. يمكنك محاولة تغيير الدلائل.
ينطبق على: NoSQL
مع عمليات الكتابة متعددة المناطق، عندما يكتب العديد من العملاء إلى نفس العنصر، قد تحدث تعارضات. عند حدوث تعارض، يمكنك حل التعارض باستخدام نُهج مختلفة لحل التعارض. توضح هذه المقالة كيفية إدارة نُهج حل التعارض.
تلميح
يمكن تحديد نهج حل التعارض فقط في وقت إنشاء الحاوية ولا يمكن تعديله بعد إنشاء الحاوية.
إنشاء نهج حل تعارض لـ last-writer-wins
توضح هذه العينات كيفية إعداد حاوية باستخدام نهج حل التعارض لـ last-writer-wins. المسار الافتراضي لـ last-writer-wins هو حقل الطابع الزمني أو الخاصية _ts
. بالنسبة لواجهة برمجة التطبيقات ل NoSQL، قد يتم تعيين هذا المسار أيضا إلى مسار معرف من قبل المستخدم بنوع رقمي. في الصراع، تفوز أعلى قيمة. إذا لم يتم تعيين المسار أو كان غير صالح، فسيتم تعيينه افتراضيًا على _ts
. لا تظهر التعارضات التي تم حلها باستخدام هذا النهج في موجز التعارض. يمكن لجميع واجهات برمجة التطبيقات استخدام هذا النهج.
.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 SDKs
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)
Go SDK
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)
إنشاء نهج حل تعارض مخصص باستخدام إجراء مخزن
توضح هذه العينات كيفية إعداد حاوية بنهج مخصص لحل التعارضات. يستخدم هذا النهج المنطق في إجراء مخزن لحل التعارض. إذا تم تعيين إجراء مخزن لحل التعارضات، فلن تظهر التعارضات في موجز التعارض ما لم يكن هناك خطأ في الإجراء المخزن المعين.
بعد إنشاء النهج مع الحاوية، تحتاج إلى إنشاء الإجراء المخزن. يظهر نموذج .NET SDK مثالا على سير العمل هذا. يتم دعم هذا النهج في واجهة برمجة التطبيقات ل NoSQL فقط.
عينة الإجراء المخصص لحل التعارض المخزن
يجب تنفيذ الإجراءات المخزنة لحل التعارض المخصص باستخدام توقيع الوظيفة الموضح أدناه. لا يحتاج اسم الدالة إلى مطابقة الاسم المستخدم عند تسجيل الإجراء المخزن مع الحاوية ولكنه يبسط التسمية. فيما يلي وصف للمعلمات التي يجب تنفيذها لهذا الإجراء المخزن.
- incomingItem: العنصر الذي يتم إدراجه أو تحديثه في الالتزام الذي ينتج عنه التعارضات. لاغية لعمليات الحذف.
- CurrentItem: العنصر المعين حاليًا. هذه القيمة غير خالية في التحديث وخالية للإدراج أو الحذف.
- isTombstone: قيمة منطقية تشير إلى ما إذا كان العنصر الوارد يتعارض مع عنصر تم حذفه مسبقًا. عندما يكون هذا صحيحًا، يكون عنصر موجود أيضًا فارغًا.
- troubleItems: صفيف من الإصدار المخصص لكافة العناصر الموجودة في الحاوية التي تتعارض مع عنصر InomingItem في المعرف أو أي خصائص فهرس فريدة أخرى.
هام
مثل أي إجراء مخزن، يمكن لإجراء حل التعارض المخصص الوصول إلى أي بيانات بنفس مفتاح القسم ويمكنه تنفيذ أي عملية إدراج أو تحديث أو حذف لحل التعارضات.
يعمل نموذج الإجراء المخزن هذا على حل التعارضات عن طريق تحديد أدنى قيمة من المسار /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();
Java V2 SDKs
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();
بعد إنشاء الحاوية الخاصة بك، يجب عليك إنشاء الإجراء 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`
}
}
);
بعد إنشاء الحاوية الخاصة بك، يجب عليك إنشاء الإجراء 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)
بعد إنشاء الحاوية الخاصة بك، يجب عليك إنشاء الإجراء resolver
المخزن.
إنشاء نهج مخصص لحل التعارض
توضح هذه العينات كيفية إعداد حاوية بنهج مخصص لحل التعارضات. مع هذا التنفيذ، يظهر كل تعارض في موجز التعارض. الأمر متروك لك للتعامل مع التعارضات بشكل فردي من موجز التعارض.
.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 SDKs
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)
اقرأ من موجز الصراع
توضح هذه العينات كيفية القراءة من موجز تعارض الحاوية. قد تظهر التعارضات في موجز التعارض لسببين فقط:
- لم يتم حل التعارض تلقائيا
- تسبب التعارض في حدوث خطأ في الإجراء المخزن المعين
- تم تعيين نهج حل التعارض إلى مخصص ولا يعين إجراء مخزنا لمعالجة التعارضات
.NET SDK
FeedResponse<Conflict> conflicts = await delClient.ReadConflictFeedAsync(this.collectionUri);
Java SDKs
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)
الخطوات التالية
تعرف على مفاهيم Azure Cosmos DB التالية: