【问题标题】:Users-Posts-Comments relationship implementation on reliable collections可靠集合上的用户-帖子-评论关系实现
【发布时间】:2016-12-14 11:44:55
【问题描述】:

假设我有三个类:UserPostComment。标准操作——用户可以创建帖子并将 cmets 写入这些帖子。所以我们有下面描述的情况:

我需要非常快速地执行这三个查询:

  • 获取帖子的所有 cmets
  • 获取用户的所有 cmets
  • 获取发表评论

即使我将使用分区,它看起来也是不可能的。至少没有一本可靠的字典。可能我需要几个字典来处理不同的查询。我说的对吗?

【问题讨论】:

    标签: list dictionary data-structures azure-service-fabric


    【解决方案1】:

    我也在做同样的事情!首先:我的架构有点不同。我有一个用户、一个主题和一个评论。该主题只是一个带有评论ID列表(IEnumerable long)的类,仅此而已。第一条评论是帖子。

    哦,首先,一点警告:我刚刚开始使用 Service Fabric,所以我可能做错了;)

    该用户与我无关。我只是将用户标识存储在评论中。在检索 cmets 列表时,我从有状态用户服务中获取用户。或者我直接把用户名存到评论里,还不确定。

    所以这给我留下了主题和 cmets。首先我想'让我们创建一个有状态的主题服务和有状态的评论服务'。但后来我意识到,对于我加载的每个主题,我都需要为每个评论调用 CommentService 以获取 cmets。

    所以我创建了一个处理 2 个 IReliableDictionaries 的 TopicService:主题和 cmets。

    每当发表评论时,我都会使用 TopicId 作为分区键,并在该分区中存储评论。所以不要使用commentid!这样特定主题的所有 cmets 都在同一个分区中。

    在加载包含所有 cmets 的主题时,我再次使用 TopicId 作为分区键,从主题的可靠字典中获取主题,并在 cmets 的可靠字典中循环评论 ID 列表。不确定它是否有帮助,但我的 GetComments 看起来像这样:

            var topics = await this.StateManager.GetOrAddAsync<IReliableDictionary<long, TopicModel>>("topics");
            var comments = await this.StateManager.GetOrAddAsync<IReliableDictionary<long, CommentModel>>("comments");
    
            List<CommentModel> result = new List<CommentModel>();
    
            using (var tx = this.StateManager.CreateTransaction())
            {
                ConditionalValue<TopicModel> topic = await topics.TryGetValueAsync(tx, topicid);
    
                if(topic.HasValue)
                {
                    foreach(long commentid in topic.Value.CommentsInternal)
                    {
                        ConditionalValue<CommentModel> comment = await comments.TryGetValueAsync(tx, commentid);
    
                        if (comment.HasValue)
                            result.Add(comment.Value);
                    }
                }
    
                await tx.CommitAsync();
            }
    
            return result;
    

    我还没有完成,方法还有一些工作。

    也许这对你有帮助:)

    编辑:哦,有一个缺点!当您想通过其 id 加载单个评论时,您需要提供 topicid。所以我的 CommentModel 类有一个 CommentId 和一个 TopicId 属性。

    【讨论】:

    • 感谢您的回答。我在考虑分区,但在我看来有点“复杂”,我继续寻找更简单的解决方案。您将如何获得特定用户的所有 cmets?你为什么打电话给CommitAsync,因为可靠的集合没有变化?您是否将 cmets 存储在可靠字典内的列表中?如果是这样,它就不是线程安全的,应该避免。
    • 分区并不难。它都是关于在节点上对数据进行分组的。服务结构为此做的工作最多。这也取决于有多少 cmets。如果它有数千个,请不要打扰分区。如果它在数十万......分区!特定用户的所有 cmets 都可以使用 Azure 搜索或保留单独的索引来完成。我承诺作为一种习惯。我有一个事务,所以我以提交结束它。列表中的注释是的,我使用一个 Actor(没有持久性)来编辑数据。 Actor 的行为是单线程的。 Write=Actor,Read=有状态服务。
    • 那么,每个主题一个演员来存储 cmets 还是存储在服务中,而您只编辑数据,从演员调用服务的方法?有多少用户可以同时向主题添加/删除新的 cmets?
    • Actor 仅用于写入操作。读取操作直接转到有状态服务。 Actor 没有状态,因此持久化状态设置为 None(Actor 类上方的属性)。该主题仅包含一组评论 ID,因此非常轻巧。向主题添加评论大约需要 9 毫秒。那是每秒 111 厘米(!)。如果这还不够,您可以跳过 Actor 并创建一个带有队列的有状态服务,该队列将评论 ID 添加到主题中。当它真的很忙(每秒数百个 cmets)时,这可能会增加一点延迟,但在相当长的几个小时内几乎是即时的。
    • 你为什么决定通过演员写作和通过服务阅读?
    猜你喜欢
    • 1970-01-01
    • 2016-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-13
    相关资源
    最近更新 更多