V1.0
项目介绍
在直播平台中,用户在主播页面关注该主播时,粉丝状态栏下方插入三度关系推荐模块,显示关注了该主播的粉丝同时关注了哪些主播。按照推荐重合度且满足一定的筛选条件进行择优展示
数据采集
Flume(内部有ACK机制,确保数据不会丢失) / Logstash / FileBeat(基于go语言,性能消耗低)
在前端业务机器上部署Filebeat,将日志数据采集到消息队列里面(因为这个时候要求是尽可能少的占用服务器资源)。然后利用flume,使用其里面的拦截器将采集来的数据做一个粗处理。
数据采集模块流程图如下:
使用sqoop直连采集数据库中的数据
数据存储
计算框架计算的数据有一些是需要和前段交互的,这些数据前期可以选择存储到MySQL中。在维护用户三度关系数据的时候,如果使用普通的关系型数据库进行存储的话,会造成很多冗余,并且查询起来也很麻烦。所以使用图数据库。
Graphx (spark中) / Gelly (flink中)不能保存数据,不符合要求。
Neo4j对各种语言支持也比较好。官方提供的Connector插件,可以实现spark直接操作Neo4j
数据计算框架
使用spark去处理流式和批式的数据
数据展现
由Andriod和ios组完成即可,我们只需要将数据计算完存储起来即可
项目整体架构设计
- 第一个问题:针对实时计算,spark不是最优选择,最好使用flink。
- 第二个问题:对结果的存储MySQL也不是最优的选择,最好使用Redis
- 对于数据展现这一块,直接查询数据库中的内容也不是最优选择,最好是开发接口,堆外查询接口开发数据
Neo4j
Neo4j 介绍
Neo4j是一个高性能图数据库,其具备完全的事务特性,将结构化的数据存储在网络上而不是表中。
Neo4j 添加/查询数据
merge(a:User {name:'A'})
merge(b:User {name:'B'})
merge(a) -[:follow]-> (b)
match (:User {name:'B'}) <-[:follow]- (n:User) return n
match (n:User) -[:follow]-> (:User {name:'B'}) return n.name
match+return:查看满足条件的数据并返回
match(p:Person {name:'tom'}) return p
二度关系:
我 -> 主播B -> 粉丝
三度关系:
我 -> 主播B -> 粉丝 -> 主播N
match (a:User {name:'B'}) <-[:follow]- (b:User) -[:follow]-> (c:User) where c.name <> 'X' return c.name as cname, count(*) as sum order by desc limit 3
Neo4j 更新数据
更新节点的属性:match+set
match (a:User {name: 'X'}) set a.age = 18
更新节点之间的关系:match+delete
match (:User {name: 'A'}) -[r:follow]-> (:User {name: 'B'}) delete r
Neo4j 建立索引
普通索引 CREATE INDEX ON :User(name)
唯一约束 CREATE CONSTRAINT ON (u:User) ASSERT u.id IS UNIQUE
如果某个字段的值是唯一的,可以建立唯一约束,这个比索引的要更快
Neo4j 批量导入数据
- batch import: 需要组装三个文件,导入性能比load快
- load csv:只需要把数据组撞到一个CSV文件即可,用起来方便。但如果在load csv中使用了merge或者match时,需要确认关键字段是否有索引,否则性能会很差
针对关键字段建立索引:
create constraint on (user:User) assert user.uid is unique;
批量导入语句
using periodic commit 1000 //每1000条提交一次
load csv with headers from 'file:///follower_demo.log' as line fieldterminator '\t'
merge (viewer:User {uid: toString(line.fuid)})
merge (anchor:User {uid: toString(line.uid)})
merge (viewer) -[:follow]-> (anchor);