共用方式為

Azure Service Fabric中可靠集合的准则和建议

本部分提供有关使用可靠状态管理器和 Reliable Collections 的指导原则。 目的是帮助用户避免常见错误。

可靠集合指导原则

这些准则组织为简单建议,其前缀为 “Do”、“ 考虑”、“ 避免”和 “请勿”。

  • 请勿修改读取操作返回的自定义类型的对象(例如, TryPeekAsyncTryGetValueAsync)。 Reliable Collections 与 Concurrent Collections 一样,返回对这些对象的引用,而非副本。
  • 在修改返回的自定义类型的对象之前,务必对其进行深层复制。 由于结构和内置类型是按值传递的,因此无需对其执行深层复制,除非它们包含要修改的引用类型字段或属性。
  • 不要使用 TimeSpan.MaxValue 来处理超时。 应使用超时值来检测死锁。
  • 在提交、中止或释放事务后,请勿使用该事务。
  • 不要在事务创建时的范围之外使用枚举。
  • 不要在另一个事务的 using 语句中创建事务,因为它可能会导致死锁。
  • 不要在同一事务中创建可靠状态并使用该可靠状态。 这会导致 InvalidOperationException 异常。
  • 务必确保 IComparable<TKey> 实现正确。 系统依赖 IComparable<TKey> 进行检查点和行的合并。
  • 请使用更新锁在读取某项时有意更新它,以防止某类死锁的发生。
  • 请考虑将每个分区的可靠集合数保持在 1000 以下。 建议选择包含更多项的可靠集合,而不是多个包含较少项的可靠集合。
  • 请考虑将您的元素(例如,Reliable Dictionary 的 TKey + TValue)控制在 80 千字节以下,越小越好。 这会减少大型对象堆的使用量,并降低磁盘和网络 IO 的要求。 通常情况下,当只更新值的一小部分时,它可以减少重复数据的复制。 在 Reliable Dictionary 中实现此效果的常用方法是将一行划分为多行。
  • 请考虑使用备份和还原功能进行灾难恢复。
  • 避免在同一事务中混合使用单个实体操作和多个实体操作(例如 GetCountAsyncCreateEnumerableAsync),因为它们的隔离级别不同。
  • 请务必处理 InvalidOperationException。 系统可能出于各种原因中止用户事务。 例如,当可靠状态管理器将其角色从“主要”更改为其他角色时,或者当长时间运行的事务阻止截断事务日志时。 在这类情况下,用户可能会收到 InvalidOperationException,指示其事务已终止。 假设用户未请求终止事务,处理此异常的最佳方式是释放事务,检查取消令牌是否已发出信号(或副本的角色已更改),如果未创建新事务,则重试。
  • 不要在事务中应用 并行并发 操作。 一个事务中仅支持一个用户线程操作。 否则,会导致内存泄漏和锁定问题。
  • 请在提交完成后尽快处理事务(特别是在使用 ConcurrentQueue 时)。
  • 不要在事务中执行任何阻塞代码。
  • 字符串用作可靠字典的键时,排序顺序使用默认字符串比较器 CurrentCulture。 请注意,CurrentCulture 排序顺序不同于Ordinal 字符串比较器
  • 请勿处置或取消正在提交的事务。 这不受支持,可能会使主机进程崩溃。
  • 在读取多个字典或向多个字典写入内容时,请确保所有并发事务中针对不同字典的操作顺序保持相同,以避免发生死锁情况。

需谨记以下几点:

  • 所有 Reliable Collection API 的默认超时值均为 4 秒。 大多数用户应使用默认超时值。
  • 所有 Reliable Collections API 中的默认取消标记均为 CancellationToken.None
  • 可靠字典的键类型参数 (TKey) 必须正确实现 GetHashCode()Equals()。 键必须不可变。
  • 若要实现 Reliable Collections 的高可用性,每个服务应至少有一个目标,并且最小副本集大小必须为 3。
  • 辅助副本上的读取操作可能会读取未提交仲裁的版本。 这意味着从单个辅助副本读取的数据版本可能被错误处理。 从主副本读取的数据始终是稳定的:绝不会出现虚假进展。
  • 在一个可靠集合中,由你的应用程序持久保存的数据的安全/隐私是由你决定的,并且受存储管理提供的保护措施制约;即,操作系统磁盘加密可用于保护你的静态数据。
  • ReliableDictionary 枚举使用按键排序的排序数据结构。 为了提高枚举的效率,提交会被添加到临时散列表中,然后在检查点后移动到主要的排序数据结构中。 如果需要验证检查是否存在键,“添加”/“更新”/“删除”操作的最佳运行时为 O(1),最差运行时为 O(log n)。 读取可能是 O(1)或 O(log n),具体取决于您是从最新提交还是从早期提交中读取。

关于持久化可靠集合的其他指导原则

决定使用易失可靠集合时,请考虑以下事项:

  • ReliableDictionary 具有易失性支持
  • ReliableQueue 具有易失性支持
  • ReliableConcurrentQueue 不具有易失性支持
  • 持久化服务无法变为易失性服务。 将 HasPersistedState 标志改为 false 需要从头开始重新创建整个服务
  • 易失性服务无法变为持久化服务。 将 HasPersistedState 标志改为 true 需要从头开始重新创建整个服务
  • HasPersistedState 是服务级别的配置。这意味着所有集合都可归为持久化集合和易失性集合中的一种。 不能混合可变集合和持久化集合
  • 由于法定人数的丧失,易失性分区会导致数据完全丢失
  • 备份和还原不可用于易失性服务

后续步骤