Service Fabric Reliable Collections 中是否有既定的分页模式
Is there an established pattern for paging in Service Fabric ReliableCollections
在可靠集合(特别是 IReliableDictionary)中,实现 'common' 查询的一种方法是更新二级字典,该字典构造要在枚举中以特定方式排序的键。对于大型数据集,我想避免在 周围穿梭大量数据。
为了实现这一点,我想实现某种延续令牌,调用者可以在请求数据时提供给我。我目前通过首先生成一个有序的枚举并返回前 n 个项目来实现这一点,其中 n = MAX_PAGE 大小。 continuation 本质上是该 n 项列表中的最后一个键。下次调用者传入延续令牌时,我生成有序枚举,并使用指定键应大于延续的过滤器函数。
这有 2 个问题(我可以看到):
- 集合可能会在调用者首次请求页面和后续请求之间发生变化。这一点,我不确定我是否可以避免,因为无论谁试图翻阅数据,都需要随时更新集合。
- 我不确定过滤功能是如何使用的。我假设由于开发人员可以过滤任何内容,因此 GetEnumerableAsync() 方法必须在返回可枚举 之前提供字典中的所有键。对于足够大的数据集,这似乎很慢。
对于像这样的分页数据是否有任何规定的方法?我开始觉得我可能为我的一些用例找错了 Reliable Collections。
建立二级索引的一种方法是使用Notifications。使用具有引用类型 TKey 和 TValue 的通知,您可以维护二级索引而无需创建 TKey 或 TValue 的任何副本。
如果您需要二级索引提供快照隔离,那么二级索引选择的数据结构必须实现多版本并发控制。
如果您没有这样的数据结构来托管二级索引,另一种选择是让事务和枚举在分页客户端调用中保持活动状态。通过这种方式,您可以使用 Reliable Dictionary 的内置快照支持在不阻塞写入的情况下提供对数据的分页一致扫描。在这种情况下,令牌将是 TransactionId allowing your service to find the relevant enumeration to MoveNextAsync 上的。使用此选项的缺点是 Reliable Dictionary 将无法 trim 旧版本的值,这些值由可能很长 运行 的快照事务保持可见。
为了减轻上述缺点,您可能希望限制进行中快照事务的数量以及在您的服务处理枚举和相关读取事务之前客户端必须完成分页枚举的时间。
当 CreateEnumerableAsync 与键过滤器一起使用时,Reliable Dictionary 将为每个键调用过滤器以查看它是否满足自定义过滤器。由于今天 TKeys 始终保存在内存中,因此对于大多数密钥过滤器,我们在这里没有看到问题。枚举中最昂贵的部分往往是从磁盘中检索分页出的值。
我也有类似的问题,也是涉及到对多个分区的数据进行过滤和排序。
我的计划是通过使用通知在非分区有状态服务中构建索引视图。在这里,我将有多个字典,具有不同的键,其中每个键是一个或多个可以过滤或排序的属性,值是 ID 的排序列表。
基本上,我计划对这些键进行搜索、排序和分页,然后在最后一步,我使用需要返回到原始分区的页面的 ID,并获取这些 ID 的完整数据从那里开始(这也可以通过不同的无状态服务完成)。
该方法不提供数据一致性,因为查询的数据在后续分页之间可能会发生变化。
它肯定比带有快照和延续令牌的慢,但也许值得一试。
在可靠集合(特别是 IReliableDictionary)中,实现 'common' 查询的一种方法是更新二级字典,该字典构造要在枚举中以特定方式排序的键。对于大型数据集,我想避免在 周围穿梭大量数据。
为了实现这一点,我想实现某种延续令牌,调用者可以在请求数据时提供给我。我目前通过首先生成一个有序的枚举并返回前 n 个项目来实现这一点,其中 n = MAX_PAGE 大小。 continuation 本质上是该 n 项列表中的最后一个键。下次调用者传入延续令牌时,我生成有序枚举,并使用指定键应大于延续的过滤器函数。
这有 2 个问题(我可以看到):
- 集合可能会在调用者首次请求页面和后续请求之间发生变化。这一点,我不确定我是否可以避免,因为无论谁试图翻阅数据,都需要随时更新集合。
- 我不确定过滤功能是如何使用的。我假设由于开发人员可以过滤任何内容,因此 GetEnumerableAsync() 方法必须在返回可枚举 之前提供字典中的所有键。对于足够大的数据集,这似乎很慢。
对于像这样的分页数据是否有任何规定的方法?我开始觉得我可能为我的一些用例找错了 Reliable Collections。
建立二级索引的一种方法是使用Notifications。使用具有引用类型 TKey 和 TValue 的通知,您可以维护二级索引而无需创建 TKey 或 TValue 的任何副本。
如果您需要二级索引提供快照隔离,那么二级索引选择的数据结构必须实现多版本并发控制。
如果您没有这样的数据结构来托管二级索引,另一种选择是让事务和枚举在分页客户端调用中保持活动状态。通过这种方式,您可以使用 Reliable Dictionary 的内置快照支持在不阻塞写入的情况下提供对数据的分页一致扫描。在这种情况下,令牌将是 TransactionId allowing your service to find the relevant enumeration to MoveNextAsync 上的。使用此选项的缺点是 Reliable Dictionary 将无法 trim 旧版本的值,这些值由可能很长 运行 的快照事务保持可见。
为了减轻上述缺点,您可能希望限制进行中快照事务的数量以及在您的服务处理枚举和相关读取事务之前客户端必须完成分页枚举的时间。
当 CreateEnumerableAsync 与键过滤器一起使用时,Reliable Dictionary 将为每个键调用过滤器以查看它是否满足自定义过滤器。由于今天 TKeys 始终保存在内存中,因此对于大多数密钥过滤器,我们在这里没有看到问题。枚举中最昂贵的部分往往是从磁盘中检索分页出的值。
我也有类似的问题,也是涉及到对多个分区的数据进行过滤和排序。
我的计划是通过使用通知在非分区有状态服务中构建索引视图。在这里,我将有多个字典,具有不同的键,其中每个键是一个或多个可以过滤或排序的属性,值是 ID 的排序列表。
基本上,我计划对这些键进行搜索、排序和分页,然后在最后一步,我使用需要返回到原始分区的页面的 ID,并获取这些 ID 的完整数据从那里开始(这也可以通过不同的无状态服务完成)。
该方法不提供数据一致性,因为查询的数据在后续分页之间可能会发生变化。
它肯定比带有快照和延续令牌的慢,但也许值得一试。