直播平台三度关系推荐系统

369 阅读3分钟

V1.0

项目介绍

在直播平台中,用户在主播页面关注该主播时,粉丝状态栏下方插入三度关系推荐模块,显示关注了该主播的粉丝同时关注了哪些主播。按照推荐重合度且满足一定的筛选条件进行择优展示

数据采集

Flume(内部有ACK机制,确保数据不会丢失) / Logstash / FileBeat(基于go语言,性能消耗低)

在前端业务机器上部署Filebeat,将日志数据采集到消息队列里面(因为这个时候要求是尽可能少的占用服务器资源)。然后利用flume,使用其里面的拦截器将采集来的数据做一个粗处理。

数据采集模块流程图如下:

Screenshot 2022-09-05 at 2.48.14 PM.png

使用sqoop直连采集数据库中的数据

数据存储

计算框架计算的数据有一些是需要和前段交互的,这些数据前期可以选择存储到MySQL中。在维护用户三度关系数据的时候,如果使用普通的关系型数据库进行存储的话,会造成很多冗余,并且查询起来也很麻烦。所以使用图数据库。

Graphx (spark中) / Gelly (flink中)不能保存数据,不符合要求。

Screenshot 2022-09-05 at 2.54.30 PM.png

Neo4j对各种语言支持也比较好。官方提供的Connector插件,可以实现spark直接操作Neo4j

数据计算框架

使用spark去处理流式和批式的数据

数据展现

由Andriod和ios组完成即可,我们只需要将数据计算完存储起来即可

项目整体架构设计

Screenshot 2022-09-05 at 2.59.32 PM.png

  • 第一个问题:针对实时计算,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);

数据采集模块

Screenshot 2022-09-05 at 7.26.10 PM.png