Star

云计算Project:基于多个后端的社交网络时间线的实现

本文是关于CMU15619Cloud Computing项目:Social Networking Timeline with Heterogeneous Backends的介绍以及总结反思。

项目主要目标:

  • 探索AWS的DBaas服务的申请、配置和管理
  • 比较MySQL, HBase和MongoDB在使用Java API载入数据时的异同。
  • 利用多个后端为同一个复杂的web应用提供数据。
  • 比较不同数据库在实际应用中的特点。

背景介绍

DBaas(Database-as-a-Services):

在AWS中,我们可以用其中的RDS的MySQL服务。

MongoDB:

MongoDB是NoSQL数据库的典型,基于文档存储(Document-oriented),不支持事务和表连接,所以查询的编写、理解和优化比较容易。之后会写一篇关于NoSQL的总结(一个坑)。 和HBase的key-value存储模式不同,MongoDB基于文档存储模式的优势在于可以支持复杂的数据类型,并且也支持Index。 MongoDB使用BSON类型存储数据,据说就是把文本直接转成二进制表示,BSON用于以下三种目的:

  • 节省空间:BSON即使在最坏的情况下,也比普通的JSON占用空间少。
  • 移动性
  • Performance:BSON对内容的编码和解码的速度快于很多编程语言。

数据结构: 图

1.邻接矩阵Adjacent Matrix:空间复杂度为O(n^2)

比如这个:

2.邻接表Adjacent List 空间较少:

社交网络应用基础:

如今像Facebook, Twitter和Instagram都需要复杂和涉及良好的后端来处理多种类型的用户数据,提供持续的高性能低延迟的服务。同时还要通过实时数据分析为公司和广告商提供有价值的信息。

  • 不同的数据类型(Video,Text,Link,etc.)需要存在不同的数据库中)
  • 一个简单的展示社交网络页面的HTTP请求会触发后端一系列的请求和数据库动作。可以参见下图:

社交网络中的数据通常包括以下三种:

  • 用户信息:
    • 身份验证系统
    • 用户信息/简介
    • 活动日志
    • 社交关系图(在下面会进步介绍)
  • 用户活动:
    • 用户产生的多媒体数据
  • 大数据分析系统:
    • 搜索系统
    • 推荐系统
    • 用户行为分析(基于云数据仓库的OLAP,有机会单独更新这个部分)

社交网络的前端已经做好,我们需要把四中不同的数据集存入三种数据库(MySQL, HBase, MongoDB),你完成的后端要能同时响应四中不同的request。

项目操作

通过RDS的MySQL实现基本登录:

在AWS RDS中配置MySQL并导入users.csv, userinfo.csv数据集。 连接AWS RDS中MySQL时注意: 远程登录需要导入数据时要加入 --local-infile得到授权。 mysql -u username -p password -h hostname --port=portname --local-infile database

数据集格式:

  • users.csv [UserID, Password]
  • userinfo.csv [UserID, Name, Profile Image URL]

导入MySQL语句: LOAD DATA LOCAL INFILE 'filename' INTO TABLE tablename CHARACTER SET utf8mb4 FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n';

请求格式: GET /task1?id=[UserID]&pwd=[Password]

响应格式: returnRes({"name":"my_name", "profile":"profile_image_url"})

所以,之后在Java文件中连接数据库,再创建JSON相应的代码即可。 测试:

  1. 启动前后端服务器,访问http://<your_front_end_dns>:3000
  2. 输入正确或错误的账号密码登录测试

利用HBase存储社交图谱:

用HBase来保存用户间的follow关系,可以选择用之前在图中介绍的邻接矩阵和邻接表中选择一种,来保存数据。 原始数据格式: <followee, follower>

请求格式: GET /task2?id=[UserID]

响应格式: {"followers":[{"name":"follower_name_1", "profile":"profile_image_url_1"}, {"name":"follower_name_2", "profile":"profile_image_url_2"}, ...]}

思路:

  • 在HBase中存成followee: follower1, follower2, ...的格式
  • 设计好HBase之后导入数据
  • 启动前后端服务器后访问http://<your_front_end_dns>:3000
  • 输入userid进行测试

用MongDB搭建主页:

如之前介绍的那样,对于各种形式的帖子,用MongoDB存储会是一个很好的选择。这里会查询一些特定的field,所以可以建立索引来加速查询。

帖子数据的形式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
"pid":xxx, // PostID
"uid":xxx, // UserID of poster
"name":"xxx", // User name of poster
"profile":"xxx", // Poster profile image URL
"timestamp":"YYYY-MM-DD HH:MM:SS", // When post is posted
"image":"xxx", // Post image
"content":"xxx", // Post text content
"comments":[ // comments json array
{
"uid":xxx, // UserID of commenter
"name":"xxx", // User name of commenter
"profile":"xxx", // Commenter profile image URL
"timestamp":"YYYY-MM-DD HH:MM:SS", // When comment is made
"content":"xxx" // Comment text content
},
{
"uid":xxx,
.......
},
......
]
}

关于MongoDB建立索引,可以参考这里

请求格式: GET /task3?id=[UserID]

响应格式: {"posts":[{post1_json}, {post2_json}, ...]}

测试方法:

  • 启动前后端服务器,输入userid

最终整合

之前三个部分分别实现了三个数据库的存储,现在我们希望实现输入一个userid就可以返回用户信息(MySQL),用户粉丝列表(HBase)以及用户关注的人最新三十条帖子(MongoDB)。

排序规则:

  • 对followers进行排序:
    • 姓名升序排列
    • Profile image URL升序排列
  • 对最新30篇post排序:
    • 按照timestamp升序排序
    • 按照PostID升序排序

请求格式: GET /task4?id=[UserID]

响应格式: {"name":"my_name", "profile":"my_profile_image_url", "followers":[{"name":"follower_name_1", "profile":"profile_image_url_1"}, {"name":"follower_name_2", "profile":"profile_image_url_2"}, ...], "posts":[{post1_json, post2_json, ...}]}

简单推荐的实现

推荐系统的内容太多了,可以看看shaung的博客(一个广告) 这次我们用协同过滤算法实现一个简单的推荐系统,利用“朋友的朋友”来推荐好友。

Graph Distance:

比如:

1
2
3
4
A follows {B, C, D}
Followee B follows {C, E, A}
followee C follows {F, G}
followee D follows {G, H}

我们可以得到与A的距离关系为: {A:1, C:1, E:1, F:1, G:2, H:1} 其中去掉A本身,去掉A已经关注的C,剩下的就是 {G: 2, E: 1, F: 1, H: 1}

思路:

  • 找到userid的关注的人的集合
  • 将关注的人的集合中的每个人关注的人添加到信集合中,第一次出现则为1,之后的为原来的加1
  • 用优先队列存储,注意第一个关注的人集合中的元素都不应该在此队列中
  • 返回前十个的name和url,并返回

请求格式: http://backend-public-dns:8080/MiniSite/task5?id=<user_id>

响应格式: returnRes({"recommendation":[{name:<name1>, profile:<profile1>},{name:<name2>, profile:<profile2>},...,{name:<name10>, profile:<profile10>]})

Done!

Reference:
CMU15619课件:Social Networking Timeline with Heterogeneous Backends 小土刀博客:http://wdxtub.com/vault/cc-17.html