1

尝试对用户访问的服务的依赖关系进行建模。我创建了一个父/子邻接列表样式表,其中列出了“服务”依赖于组件 1,组件 1 依赖于组件 2 等,以及依赖的类型,例如完全或部分

此图像显示布局 - 依赖关系图像

在此处输入图像描述

Comp 1 和 9 的颜色不同,因为如果它们失败,则整体服务失败。如果 Comp 2-9 中的任何一个失败,则服务会继续,但弹性会降低。

这是我用来创建表格的内容

CREATE TABLE scratch
( 
    KeyID        int    PRIMARY KEY        NOT NULL, 
    CompDesc       varchar(30), 
    CompID        int    NOT NULL, 
    ReliesOn       int    NOT NULL, 
    RelianceType       varchar(30), 
)

INSERT scratch SELECT 0, 'Service', 0, 1, 'Full'
INSERT scratch SELECT 1, 'Component 1', 1, 2, 'Partial'
INSERT scratch SELECT 2, 'Component 1', 1, 3, 'Partial'
INSERT scratch SELECT 3, 'Component 1', 1, 4, 'Partial'
INSERT scratch SELECT 4, 'Component 4', 4, 5, 'Full'
INSERT scratch SELECT 5, 'Component 5', 5, 6, 'Full'
INSERT scratch SELECT 6, 'Component 6', 6, 7, 'Partial'
INSERT scratch SELECT 7, 'Component 6', 6, 8, 'Partial'
INSERT scratch SELECT 8, 'Component 2', 2, 9, 'Full'
INSERT scratch SELECT 9, 'Component 3', 3, 9, 'Full'
INSERT scratch SELECT 10, 'Component 7', 7, 9, 'Full'
INSERT scratch SELECT 11, 'Component 8', 8, 9, 'Full'

然后我可以运行一个非常粗略的查询来显示用户可以访问服务的 4 个不同选项 -

SELECT t1.ReliesOn AS lev1, t2.ReliesOn as lev2, t3.ReliesOn as lev3, t4.ReliesOn as lev4, t5.ReliesOn as lev5, t6.ReliesOn as lev6
FROM Scratch AS t1
LEFT JOIN Scratch AS t2 ON t2.CompID = t1.ReliesOn
LEFT JOIN Scratch AS t3 ON t3.CompID = t2.ReliesOn
LEFT JOIN Scratch AS t4 ON t4.CompID = t3.ReliesOn
LEFT JOIN Scratch AS t5 ON t5.CompID = t4.ReliesOn
LEFT JOIN Scratch AS t6 ON t6.CompID = t5.ReliesOn
WHERE t1.ReliesOn = 1;

(抱歉,可能有更好的方法将该查询串在一起)

有了这个结果 -

lev1    lev2    lev3    lev4    lev5    lev6
1       2       9       NULL    NULL    NULL
1       3       9       NULL    NULL    NULL
1       4       5       6       7       9
1       4       5       6       8       9

我要做的是创建一个查询,我可以列出失败的补偿并确定该服务是否仍然可用,例如

Failed      Result
1           No Service
2,3         Reduced Resiliency
3,8         Reduced Resiliency
2,3,7,8     No Service

这只是一个非常简单的示例,我还有很多需要添加的内容,并且在大多数情况下,许多服务将依赖于相同的组件。

那么,你如何从失败的组合中去向上/跨越/向下依赖关系来确定路径是否仍然存在?

希望这是有道理的

谢谢

4

2 回答 2

0

显然,结果查询并非易事。我向您发布了一个方法,您可以在SQL Fiddle上使用它

MS SQL Server 2014 架构设置

CREATE TABLE scratch
( 
    KeyID        int    PRIMARY KEY        NOT NULL, 
    CompDesc       varchar(30), 
    CompID        int    NOT NULL, 
    ReliesOn       int     NULL, --null to allow node 9
    RelianceType       varchar(30), 
)

INSERT scratch SELECT 0, 'Service', 0, 1, 'Full'
INSERT scratch SELECT 1, 'Component 1', 1, 2, 'Partial'
INSERT scratch SELECT 2, 'Component 1', 1, 3, 'Partial'
INSERT scratch SELECT 3, 'Component 1', 1, 4, 'Partial'
INSERT scratch SELECT 4, 'Component 4', 4, 5, 'Full'
INSERT scratch SELECT 5, 'Component 5', 5, 6, 'Full'
INSERT scratch SELECT 6, 'Component 6', 6, 7, 'Partial'
INSERT scratch SELECT 7, 'Component 6', 6, 8, 'Partial'
INSERT scratch SELECT 8, 'Component 2', 2, 9, 'Full'
INSERT scratch SELECT 9, 'Component 3', 3, 9, 'Full'
INSERT scratch SELECT 10, 'Component 7', 7, 9, 'Full'
INSERT scratch SELECT 11, 'Component 8', 8, 9, 'Full'
INSERT scratch SELECT 12, 'Component 9', 9, Null, 'Full' --node 9 added

这里是查询活动路径的查询:

with 
from_to as ( select 9 as [from], 1 as [to] ),
failed_nodes as ( select 3 as f union select 4 ), --list of failed nodes
cte as (
   select *
          ,CAST(CompID AS VARCHAR(255)) AS Path
   from scratch
   where CompId = (select [from] from from_to ) -easy: ReliesOn is null
   union all
   select s.*
          ,CAST(Path + '.' + CAST(s.CompID AS VARCHAR(255)) AS VARCHAR(255))
   from scratch s
   inner join cte on s.ReliesOn = cte.CompID
   where s.compid not in ( select * from failed_nodes)
)
select * from cte

只需检查结果keyID = 0结果以了解服务是否仍然可用以及活动路径(很简单):where

| KeyID |    CompDesc | CompID | ReliesOn | RelianceType |    Path |
|-------|-------------|--------|----------|--------------|---------|
|    12 | Component 9 |      9 |   (null) |         Full |       9 |
|     8 | Component 2 |      2 |        9 |         Full |     9.2 |
|    10 | Component 7 |      7 |        9 |         Full |     9.7 |
|    11 | Component 8 |      8 |        9 |         Full |     9.8 |
|     7 | Component 6 |      6 |        8 |      Partial |   9.8.6 |
|     5 | Component 5 |      5 |        6 |         Full | 9.8.6.5 |
|     6 | Component 6 |      6 |        7 |      Partial |   9.7.6 |
|     5 | Component 5 |      5 |        6 |         Full | 9.7.6.5 |
|     1 | Component 1 |      1 |        2 |      Partial |   9.2.1 |
|     0 |     Service |      0 |        1 |         Full | 9.2.1.0 < still alive

此外,请将此解决方案适应您的场景以处理RelianceType节点。

于 2017-12-28T11:57:10.857 回答
0

我设法使用Recursive CTEs编写了一个执行此操作的查询。

首先,我冒昧地向scratch表中添加了两条记录:

INSERT scratch SELECT 12, 'Component 9', 9, 10, 'Full'
INSERT scratch SELECT 13, 'Users', 10, 10, 'Full'

这意味着:

  • 9 依赖于 10(用户)如图所示
  • 10 依赖于自身(这意味着在这种情况下 10 是终端组件 - 必须为服务可用的组件)。

在查询中,不可用的组件应在FailedComponentsCTE 中枚举其 id:

with FailedComponents (id) as (
  select id from (values
    (1), (7), (8)
    ) x(id)
), OnlineComponents (compId, reliesOn) as (
  select compId, reliesOn
  from scratch
  where compId = 0 -- <== entry point here
  union all
  select s.compId, s.reliesOn
  from scratch s
  join OnlineComponents c
    on s.compId = c.reliesOn
  where s.compId not in (select id from FailedComponents)
)
select case
  when exists (select * from OnlineComponents where compId = reliesOn)
    then 'Service is available'
    else 'No Service'
  end as [Status]
;

这是SQL Fiddle,您可以在其中尝试不同的值以查看查询如何处理它们。

请注意,该查询不使用表中指定的Full/Partial依赖类型scratch。依赖类型是从上下文中推断出来的。基本上,如果有一种方法可以仅在可用组件上遍历从 0 到 10 的图表,那么整个服务都是可用的。

此外,还有一点警告:递归 CTE 的深度是有限度的。这被调用MAXRECURSION,默认值为 100。如果需要,您需要将其更改为更高的值。

于 2017-12-28T11:57:24.173 回答