# feed **Repository Path**: qian/feed ## Basic Information - **Project Name**: feed - **Description**: feed流 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2020-07-13 - **Last Updated**: 2023-11-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # feed流服务设计 简单的feed流服务设计 ## 一. 实现业务目标 - 要有用户之间的关注关系 - db如何设计 - 是否要使用redis,如何使用 - 尽量保证高性能 - 尽量保证高可用 - 类似微博那样的数据流实现 ## 二. 设计思路 逻辑实现图: ![image](./static/feed.png) 系统实现: ## 三. 数据库和队列实现 ### 1.数据库构建 1. 用户表 (用户uid,用户名称) 2. 信息表 (信息id,发布时间,发布人,接收人,发送图集,内容)**暂时不做拆分** 3. feed流表 (信息id,发布时间,接收人,接受状态) 4. 用户关注表 (用户uid,被关注uid, 好友时间,状态) 数据库结构: ``` //用户表 CREATE TABLE `user` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `uid` varchar(32) NOT NULL COMMENT '用户uid', `name` varchar(128) NOT NULL COMMENT '用户姓名', `create_time` timestamp NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`), KEY `uid` (`uid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表'; //信息表 CREATE TABLE `dynamic` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '信息id', `uid` varchar(32) NOT NULL, `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '发布动态时间', `images` text COMMENT '序列化图集', `content` text, `localtion` varchar(255) DEFAULT NULL COMMENT '发送信息定位经纬度', `star` int(11) unsigned DEFAULT '0' COMMENT '点赞数', PRIMARY KEY (`id`), KEY `uid` (`uid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户发布动态表'; //关注信息表 CREATE TABLE `follow` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `follow_uid` int(11) DEFAULT NULL COMMENT '关注者uid', `uid` varchar(32) DEFAULT NULL COMMENT '被关注者uid', `create_time` int(11) DEFAULT '0' COMMENT '关注时间', PRIMARY KEY (`id`), KEY `follow_uid` (`follow_uid`), KEY `uid` (`uid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='关注信息表'; //推流表 CREATE TABLE `feed` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `dynamic_id` int(11) unsigned NOT NULL COMMENT '信息id', `uid` int(11) NOT NULL COMMENT '信息发布者', `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `expire_time` int(11) NOT NULL COMMENT '任务超时时间', `status` tinyint(4) DEFAULT '1' COMMENT '任务状态:1待发送,2发送中,3已完成,4已失败', PRIMARY KEY (`id`), KEY `dynamic_id` (`dynamic_id`), KEY `uid` (`uid`), KEY `expire_time` (`expire_time`), KEY `status` (`status`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='推流id'; //推流表日志 CREATE TABLE `feed_log` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `feed_id` int(11) unsigned NOT NULL COMMENT '推送id', `dynamic_id` int(11) unsigned NOT NULL, `send_uid` varchar(32) NOT NULL COMMENT '发送者id', `receive_uid` varchar(32) NOT NULL COMMENT '接收者id', `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='feed 日志表'; ``` ### 2.redis #### 2.1 异步队列 - 用户发送消息,信息id加入队列,异步程序推送 | key | value | desc | | ---- | ---- | ---- | | dynamic-add | {id:[信息id],uid:[发布者uid]} | 用户发布信息事件队列 | | watch-dynamic-add | {id:[信息id],uid:[发布者uid]} | 用户发布信息事件队列监听列表 | #### 2.2 用户推送列表 | key | value | desc | | ---- | ---- | ---- | | feed-user:[uid] | 信息id | 关注者feed列表 | | feed-list:[feed_id] | feed任务id | 某任务推送到所有关注人列表 | ### 3.推流信息存储 - 如果粉丝较多,选取活跃用户推送,其他用户拉取 - 粉丝量少的用推 - 粉丝量特别大的大V,需要用到大数据存储,暂时不考虑此情况 - 推流过程中,信息被删除,需要停止发送, 已推送用户的,需要设置为已删除状态 ## 四.代码实现 > 暂时不使用框架,只实现文件架构和伪代码 #### 1. 应用结构 app设置2个client - front 为用户发布信息 - feedService 为后端推送服务 #### 2. 步骤流程: 1. 用户请求 front/api/dynamic/add 2. 成功后触发事件,user.dynamic.add,将次消息加入redis队列 3. feedService通过queue.php脚本去读取队列,运行FeedLogic::add方法。 4. FeedLogic方法在非dav情况下,批量插入log日志,完成后标识状态,否在报警和修复 5. front端通过 front/api/dynamic/get 和pull 去获取或者拉去队列中的动态显示, 次接口通过rpc接口从后端获取动态id后读出相应的数据 #### 3. feedService 后端接口 feedService服务提供 3个rpc方法: - add 增加一条推送 - get 获取用户推送 - pull 从队列拉去 > 请求方式:rpc
请求service :feedService - add 方法参数 字段 |字段类型 |字段说明 ------------|-----------|----------- dynamicId |int |信息id 返回结果:bool - get 方法参数 字段 |字段类型 |字段说明 ------------|-----------|----------- uid |string |token值 page |int |页数,默认1 limit |int |每页数量,默认10 返回结果:dynamic_id数组 - pull 方法参数 字段 |字段类型 |字段说明 ------------|-----------|----------- uid |string |token值 limit |int |拉去数量,默认10 返回结果:dynamic_id数组 后端主逻辑代码: app\feedService\logic\FeedLogic ## 五.其他 ### 1.高性能 用户发布信息后,触发异步消息,后端脚本监听消息,发送到后端推送服务 ### 2.高可用 - 推送前讲信息状态设置为推送中,推送记录日志。 - 服务在完成推送后,将结果回填到消息数据库,完成推送,发送失败的同样计入本地存储。 - 定时扫描失败任务,和推送中超时的任务,执行检测修复和报警 - 后端推送服务注册到服务中心,通过监测系统cpu,io等参数,设置服务自动伸缩机制。 ### 3.数据流的实现 简易版的粉丝数量较少的可用mysql,记录推送关系,消息按日期分表。发送一条信息,找出关注用户列表进行推送,即写入一条记录 粉丝量较多情况下,建立关注者redis列表,根据活跃度算法(目前以最近关注的优先,后期优化),设置权重,进行部分推送和关注者拉取结合