前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Feeds 系统简析 ---- 手Q游戏中心游戏圈

Feeds 系统简析 ---- 手Q游戏中心游戏圈

原创
作者头像
叫你不戴帽子
修改2023-03-14 14:24:18
1.4K0
修改2023-03-14 14:24:18
举报

项目背景介绍

游戏圈,是手Q游戏中心在社交化场景的一个探索和实践,将用户在游戏内的战绩、高光等事件作为动态展示在好友的 feeds 流列表中,产品形态上类似微信朋友圈、QQ 空间、推特等。

整体交互上就是用户产生游戏高光(发动态),好友进入动态 feeds 列表按照时间线查看。

先分享下我们业务的一些数据:feeds 发表峰值(写)大约是在 x k/s 左右,日发表量约在 xkw,活跃用户大约 x 亿,单条 feeds 约 900B,每个用户存最近 x 条,大约需要 5T 存储;好友 feeds 流时间线拉取(读)峰值大约在 xk/s。

技术方案

社交 feeds 型的产品,绕不开的挑战是:

  1. 读写方案选型。
  2. 海量 feeds 存储选型。

读写方案选型

业界几款明星产品的选型:

QQ 空间

读扩散

微信朋友圈

写扩散

新浪微博

读写扩散

twitter

写扩散

facebook

读扩散

读扩散:只有发件箱。优点是写简单、省存储、feeds 策略更灵活(例如支持多种关系链);缺点是读逻辑实现复杂且存储读扩散压力大。

写扩散:有发件箱和收件箱。优点是读简单,缺点是费存储、写复杂(合并写)、大V关系链下扩散慢,延迟高。

读写扩散:本质还是写扩散。大V用读扩散加速拉取。

架构选择上没有银弹,具体选型还是要结合业务的场景选择。以我们业务为例,选择读扩散,主要考虑:

  1. 产品和游戏侧强关联,未来有接入多种关系链的可能(游戏好友等)。
  2. 公司大背景,降本增效,写扩散,沉默用户和低活用户太费存储和计算资源了。
  3. 关系链权限风险。很多数据走游戏流水接入,无登录态或互联登录态,权限层级上无法获取手Q侧关系链数据(低权限换高权限,违反规则)。

存储选型

存储诉求:1是要支持海量存储,10T级别,最好是分布式的,可动态扩容;2是要支持高并发的访问,业务侧估算,xk/s 的 feeds 流拉取,平均每个活跃用户有 xxx 好友,对存储层压力在 64w/s 左右;3是要上云。

结合如上诉求,可选的就这2个:Mongo 分片集群、Tendis/keewidb。

Mongo 的特点是:

  1. 分布式分表,扩容、迁移业务无感。
  2. 性能较好,云上6核16G规格,大约单片支持 5w/s(参见腾讯云产品文档)。
  3. 数据 schema 可动态扩展,业务友好。
  4. bson 存储,略费存储。10T存储每月成本 xx 万左右。

Tendis/Keewidb 简而言之就是支持大容量的降冷版的 redis,特点如下:

  1. 分布式,扩容、迁移业务无感。
  2. 数据读写性能高,热门数据单分片大约支持 10w/s 左右的读写。
  3. 不支持部分字段读取(例如某个用户近10条 feeds 等),kv 长度最大不能超过 16MB。
  4. 数据 key 无法降冷,占用内存。也就是说如果采用 feedid 作为 key,key 数量会极为庞大,内存中基本全是 key,热门内容的缓存效果会大打折扣。
  5. 成本较高,10T存储每月 xx 万左右。

综上来说,我们选择了 mongo 集群作为存储方案,单用户单条 feeds 为一条记录。

整体架构

实现细节

TimeFeeds 流

用户进入动态页,按照时间顺序展示好友的 feeds 列表。采用读扩散的方案,先拉取好友列表,再拉取好友的 feeds 记录统一排序返回页面,每页展示10条动态。

参考QQ空间的实现方案,为了减轻读扩散对存储层的压力,游戏圈主要采用如下两种策略:

1. Redis 时间索引

Redis 记录所有用户最近发表 feeds 的时间戳。首页拉取时,以当前时间为基准,根据 redis 时间索引只拉取最近的10个好友的10条 feeds;翻页时,以上一页的最后一条 feeds 时间为基准,找到基准时间最近的10个好友,加上前一页展示的所有好友,拉取这些好友的基准时间前发表的10条 feeds,排序后返回。

缺陷很明显:越往后翻页,查好友数量越多,拉取速度越慢。但是按照统计数据来说,超过 90% 的用户都是只看第一页,因此问题不是很严重。

2. 缓存

那针对这 10% 的活跃用户,我们有办法进行优化吗?作为开发人员,我们要有精益求精,极致优化的追求。

方案就是叠加缓存,我们知道时间是单向流逝的。因此,用户 a 在时间 t0~t1 内看到的 feeds 应该说是固定的,不管用户是在 t2、t3、t4 进来查看,只要查看的时间区间是 t0~t1 那就是同一份数据。基于这个原因,我们可以额外做缓存优化。

具体来说,就是用户每次进入页面,我们将当前计算好的 feeds 列表缓存在 mongo 中(只缓存最近10页),下次用户进入页面时,计算增量的 feeds 列表,然后合并到 feeds 列表缓存中去。这样,用户特定时间区间内的 feeds 列表只会计算1次。

当然,这种策略更复杂,也会有额外的存储消耗,我们可以做进一步优化。

  1. 针对缓存列表增加过期时间,例如5天,保证缓存不会单调增长。
  2. 针对用户进行分级,例如产品高活用户,走这种策略缓存计算和加载;低活用户,一般只看首页内容,则不进入缓存机制。

Feeds 超长清理

手Q游戏中心,毕竟不是一个 feeds 流的产品形态,只是希望展示用户最近的好友动态。因此产品策略上,对 feeds 的保留时间做了限制,每个用户只保留最近 N 条。

我们采用的方案是:在业务谷期,对 feeds 存储离线扫描;同时为了减少离线扫描的数量,用咆哮位图记录每天发表过 feeds 的用户;同时做了读写分离和合并查询,提升扫描速度。

性能优化

上线后,发现服务器 CPU 消耗较多,Perf 后发现大多数在 gc 上。

我们用 Sync.Pool 复用了大多数网络 IO 过程中的临时对象,优化后CPU 降低了 18%,gc 耗时也降低了很多。

线上 Mongo 高负载优化

现象

线上 Mongo 集群经常出现尖峰,峰值期间业务访问质量大受影响。

原因

定位后发现,毛刺是由于业务服务和 Mongos 实例链接断掉后,短时间内大批量新建链接引起的。上游调用下来超时时间800ms。db 高负载时,由于800ms内无法响应,driver 认为出错,直接关闭链接,重新新起链接去查,新链接在 800ms 内无法建立,导致driver 不停地关闭、重建新链接;导致雪崩的出现。

业务侧设置每台实例 maxPoolSize=minPoolSize=15。

代码语言:txt
复制
1. 线上 Mongod 集群高负载,偶尔出现一些超时慢查询,超过 800ms。
2. 业务使用连接池访问,高负载时链接访问1s超时了,导致链接被释放。
3. 连接池监控发现链接不够了,新起链接去 mongos,同样 1s 超时释放超时连接。
4. 后面反复这个流程,导致1分钟内不停的创建新链接,达到13w/min,引起雪崩。

解决方案

  1. Mongo 集群设置 relance.window 时间窗口为 3:00~8:00,避免平时 rebalance 影响。
  2. Mongo driver 断掉上游的 ctx,新起新的 ctx 超时3s去访问 db。避免上游 ctx 结束导致建立中的链接不停失败。上游可以失败,但是链接要保持住不要重连。

效果

调整完之后业务侧已经不受影响,慢查询数量从 3.5k/min 降低到 300/min 即时偶尔有超时,也不会产生雪崩效应。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 项目背景介绍
  • 技术方案
    • 读写方案选型
      • 存储选型
      • 整体架构
      • 实现细节
        • TimeFeeds 流
          • 1. Redis 时间索引
          • 2. 缓存
        • Feeds 超长清理
          • 性能优化
          • 线上 Mongo 高负载优化
            • 现象
              • 原因
                • 解决方案
                  • 效果
                  相关产品与服务
                  云数据库 MongoDB
                  腾讯云数据库 MongoDB(TencentDB for MongoDB)是腾讯云基于全球广受欢迎的 MongoDB 打造的高性能 NoSQL 数据库,100%完全兼容 MongoDB 协议,支持跨文档事务,提供稳定丰富的监控管理,弹性可扩展、自动容灾,适用于文档型数据库场景,您无需自建灾备体系及控制管理系统。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档