Performance 快速遍历ACL的策略
我们目前正在进行一个项目,其中主要的域对象是内容节点,我们正在使用一个类似ACL的系统,其中层次结构中的每个节点都可以包含覆盖或补充其父节点上的规则。例如,一切都基于角色和行动Performance 快速遍历ACL的策略,performance,algorithm,tree,acl,Performance,Algorithm,Tree,Acl,我们目前正在进行一个项目,其中主要的域对象是内容节点,我们正在使用一个类似ACL的系统,其中层次结构中的每个节点都可以包含覆盖或补充其父节点上的规则。例如,一切都基于角色和行动 Node 1 - {Deny All, Allow Role1 View} \- Node 2 - {Allow Role2 View} \- Node 3 - {Deny Role1 View} 在这种情况下,规则将按从上到下的顺序读取,因此节点3只能由Role2查看。这在概念上并不复杂 检索单个节点的规则可能
Node 1 - {Deny All, Allow Role1 View}
\- Node 2 - {Allow Role2 View}
\- Node 3 - {Deny Role1 View}
在这种情况下,规则将按从上到下的顺序读取,因此节点3只能由Role2查看。这在概念上并不复杂
检索单个节点的规则可能会导致一些查询,获取所有父节点,然后重新创建规则列表并对其进行评估,但此过程可能会很麻烦,因为层次结构可能会变得很深,并且每个节点上可能有很多规则
我一直在考虑为每个节点准备一个带有预先计算的规则的表,每当更改权限并将其传播到更新的节点的所有叶节点时,都可以重新创建该表
您认为有没有其他策略可以加快规则的检索和计算?理想情况下,它应该在一个查询中完成,但树并不是最好的结构。我认为可以采用
其思想是每个节点维护一个预计算的列表,并由其父节点简单地通知任何更新,以便可以重新计算该列表
这可以通过两种不同的方式完成:
通知发生了更改,但不要重新计算任何内容
每次更新时重新计算
如果可能的话,我建议使用1
,因为它不需要在根目录更新时重新计算整个世界,只需要在需要时重新计算(事实上是延迟求值),但是如果很少更新但需要快速检索(尽管存在更多并发问题),您可能更喜欢第二个选项
让我们举例说明解决方案1:
Root ___ Node1 ___ Node1A
\ \__ Node1B
\_ Node2 ___ Node2A
\__ Node2B
现在,首先,如果我要求Node2A
规则,它们都没有预计算任何内容(都处于脏状态):
Node2A
意识到它是脏的:它查询Node2
规则
Node2
意识到它是脏的:它查询Root
Root
没有任何父级,因此它不能脏,它将其规则发送到Node2
Node2
缓存来自Root
的答案,将其规则与从Root
接收的规则合并,并清除脏位,它将合并结果(现在缓存)发送到Node2A
Node2A
缓存、合并、清除脏位并返回结果
如果我随后要求Node2B
规则:
Node2B
脏了,它查询Node2
Node2
是干净的,它会回复
Node2B
缓存、合并、清除脏位并返回结果
请注意,Node2
没有重新计算任何内容
在更新情况下:
- 我更新
Node1
:我使用Root
缓存规则重新计算新规则,并向Node1A
和Node1B
发送节拍,通知它们缓存已过期
Node1A
和Node1B
设置它们的脏位,如果它们有孩子,它们也会传播此通知
请注意,因为我缓存了Root
规则,所以我不必查询Root
对象,如果这是一个足够简单的操作,您可能更希望根本不缓存它们:如果您不在这里玩分布式游戏,而查询根目录
只涉及一次内存往返,为了节省一些内存和簿记,您可能不希望重复它
希望它能让您继续。您的预计算版本似乎存储了与每个节点上每个角色相关的所有权限。通过遍历树,在到达节点时对节点进行编号,并为每个角色生成一个节点编号和权限更改数组(仅针对与该角色相关的权限更改的节点),可以节省一点时间和空间。这只会产生输入树(包括其注释)大小的线性输出。然后,当您来检查某个节点上某个角色的权限时,请使用该节点的编号搜索阵列,以查找阵列中表示您在巡更期间访问该节点时权限最近更改的点
这可能在某种程度上与and有关,但我真的不知道这些引用是否有用。非常有用的回答,我想你是在暗示:预计算全部(在或多或少复杂的策略中)。一点也不,这是浪费。我的意思是延迟计算(根据需要计算,并缓存结果),并使用观察者模式来知道何时缓存的结果不推荐使用。