设计基于Firebase的可扩展Feed模型

时间:2015-07-24 15:41:54

标签: performance database-design firebase

问题:

如何设计社交网络" feed"使用Firebase作为后端,可以扩展吗?

可能的答案:

" MVP"解决方案是设计一个feeds root子项,每个用户一个,并在每个关注者的Feed中附加跟随用户的任何新帖子。

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

posts
  post1
     author: user1
     text: 'Hi there'

feeds
  user2
    post1: true

这很有效,并在Firefeed项目中进行了演示。但它不能很好地扩展:如果凯蒂佩里想发布一些东西,她的手机将不得不写入数百万的饲料。

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

我的问题是,Firebase是一个" no-backend"解决方案,这就是我使用它的主要原因,所以我想确保在没有服务器的情况下完全没有机会实现这个功能。

如果在上述架构中删除了feeds子项,该怎么办?

然后这样做:

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

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

可以在不需要服务器的情况下实现任何其他模型结构吗?

由于

1 个答案:

答案 0 :(得分:7)

Firebase的人有点回复他们的博客:https://www.firebase.com/blog/2015-10-07-how-to-keep-your-data-consistent.html

帖子是关于“数据扇动”(在一个原子写操作中跨多个节点传播项目)。

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

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

  • 用于创建fannout对象的函数(实际上是一个简单的对象,其中键是要写入的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);
    });
    

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