使用IReliableDictionary2时,何时将数据持久保存到磁盘?

时间:2018-10-02 20:11:54

标签: c# azure-service-fabric

我们有一个实现IReliableDictionary2的c#可靠集合字典,并注意到由于序列化错误而有些奇怪。

我们有包含另一个类Y的类X。我们忘记了将序列化添加到类Y。但是在将类X添加到可靠的集合字典后的几天里,当我们检索以下实例时,类Y也在那里X

显然,可靠的集合字典只是在内存中,但是在某个时候集合仍保存在磁盘上,这时Class Y返回null,因为它没有添加到[DataMember]的序列化中。

所以问题是可靠的集合何时会持久化到磁盘上?是否对此有程序控制?还是这是某种集群设置?

3 个答案:

答案 0 :(得分:1)

使用ReliableCollections时,每个操作(即AddAsync)都会执行以下操作:

  1. 更新ITransaction本地存储(以提供read-your-own-writes semantics
  2. 序列化值并更新本地操作日志(持久性)。
  3. 将这些字节发送到所有辅助副本,以确保它们具有相同的信息。

然后,在提交ITransaction时,commit条目将附加到日志并发送到所有辅助副本。在quorum确认提交时,该操作被视为已完成(有关更多信息,请参见here)。

因此,通常情况下,信息始终是序列化的。

之所以看到“正确”的结果,是因为大多数时候您使用同一副本-主副本(这样做是因为只有主副本才能修改状态),并且所有读取/来自同一副本的写入均返回正确值。

这里的窍门是Service Fabric可以在节点之间移动副本,例如,假设您的主副本位于Node1上。您所有的读取和写入都很好,但是Service Fabric决定将您的主副本移至Node2-这导致Node2上的新空闲副本通过将序列化数据传输到其中而获得initialized 。初始化副本后,Node1上的副本将降级,Node2上的副本将被升级。现在,您所有的请求都是来自Node2的服务器,而不是来自Node1的服务器(有关服务和副本生命周期的更多信息,请参见herehere)。

答案 1 :(得分:0)

问题应该是相反的:当服务结构从磁盘读取集合时?

当事务提交时,它将持久化数据(到磁盘和在内存缓存中)。从磁盘读取数据可能有多种原因(例如主节点已更改/重新启动。)

答案 2 :(得分:0)

主要问题:When is data persisted to disk when using IReliableDictionary2?在堆栈溢出和文档中已经有很多答案。

How is data in Reliable Dictionary in Azure Service Fabric persisted to disk

此答案详细说明了如何更改和复制数据:Downsides of CommitAsync() w/o any changes to collection

这个回答了它如何存储在内存中:Azure Service Fabric reliable collections and memory

在您的情况下发生问题的原因很明显:

  1. 您没有正确序列化数据,将数据复制到其他副本时会丢失信息
  2. 正如在其他许多问题和帖子中所解释的那样,数据保存在内存中,因此将这些数据写入磁盘并读取到内存没有任何意义,原始副本将保留完整的数据,与一个复制了。
  3. 如果辅助副本成为主副本,则内存中加载的数据将丢失信息。
  4. Reliable Dictionary还具有“缓存”功能,可将未使用的“冷”数据刷新到磁盘上以释放内存,这是他们所做的改进之一,以便每当您长时间不使用数据时就更好地利用内存。到时候,它们会从内存中删除字典值而不是键来释放空间,当您再次访问数据时,将从磁盘中加载数据。