【问题标题】:Designing a Firebase based scalable feed model设计基于 Firebase 的可扩展 Feed 模型
【发布时间】:2015-10-15 08:52:18
【问题描述】:

问题:

如何设计一个以 Firebase 作为后端且可扩展的社交网络“供稿”?

可能的答案:

“MVP”解决方案是为每个用户设计一个feeds 根子节点,并将来自关注用户的任何新帖子附加到每个关注者的提要中。

users
  user1
    name: bob
  user2
    name: alice
    follows: 
      user1: true

posts
  post1
     author: user1
     text: 'Hi there'

feeds
  user2
    post1: true

这很好用,并在Firefeed 项目中进行了演示。但它不能很好地扩展:如果 Katy Perry 想要发布一些东西,她的手机将不得不写入数百万个订阅源。

因此this SO question 中报告的解决方案将此操作委托给基于服务器的进程。

我的问题是,Firebase 是一个“无后端”解决方案,这是我使用它的主要原因,所以我想确保在没有服务器的情况下绝对没有机会实现此功能。

如果feeds 子元素在上述架构中被删除了怎么办?

然后这样做:

baseRef.child('posts')
       .orderBy('author')
       .whereIn(baseRef.child('users/user2/follows').keys())

不幸的是,whereIn 不存在于 Firebase API 中,也不存在子查询:(

任何其他可能不需要服务器的模型结构?

谢谢

【问题讨论】:

    标签: performance database-design firebase


    【解决方案1】:

    Firebase 家伙在他们的博客上回复了:https://www.firebase.com/blog/2015-10-07-how-to-keep-your-data-consistent.html

    这篇文章是关于“数据扇形”(在一次原子写入操作中将项目传播到多个节点)。

    该技术极大地解决了原始问题的提要模型

    该帖子实际上包含实现它的示例代码:

    • 创建扇出对象的函数(实际上是一个简单的对象,键是要编写的API端点)

      function fanoutPost({ uid, followersSnaphot, post }) {
              // Turn the hash of followers to an array of each id as the string
              var followers = Object.keys(followersSnaphot.val());
              var fanoutObj = {};
              // write to each follower's timeline
              followers.forEach((key) => fanoutObj['/timeline/' + key] = post);
              return fanoutObj;  
      }
      
    • 以及使用这个函数的逻辑:

      var followersRef = new Firebase('https://<YOUR-FIREBASE-APP>.firebaseio.com/followers');
      var followers = {};
      followersRef.on('value', (snap) => followers = snap.val());
      var btnAddPost = document.getElementById('btnAddPost');
      var txtPostTitle = document.getElementById('txtPostTitle');
      btnAddPost.addEventListener(() => {
            // make post
            var post = { title: txtPostTitle.value };
            // make fanout-object
            var fanoutObj = fanoutPost({ 
                uid: followersRef.getAuth().uid, 
                followers: followers, 
                post: post 
            });
            // Send the object to the Firebase db for fan-out
            rootRef.update(fanoutObj);
      });
      

    注意:这比每次在一个追随者提要中写入循环更具可扩展性。然而,对于数百万的追随者来说,它可能还是不够的。在这种情况下,信任进行多次写入的服务器操作会更安全。我认为客户端最多可以用于数百个关注者,这是社交媒体上关注者的平均数量。 (这需要通过测试来验证)

    【讨论】:

    • 这里的读操作怎么样......对于每个 id,我们需要调用不同的观察者或循环,对吗?这是适当或有效的解决方案吗?
    猜你喜欢
    • 2011-02-14
    • 2012-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-28
    • 2010-11-20
    相关资源
    最近更新 更多