CloudKit是强一致性还是最终一致性?

7

官方文档是否有提到CloudKit的一致性?根据我的测试,它似乎是最终一致的-在写入记录后立即读取可能会成功,也可能不会(返回空结果):

CKDatabase *database = [[CKContainer defaultContainer] publicCloudDatabase];
CKRecord *record = [[CKRecord alloc] initWithRecordType:@"Foo"];

dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[database saveRecord:record completionHandler:^(CKRecord *record, NSError *error) {
    CKQuery *query = [[CKQuery alloc] initWithRecordType:@"Foo" predicate:[NSPredicate predicateWithFormat:@"TRUEPREDICATE"]];
    [database performQuery:query inZoneWithID:nil completionHandler:^(NSArray *results, NSError *error) {
        XCTAssertEqualObjects(results, @[], @"Freshly written object not returned by query."); // succeeds
        dispatch_semaphore_signal(semaphore);
    }];
}];

dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

有没有一种方法可以强制进行强一致性读取,以反映所有先前的更新?

我在我的测试中也注意到了同样的问题。我保存了一条记录并等待成功完成。如果我执行一个查询所有记录的操作,我的新记录没有被返回。你有找到任何关于CloudKit是最终一致性的信息吗? - Tim Dean
我的使用情况非常简单,所以我在数据存储层中使用了一种缓存方式“解决”了这个问题:当一个项目被插入到数据存储中时,它会被写入iCloud并在客户端上短暂存储。当数据存储层被查询时,它会将活动的缓存记录添加到结果集中。虽然有些愚蠢,但是它确实起作用。 - zoul
1
@zoul 有没有找到更好的处理方法?CKModifyRecordsOperation.h 中 modifyRecordsCompletionBlock 的内联注释的最后一部分表明这是设计行为:“此调用会在服务器查看所有记录更改后立即发生,并且可能在服务器处理这些更改的副作用时被调用。 - George
服务器更新可能需要时间,并不能保证查询表单中反映的是当前记录。但如果您使用recordID进行检索,它将是一致的。我认为延迟是处理这个问题的一种不好的方式。在我构建的应用程序中,需要跟踪实时记录(至少从用户的角度),我一直在保存更改的RecordIDs和moddate,并根据查询记录检查修改日期。如果记录不是最新的,我会从结果中删除它们,并通过CKRecordID检索这些特定记录并将它们拼接到结果中。 - agibson007
2个回答

9

这句话有点复杂,大致意思是:CloudKit在通过identifier获取记录时具有强一致性,但在使用查询时则存在最终一致性。

CKModifyRecordsOperation操作成功返回时,可以立即通过identifier获取该记录。

然而,服务器需要一些时间扫描记录的值并更新和分发其搜索索引。在索引完成之前,您将无法在任何查询中看到该记录。


0

我对“最终一致性”这个术语的唯一经验来自使用CouchDB,它是最终一致性的。CloudKit与CouchDB非常不同,因为CouchDB允许复制分布式数据库,而CloudKit仅提供“管理向iCloud服务器传输数据的服务” - 它只是一个传输机制。

我很确定传输机制本身不是最终一致性的 - 它直接从CloudKit服务器保存和检索。

由于CloudKit仅是一个传输机制,您需要负责维护自己的本地缓存/数据库。您的本地数据库被认为是最终一致的,因为在同步之间它不一定是一致的,只有当您最终使用CloudKit同步后才变得一致。

现在,你说在你的测试中你正在保存并尝试检索一条记录。但我注意到你的代码中没有检查保存操作中的错误。因此,也许有一个保存时出现的错误你没有注意到?


我不了解苹果的iCloud基础设施,但我怀疑有许多不同的iCloud服务器在某种负载均衡方案的背后运行。因此,保存记录的调用可能被路由到一个服务器实例,而随后的调用则被路由到另一个实例。根据iCloud保持这些实例同步的程度,期望在这里有一个最终一致性模型可能是相当合理的。 - Tim Dean

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接