【问题标题】:Azure table storage inverse relationshipAzure 表存储反向关系
【发布时间】:2013-02-10 07:39:13
【问题描述】:

我使用的是天蓝色表存储(注意:NOT Azure SQL),我有以下情况:

在我的应用程序中,我有许多“邀请”用户的组织,并且在邀请中有一个关联的“角色”和“到期”。组织邀请用户后,我希望组织看到他们邀请的用户列表,并且我希望用户看到他们受邀加入的组织列表。

我认为在我的应用程序和这种情况下,人数会很少(即一个组织只会邀请几个用户,而一个用户通常只会被一个组织邀请)。但是,即使数字非常大,人们也可以使用一种通用模式来处理这种情况吗?

【问题讨论】:

    标签: azure azure-storage azure-table-storage


    【解决方案1】:

    我目前使用三种方法,具体取决于我的需要:

    事务性

    我将正向和反向关系存储在同一个分区上...这意味着每个实体都在同一个分区上(即这种方法受单个分区的速率限制),但这意味着您可以使用批处理事务来同时插入正向和反向关系,这意味着你知道它们永远是正确的。

    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)。如果该项目不存在,则不要将其添加到最终列表中。这可确保如果组织更改其角色,例如用户将在下一次点击时看到此更改。

    我认为如果很少使用反向关系并且数据是最新的至关重要(我在想用户权限等?),这种方法很有用。

    【讨论】:

      猜你喜欢
      • 2015-08-16
      • 2022-11-24
      • 2013-08-25
      • 2018-01-28
      • 1970-01-01
      • 1970-01-01
      • 2011-04-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多