MSR Orleans - 如何创建具有并行读取的 reader-writer grain
MSR Orleans - How to create a reader-writer grain with parallel reads
我需要一个 reader-writer grain(s?) 来保存一些值,以便系统的其他部分可以频繁地并行引用它们。
我所追求的是存储一些系统范围的配置值,这些值经常被访问,并且可能会发生变化,但很少发生(最多一个月一次左右)。系统应该可以在不停机的情况下进行重新配置。我目前正在考虑的是将数据存储在某个数据库中。然后在silo启动的时候会读取,外部变化后会有专门的回调重新读取数据。我不想每次需要时都从数据库中读取数据,因为:
- 它会在筒仓内产生不必要的处理开销,因为必须处理和过滤掉一些数据。
- 它会增加数据库的负载,我不能保证它在处理高负载方面与筒仓环境一样好。
- 数据在更新之前由筒仓环境验证。直接从数据库读取意味着在操作员更新和修复新数据时将没有中间层来保存最后已知的有效数据。
我可以很容易地创建一个 reader-writer 锁定的内存数据存储,但是 Orleans 的单线程执行策略不允许并行访问保存数据的 grain。我可以想到以下方法来绕过这个:
- 在多个grains中有多个数据副本。这显然不是最优的。
- 使用静态字段存储数据,让grain成为一个无状态的worker。这意味着每个筒仓都有自己的数据副本(这也有助于减少网络负载),但是无法要求每个筒仓更新其数据副本(至少我知道)。
建议?
你看过像 Smart cache pattern 这样的东西吗?
也许使用 Reentrant
grain 也有帮助,这将允许方法调用交错。
我在 github 上发现 this issue 也有同样的要求。
我们在 GitHub 上找到了不需要基于计时器的更新的解决方案。我将在这里详细说明解决方案:
- 有一个master grain,负责从数据库中读取数据。当配置更改时,此 grain 还会接收外部 UpdateConfig 调用。数据库已更新 'manually',所以我不关心它是否不自动获取更新。
- 每个筒仓上都有无状态的工作缓存颗粒。这些 grains 将数据存储在静态对象中(以帮助减少内存占用)并使用 reader-writer 锁来管理对数据的访问。当第一个在筒仓上醒来时,它会更新数据,其余的只使用该数据。他们还支持外部 UpdateConfig 调用,该调用将依次向主谷物询问新数据。
- 有一个 bootstrap 提供程序可以做两件事。首先,它在初始化时唤醒 master grain,因此数据在需要之前就可用,因此我们可以避免懒惰的 init 打嗝。其次,提供者还支持控制命令(有关可控制提供者的示例,请参见 here)。收到此命令后,它将请求第一个可用的缓存颗粒(保证是本地的)来更新静态对象。这样,数据在每个筒仓内更新。 master grain 在更新数据时简单地发送这个控制命令。
我需要一个 reader-writer grain(s?) 来保存一些值,以便系统的其他部分可以频繁地并行引用它们。
我所追求的是存储一些系统范围的配置值,这些值经常被访问,并且可能会发生变化,但很少发生(最多一个月一次左右)。系统应该可以在不停机的情况下进行重新配置。我目前正在考虑的是将数据存储在某个数据库中。然后在silo启动的时候会读取,外部变化后会有专门的回调重新读取数据。我不想每次需要时都从数据库中读取数据,因为:
- 它会在筒仓内产生不必要的处理开销,因为必须处理和过滤掉一些数据。
- 它会增加数据库的负载,我不能保证它在处理高负载方面与筒仓环境一样好。
- 数据在更新之前由筒仓环境验证。直接从数据库读取意味着在操作员更新和修复新数据时将没有中间层来保存最后已知的有效数据。
我可以很容易地创建一个 reader-writer 锁定的内存数据存储,但是 Orleans 的单线程执行策略不允许并行访问保存数据的 grain。我可以想到以下方法来绕过这个:
- 在多个grains中有多个数据副本。这显然不是最优的。
- 使用静态字段存储数据,让grain成为一个无状态的worker。这意味着每个筒仓都有自己的数据副本(这也有助于减少网络负载),但是无法要求每个筒仓更新其数据副本(至少我知道)。
建议?
你看过像 Smart cache pattern 这样的东西吗?
也许使用 Reentrant
grain 也有帮助,这将允许方法调用交错。
我在 github 上发现 this issue 也有同样的要求。
我们在 GitHub 上找到了不需要基于计时器的更新的解决方案。我将在这里详细说明解决方案:
- 有一个master grain,负责从数据库中读取数据。当配置更改时,此 grain 还会接收外部 UpdateConfig 调用。数据库已更新 'manually',所以我不关心它是否不自动获取更新。
- 每个筒仓上都有无状态的工作缓存颗粒。这些 grains 将数据存储在静态对象中(以帮助减少内存占用)并使用 reader-writer 锁来管理对数据的访问。当第一个在筒仓上醒来时,它会更新数据,其余的只使用该数据。他们还支持外部 UpdateConfig 调用,该调用将依次向主谷物询问新数据。
- 有一个 bootstrap 提供程序可以做两件事。首先,它在初始化时唤醒 master grain,因此数据在需要之前就可用,因此我们可以避免懒惰的 init 打嗝。其次,提供者还支持控制命令(有关可控制提供者的示例,请参见 here)。收到此命令后,它将请求第一个可用的缓存颗粒(保证是本地的)来更新静态对象。这样,数据在每个筒仓内更新。 master grain 在更新数据时简单地发送这个控制命令。