DynamoDB授权服务图状模型构建及查询更新问题咨询
DynamoDB授权服务模型设计方案
针对你提到的授权实体关系(App→Role→FA→SE,且存在共享实体),结合所需的两个访问模式,推荐采用**邻接表+物化路径+全局二级索引(GSI)**的组合设计,同时配合反向关系维护来解决同步更新问题。
核心表结构设计
主表采用PK(分区键)和SK(排序键)的组合模式,同时存储层级路径和根实体标识,具体字段如下:
PK: 格式为实体类型#实体ID(如APP#APP1、ROLE#Role1)SK: 格式为关系类型#关联实体ID(如HAS_ROLE#Role1、ASSOCIATED_WITH#FA#FA1)EntityData: 存储对应实体的业务数据(如App名称、Role权限描述等)HierarchyPath: 实体的层级路径(如APP1/Role1/FA1/SE1),用于层级范围查询RootEntity: 根实体的PK(如APP#APP1),用于GSI分区
示例表数据
| PK | SK | EntityData | HierarchyPath | RootEntity |
|---|---|---|---|---|
| APP#APP1 | HAS_ROLE#Role1 | {"name": "APP1"} | APP1 | APP#APP1 |
| ROLE#Role1 | HAS_FA#FA1 | {"name": "Role1"} | APP1/Role1 | APP#APP1 |
| FA#FA1 | HAS_SE#SE1 | {"name": "FA1"} | APP1/Role1/FA1 | APP#APP1 |
| SE#SE1 | "" | {"name": "SE1", "perm": "read"} | APP1/Role1/FA1/SE1 | APP#APP1 |
| APP#APP1 | HAS_ROLE#Role2 | {"name": "APP1"} | APP1 | APP#APP1 |
| ROLE#Role2 | HAS_FA#FA2 | {"name": "Role2"} | APP1/Role2 | APP#APP1 |
| FA#FA2 | HAS_SE#SE2 | {"name": "FA2"} | APP1/Role2/FA2 | APP#APP1 |
| SE#SE2 | "" | {"name": "SE2", "perm": "write"} | APP1/Role2/FA2/SE2 | APP#APP1 |
| ROLE#Role2 | HAS_FA#FA1 | {"name": "Role2"} | APP1/Role2 | APP#APP1 |
| FA#FA1 | ASSOCIATED_WITH#ROLE#Role2 | {"name": "FA1"} | APP1/Role2/FA1 | APP#APP1 |
| SE#SE1 | ASSOCIATED_WITH#FA#FA1 | {"name": "SE1", "perm": "read"} | APP1/Role2/FA1/SE1 | APP#APP1 |
针对访问模式的解决方案
1. 获取指定Application对应的所有Roles、FAs及SEs
创建一个GSI,将RootEntity设为GSI的分区键,HierarchyPath设为GSI的排序键。
- 查询逻辑:直接查询GSI中
RootEntity = "APP#APP1"的所有项,即可获取该App下所有层级的Role、FA、SE实体。 - 优势:一次查询覆盖所有关联实体,无需多次递归查询;通过
HierarchyPath的前缀可以快速过滤特定层级(如只查FAs,可筛选HierarchyPath以APP1/*/FA开头的项)。
2. 更新SE1并同步至所有关联FAs
方案一:反向关系+批量更新
在表中为SE实体维护反向关联记录(如示例中SE#SE1对应的ASSOCIATED_WITH#FA#FA1项):
- 更新SE1时,先执行查询:
PK = "SE#SE1" AND SK BEGINS_WITH "ASSOCIATED_WITH#FA#",获取所有关联的FA ID。 - 批量更新这些FA的
EntityData中与SE1相关的属性(如果FA存储了SE的冗余数据)。
方案二:引用式查询+DynamoDB Streams
如果不需要在FA中存储SE的冗余数据,而是通过SE ID实时查询:
- FA的
EntityData只存储关联的SE ID(如{"name": "FA1", "se_ids": ["SE1"]})。 - 当SE1更新时,无需同步FA,授权校验时直接通过SE ID查询最新的SE数据。
- 若需要强一致性同步,可借助DynamoDB Streams监听SE的更新事件,触发Lambda函数自动更新所有关联FA的相关引用或冗余数据。
额外优化建议
- 对于共享实体(如FA1被多个Role关联),确保每个关联关系都有独立的表记录,避免因共享导致的查询遗漏。
- 物化路径可以采用分隔符(如
/)或固定长度前缀,便于使用BEGINS_WITH进行范围查询。 - 若实体层级较多,可考虑引入闭合表模式(存储所有祖先-后代的直接关联),进一步优化后代查询效率,但会增加写入时的维护成本。
内容的提问来源于stack exchange,提问作者Jesus Zuñiga Vega
相关产品推荐
相关产品推荐

