同步操作将从 Xhy/lucky-journey 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
幸运日是一款短视频平台,拥有热度排行榜,热门视频,兴趣推送,关注推送,内容审核等功能
👍 教学地址
👍 项目地址 项目地址防止刷流量,已关闭
注意:该项目技术选型,方案实现,是基于当前项目体量以及实际场景选择,避免过度设计,增加服务器成本,开发成本,运营成本。优化地方下面会提出
前端 - 刘顺顺
负责设计实现前端所有模块的页面和交互
技术选型:
vite + vue3 + axios + pina + router + vuetifyUI + videojs + 七牛云sdk
后端 - 胡展鸿
负责设计实现后端所有模块
技术选型:
Jdk1.8 + SpringBoot + MyBatis + MySql + Redis + 七牛云存储 + 七牛云审核 + 七牛云转码 + 七牛云回源鉴权
后端
1.将docs中sql文件导入
2.配置参数: MySql数据源,redis数据源,邮箱参数,七牛云参数,七牛云CNAME
3.配置七牛云回源鉴权相关参数
4.配置系统配置表白名单(放行资源),回源鉴权开关
后台管理地址:http://localhost:8882/page/login.html
前端
本地启动
1.进入front-end文件夹
2.vite.config.js 更改proxy服务为后端的正确ip:port/luckyjourney
3.执行 yarn
下载依赖
4.执行 yarn dev
运行dev项目
5.访问: http://127.0.0.1:5378/#/ 可查看前端项目。
部署
准备 Node.js v16.15.1 环境
1.进入front-end文件夹
3.执行 yarn
下载依赖
4.执行 yarn build
构建项目
5.搭建nginx环境:nginx 1.22
6.将构建好的前端项目部署到nginx
7.配置反向代理:http://127.0.0.1:8882/luckyjourney/ 更改为自己的后端服务地址
#PROXY-START/
location ^~ /api/
{
proxy_pass http://127.0.0.1:8882/luckyjourney/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_http_version 1.1;
# proxy_hide_header Upgrade;
add_header X-Cache $upstream_cache_status;
#Set Nginx Cache
set $static_filegKiLSCbO 0;
if ( $uri ~* "\.(gif|png|jpg|css|js|woff|woff2)$" )
{
set $static_filegKiLSCbO 1;
expires 1m;
}
if ( $static_filegKiLSCbO = 0 )
{
add_header Cache-Control no-cache;
}
}
#PROXY-END/
登录/注册
首页
视频播放(可滚动播放),右侧是视频详情以及 相似视频推送
创作中心
用户可对TA人进行关注/粉丝,关注后即可在关注推送TA人的视频,取关后取消推送
用户可对视频进行收藏管理
注:用户注册后生成默认收藏夹,不可删除
用户所刷的视频将保存在此为5天
用户可订阅感兴趣的分类,后续在推荐页中可被推荐更多相似视频
视频存储在云端,需要被保护,用到了七牛云的回源鉴权
流程
1.获取资源请求服务器
2.服务器判断当前请求referer是否包含在系统白名单内
3.1.不包含 403 END
3.2.包含
4.生成UUID TTL:8秒 放入caffeine中并且拼接url
5.重定向七牛云资源
6.七牛云转发鉴权服务
7.鉴权服务校验是否合法
用户
用户在订阅分类后,可进行相似推送
游客
随机分类推送
设计
每个分类拥有默认标签,每个视频可拥有最多5个标签,用户订阅分类后,实际是订阅了分类后的标签,将标签概率分布,后续兴趣推送则获取用户的标签,进行随机概率获取推送视频。浏览停留时长,点赞,收藏行为将对对应的标签概率进行增减
系统标签库
数据结构:
Set ttl: -1
key: system:stock: + 标签id
value: 视频ids
用户模型库
数据结构:
Map ttl: -1
key: user:model: + 用户id
value :
key: 标签id
value: 概率
流程
1.用户订阅分类后取出分类后的默认标签,标签数/100 得到同等概率,存到用户模型库
2.用户在 视频停留时长/点赞/收藏 将对该视频下的所有标签拿到 模型库中进行增长/缩减 ,每次增长后需要同等比缩小概率,防止概率膨胀
3.推送视频时获取用户的模型库,将其组装为数组,下标为labelId,随机数取数组长度,获取videoId,并和浏览记录去重,再根据用户性别标签获取视频,封装数据后返回,这里可能会推送很少的视频,不要紧
4.前端拉取推荐视频根据上一次推送视频集合的阈值拉取,例如集合扩容机制
推送流程图
数据结构:
Set ttl: 3天
key: hot:video
value: hotVideo
设计
每隔3个小时 切片快速分页扫描全表 ,每个视频计算热度值后和系统配置表的热度值做比对,小于则放入热门视频
推送:
热门视频属于随机推送且下拉获取新视频,不需要分页,如果出现相似视频则说明是数据量不够大
根据视频的热度进行排行
设计
热度 = 权重 和时差的计算
权重 = 点赞,浏览,分享,收藏对应的占比例
时差:当前时间 - 视频发布时间的差值
A视频24小时内点赞到了1W,B视频1小时内点赞到了1W,则说明B视频热度更高
这里可以采用半衰期公式计算热度
总结可以理解为 当前时间 - 视频发布时间 差值为x ,x越小y越大,x越大y越小 后 对应的权重 得到热度
数据结构:
Zset ttl: -1
key:hot:rank
value: videoId
socore: 热度
每隔1个小时切片快速分页扫描全表,每个视频计算热度值后放入有界的小根堆,遍历完成再放入Redis -> TopK问题
推送关注人发送的视频 -> feed流
设计
用户拥有发件箱和收件箱
发件箱
用户所发布的视频存储在发件箱
数据结构:
Zset ttl:-1
key: out:follow:feed: + 用户id
value: 视频id
Score: 视频发布时间
收件箱
存储用户关注人的视频
数据结构:
Zset ttl:5天
key:in:follow:feed: + 用户id
value: 视频id
score: 视频发布时间
流程
1.用户发布视频后,将视频异步发送到发件箱
2.用户上线后异步获取关注流:
2.1关注流为空,则拉取关注人7天之内的视频
2.2不为空,则拉取收件箱最新视频的时间 - 当前时间内关注人的视频并存入收件箱
3.用户删除视频将异步删除发件箱视频,以及粉丝内的收件箱视频
4.用户拉取关注流根据滚动分页获取
推拉模式的选择是需要根据当前项目的数据体量决定的。当前项目体量不大,选择拉模式且设置ttl,过滤不活跃粉丝
收件箱初始化
拉取关注视频
根据分类随机推送视频,不需要分页,不需要去重,因数据量少
一切的设计实现都要考虑当前项目的因素落地
审核中台可自定义放行比例以及设置是否开启审核
设计
AuditService: 规定审核标准,规定入参返回值 <T,R>
AbstractAuditService: 封装统一逻辑 : 比较得分,获取消息,返回对应审核状态(策略模式)
ImageAuditService: 图片审核
TextAuditService: 内容审核
VideoAuditService: 视频审核
VideoPublishAuditServiceImpl: 发布视频审核设计
使用RBAC实现权限模块,超级管理员可自行分配角色
系统配置中配置了审核力度、审核开关、热门视频热度限制、白名单
可对视频进行下架审核处理
可管理首页的分类
当前项目为单体架构,为什么没考虑微服务如下:
1.个人认为无论是实际项目还是比赛,不以 实际解决问题出发而引入某些技术就是在炫技 ,无非是增加了开发成本,运维成本等。例如:不考虑用户体量的场景下就做分库表,引入ES做搜索,MQ做异步解耦
架构改进如下:
1.视频服务
2.用户服务
3.评论服务
评论服务抽出来是考虑到后续产品会出 动态 功能,因此将评论服务抽出来
4.点赞收藏浏览分享服务
该服务考虑到后续可能会有对视频,动态,评论等有操作
5.审核中台
6.鉴权服务
用于对资源的保护
7.网关
路由请求转发
在项目中大量使用了线程解耦,实际引入MQ
项目中Redis有一个分类库,用于存储所有的视频达到随机推送视频,且ttl为-1,项目中未做分片,会造成大key
分片设计
1.每个分类维护一个分片id,且限制分片id最大存储X条数据。 数据结构String key: 分类id value: 自增id
2.系统启动时将分片id存储本地缓存
3.存储视频时,先判断对应分类中的数量是否达到限制
3.1.未达到 - 跳到4 3.2.达到限制 - 将本地缓存自增1,异步修改Redis对应分类id 跳到4
4.获取本地缓存对应分类id
5.取对应id内的随机数,达到分片获取数据。如果想避免数据倾斜(随机数很旧,获取视频不是最新),可指定具体id进行获取数据
当前项目中是以拉模式实现,用户上线后拉取内容且设置ttl。这里应该做成推拉模式,用户发布一个视频后,推送到活跃用户的收件箱
这里的设计是考虑了项目体量决定
对象存储在项目中是将和资源相关暴露给了前端,实际该尽可能减少暴露
设计
1.设计文件表,用于管理所有的文件
2.视频表关联文件表, file_id = file_key
3.获取资源时根据file_id从文件表中查询file_key进行重定向
4.鉴权...
在项目中审核的设计为嵌入式服务,应该将其抽出改为单独服务,并且提供更多的信息
分享未做短链接,实际应该做短链接处理,存储视频信息,用户信息等
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。