使用 IReliableDictionary2 时数据何时持久保存到磁盘?
When is data persisted to disk when using IReliableDictionary2?
我们有一个实现 IReliableDictionary2 的 c# 可靠集合字典,并且由于序列化错误而注意到一些奇怪的事情。
我们有 Class X,其中包含另一个 class、Class Y。我们忘记将序列化添加到 Class Y。但是在 [=18 之后的几天=] X 被添加到可靠的集合字典中,Class 当我们检索 X 的实例时 Y 也在那里。
显然可靠的集合字典只是在内存中,但在某些时候集合被持久化到磁盘,此时 Class Y 返回 null 因为它没有添加到序列化 [数据成员].
所以问题是可靠集合何时持久化到磁盘?对此有程序控制吗?或者这是某种集群设置?
问题应该换个方向:当服务结构 从磁盘读取 集合时?
它在提交事务时将数据持久化(同时保存到磁盘和内存缓存中)。从磁盘读取数据可能有多种原因(例如主节点 changed/restarted ..)
当您使用 ReliableCollections
时,每个操作(即 AddAsync
)执行以下操作:
- 更新
ITransaction
本地存储(提供read-your-own-writes semantics
)
- 序列化值并更新本地操作日志(持久化)。
- 将这些字节发送到所有辅助副本以确保它们具有相同的信息。
然后当 ITransaction
被提交时,commit
条目被附加到日志中并发送到所有辅助副本。在 quorum
确认提交的那一刻,操作被视为完成(请参阅 here 了解更多信息)。
所以一般来说,信息一直是序列化的。
您看到 'correct' 结果的原因是因为大多数时候您使用同一个副本 - 主副本(这样做是因为只有主副本可以修改状态)并且来自同一副本的所有读取/写入都返回 正确 值。
这里的技巧是 Service Fabric 可以在节点之间移动副本,即假设您的主副本在 Node1
上。您的所有读取和写入都很好,但 Service Fabric 决定将您的主副本移动到 Node2
- 这导致 Node2
上有一个新的空闲副本,通过向其传输序列化数据来获取 initialized
.当副本初始化时,Node1
上的副本被降级,Node2
上的副本被提升。现在您所有的请求都是来自 Node2
而不是来自 Node1
的服务器(有关服务和副本生命周期的更多信息,请参阅 here and here)。
主要问题:When is data persisted to disk when using IReliableDictionary2?
在堆栈溢出和文档中已经有很多答案。
此答案详细说明了数据是如何更改和复制的:
这一个回答了它是如何存储在内存中的:
你的情况出现问题的原因很明确:
- 你没有正确序列化数据,当数据被复制到其他副本时它会丢失信息
- 正如许多其他问题和帖子中所解释的那样,数据存在于内存中,因此将这些数据写入磁盘并读取到内存是没有意义的,原始副本保存在内存中的完整数据,这是不同的来自复制的那个。
- 如果从副本变成主副本,加载到内存中的数据将丢失信息。
- Reliable Dictionary 还有 'caching' 将未使用的 "cold" 数据刷新到磁盘以释放内存,这是他们为更好地利用内存所做的改进之一,只要您的数据'long' 时间未使用,它们从内存中删除字典值,而不是键,以释放 space,当您再次访问数据时,它将从磁盘加载。
我们有一个实现 IReliableDictionary2 的 c# 可靠集合字典,并且由于序列化错误而注意到一些奇怪的事情。
我们有 Class X,其中包含另一个 class、Class Y。我们忘记将序列化添加到 Class Y。但是在 [=18 之后的几天=] X 被添加到可靠的集合字典中,Class 当我们检索 X 的实例时 Y 也在那里。
显然可靠的集合字典只是在内存中,但在某些时候集合被持久化到磁盘,此时 Class Y 返回 null 因为它没有添加到序列化 [数据成员].
所以问题是可靠集合何时持久化到磁盘?对此有程序控制吗?或者这是某种集群设置?
问题应该换个方向:当服务结构 从磁盘读取 集合时?
它在提交事务时将数据持久化(同时保存到磁盘和内存缓存中)。从磁盘读取数据可能有多种原因(例如主节点 changed/restarted ..)
当您使用 ReliableCollections
时,每个操作(即 AddAsync
)执行以下操作:
- 更新
ITransaction
本地存储(提供read-your-own-writes semantics
) - 序列化值并更新本地操作日志(持久化)。
- 将这些字节发送到所有辅助副本以确保它们具有相同的信息。
然后当 ITransaction
被提交时,commit
条目被附加到日志中并发送到所有辅助副本。在 quorum
确认提交的那一刻,操作被视为完成(请参阅 here 了解更多信息)。
所以一般来说,信息一直是序列化的。
您看到 'correct' 结果的原因是因为大多数时候您使用同一个副本 - 主副本(这样做是因为只有主副本可以修改状态)并且来自同一副本的所有读取/写入都返回 正确 值。
这里的技巧是 Service Fabric 可以在节点之间移动副本,即假设您的主副本在 Node1
上。您的所有读取和写入都很好,但 Service Fabric 决定将您的主副本移动到 Node2
- 这导致 Node2
上有一个新的空闲副本,通过向其传输序列化数据来获取 initialized
.当副本初始化时,Node1
上的副本被降级,Node2
上的副本被提升。现在您所有的请求都是来自 Node2
而不是来自 Node1
的服务器(有关服务和副本生命周期的更多信息,请参阅 here and here)。
主要问题:When is data persisted to disk when using IReliableDictionary2?
在堆栈溢出和文档中已经有很多答案。
此答案详细说明了数据是如何更改和复制的:
这一个回答了它是如何存储在内存中的:
你的情况出现问题的原因很明确:
- 你没有正确序列化数据,当数据被复制到其他副本时它会丢失信息
- 正如许多其他问题和帖子中所解释的那样,数据存在于内存中,因此将这些数据写入磁盘并读取到内存是没有意义的,原始副本保存在内存中的完整数据,这是不同的来自复制的那个。
- 如果从副本变成主副本,加载到内存中的数据将丢失信息。
- Reliable Dictionary 还有 'caching' 将未使用的 "cold" 数据刷新到磁盘以释放内存,这是他们为更好地利用内存所做的改进之一,只要您的数据'long' 时间未使用,它们从内存中删除字典值,而不是键,以释放 space,当您再次访问数据时,它将从磁盘加载。