我正在使用 azure 表存储(注意:不是Azure SQL)并且我有以下情况:
在我的应用程序中,我有许多“邀请”用户的组织,并且在邀请中有一个关联的“角色”和“到期”。一旦组织邀请了用户,我希望组织看到他们邀请的用户列表,并且我希望用户看到他们被邀请的组织列表。
我认为在我的应用程序和这种情况下,数量会很少(即一个组织只会邀请几个用户,而一个用户通常只会被一个组织邀请)。但是,即使有非常大的数字,人们也可以使用一种通用模式来处理这种情况吗?
我正在使用 azure 表存储(注意:不是Azure SQL)并且我有以下情况:
在我的应用程序中,我有许多“邀请”用户的组织,并且在邀请中有一个关联的“角色”和“到期”。一旦组织邀请了用户,我希望组织看到他们邀请的用户列表,并且我希望用户看到他们被邀请的组织列表。
我认为在我的应用程序和这种情况下,数量会很少(即一个组织只会邀请几个用户,而一个用户通常只会被一个组织邀请)。但是,即使有非常大的数字,人们也可以使用一种通用模式来处理这种情况吗?
我目前使用三种方法,具体取决于我的需要:
事务性的
我将正向和反向关系存储在同一个分区上......这意味着每个实体都在同一个分区上(即这种方法受单个分区的速率限制),但这意味着您可以使用批处理事务来插入正向和反向关系,这意味着你知道它们永远是正确的。
public class OrganisationInvite : TableEntity
{
// Partition Id - string.Empty
// Row Id - "Invite_" + OrangisationId + "_" + UserId
public string Role { get; set; }
public DateTime Expiry { get; set; }
}
public class OrganisationRequest : TableEntity
{
// Partition Id - string.Empty
// Row Id - "Request_" + UserId + "_" + OrganisationId
public string Role { get; set; }
public DateTime Expiry { get; set; }
}
要查询,我使用t.RowKey.StartsWith("Request_...")
或t.RowKey.StartsWith("Invite_...")
取决于我是否想要获取用户/组织邀请列表。
我想这在数据非常关键时最好使用。
最终一致性
我为这两个表提供了所有属性,但它们位于不同的分区上,这为您提供了出色的可伸缩性,但您会丢失事务。我使用消息队列来更新反向关系以匹配正向关系,因此最终数据将匹配。(但有一段时间可能不会)。
// Assume both in the same table, thus the prefix on partition
public class OrganisationInvite : TableEntity
{
// Partition Id - "Invite_" + OrangisationId
// Row Id - UserId
public string Role { get; set; }
public DateTime Expiry { get; set; }
}
public class OrganisationRequest : TableEntity
{
// Partition Id - "Request_" + UserId
// Row Id - OrganisationId
public string Role { get; set; }
public DateTime Expiry { get; set; }
}
要查询,我使用t.PatitionKey == "Request_..."
或t.PatitionKey == "Invite_..."
取决于我是否想要获取用户/组织邀请列表。也许您会将其中之一视为“事实来源”,因此当用户确实接受邀请时,您将查找“事实来源”并为用户提供该角色等。
这是最具可扩展性的解决方案,如果您在其上使用缓存,则尤其有意义。
真相的来源
在这种情况下,我只给出一个实体的属性,而另一个实体只有反向关系的键。您可以将实体添加到最长或查询最多的列表中......在这种情况下,我会说它是一个组织的邀请。与最终一致性方法一样,您可以将逆向关系排队以添加逆向实体。此方法为您提供完整的数据一致性,除非您添加新关系(因为在创建反向关系之前有一点时间),并且具有高度可扩展性 - 虽然读取反向列表的成本更高。
// Assume both in the same table, thus the prefix on partition
public class OrganisationInvite : TableEntity
{
// Partition Id - "Invite_" + OrangisationId
// Row Id - UserId
public string Role { get; set; }
public DateTime Expiry { get; set; }
}
public class OrganisationRequest : TableEntity
{
// Partition Id - "Request_" + UserId
// Row Id - OrganisationId
}
您可以使用 轻松查询正向关系t.PatitionKey == "Invite_..."
。但是,这种反比关系并非微不足道。您必须使用查询t.PatitionKey == "Request_..."
并创建 n 个并行调用来获取每个项目的数据转发数据(在这种情况下,使用在反向关系的 RowKey 中找到的组织 ID)。如果该项目不存在,则不要将其添加到最终列表中。这可确保如果组织更改其角色,例如,用户将在下一次点击时看到此更改。
如果很少使用反向关系并且数据是最新的(我在想用户权限等?),我认为这种方法很有用