得物社区计数系统设计与实现
1.前言
1.1 社区数字场景
社区业务有非常多的数字统计场景,基础的场景主要有以下这些:
用户维度:发布内容数、被点赞数、被收藏数、关注数、粉丝数、点赞内容数、收藏内容数等。
内容维度:内容点赞数、内容阅读数、内容分享数、内容收藏数、内容评论数等。
标签维度:话题内容数、特效内容数、商品内容数、品牌内容数等。
其中部分场景还会有很多细分情况,例如内容相关的统计还会有以下场景:
- 根据内容类型统计:图文数、视频数、专栏数等。
这样排列组合出来的最终结果就有很多了,比如需要查询用户发布的图文内容数、用户点赞的视频内容数等等,且这些数字一般都需要能够支持高度精确性、高性能查询和批量查询等能力。
1.2 具体案例
具体案例可参考下列图示:
- 图1. 个人主页展示获赞与收藏总数、粉丝数、关注数、发布动态数(视频数、穿搭精选数、专栏数)。
- 图2. 他人主页展示获赞与收藏总数、粉丝数、关注数、点赞动态数(视频数、专栏数)。
- 图3. 话题主页展示话题内容数。
2.逐渐浮现的系统风险
2.1 历史方案
早期社区是直接采用Count数据表+缓存的方式,这种方式在体量较小和单体服务的情况下完全没问题,而且成本低、性能高、绝对精准,但随着社区的体量逐渐变大、微服务拆分越来越细之后,该方案就会越来越难以支撑业务。
2.2 系统风险
性能瓶颈和稳定性风险:
一方面业务明细表的体量越来越大,需要通过分库分表来解决问题,分库分表后再用Count聚合的方式性能就会变差。
另一方面业务统计规则越来越复杂,使用数据库Count的方式会使数据查询语句越来越复杂,容易引发慢SQL从而导致数据库不稳定。
计数业务数据层和缓存都和核心业务部分放在一起,若出现统计导致的不稳定会影响核心业务场景的使用,从而将小问题变成大问题。
缓存策略问题:
热点穿透问题:部分计数场景下是有新数据就删除缓存的策略,但若出现热点内容、热点用户时,对应的统计数据(如点赞数、粉丝数)会频繁删除缓存导致穿透的问题,且一般热点内容和用户产生的数据量比较大、查询量也比较大,会更容易加剧问题从而引发雪崩。
数据一致性问题:部分计数场景下是定时更新缓存的策略,缓存操作和MySQL操作无法在一个事务中完成,会产生不一致的问题,且在越频繁变更的场景下差异值就会越大。
3
计数系统设计与实现
结合当前社区的业务现状、体量以及考虑中长期体量增长的规划,我们也调研了业内比较常见的一些实现方案,最终敲定通过维护一套计数中心的服务,由计数中心服务统一管理社区的数字统计的方式,整体情况大致如下:
3.1 写场景
该场景下计数中心内部主要干三件事,主要包括数据获取、数据处理、数据持久化。
3.1.1 数据获取
数据的获取一般有两种方式,通过接口或通过MQ的方式,既然是平台服务更希望对业务没什么侵入性,因此我们目前采用的主要是MQ的方式。
使用MQ的情况下也有两种方案可取,一种是业务服务根据事件触发MQ消息,需要业务服务先保证业务数据已经持久化且需要生产端保证消息投递无丢失,另一种则是直接通过订阅业务数据表binlog的方式,这种方式可以保证业务数据已经持久化,目前得物已有DTS(数据订阅平台),使用起来也比较方便且可保证消息投递不丢失,因此我们目前更多的是采用第二种方案。
数据获取到后我们做一些格基础校验,验证是否存在我们必要的一些字段是否完整,同时需要验证数据处理的幂等性防止数据重复消费等,通过消息ID和业务唯一ID做幂等,然后把每行业务数据的各字段格式化成变更前和变更后俩个值且可以区分出是新增还是更新(binlog消息体就是这样因此更加方便),之后就可以进入数据处理阶段。
3.1.2 数据处理
拿到通过校验和格式化后的数据,根据对应的事件和规则来判断当前变更数据具体要做什么操作,我们通过具体的案例来看会更直观,如:
场景1. 用户A关注用户B
第一步,判断出该场景下需要变更的统计数,用户A的关注数要+1,用户B的粉丝数要+1。
第二步,提取需要变更的统计数的对象值,如用户A的ID和用户B的ID。
第三步,格式化成统计的格式,对象ID+统计类型+统计数变化值。
第四步,调用数据持久化的方法。
场景2. 用户A发布的图文内容状态由正常变为删除
第一步,判断出该场景下需要变更的统计数,用户A发布的图文内容数要-1。
第二步,提取需要变更的统计数的对象值,如用户A的ID。
第三步,格式化成统计的格式,对象ID+统计类型+统计数变化值。
第四步,调用数据持久化的方法。
3.1.3 数据持久化
持久化部分主要分为两块,一是DB持久化,二是对于缓存的更新。社区的数字统计场景主要有以下两种情况:
只增不减:如内容分享事件,每次事件触发只需要给内容的分享数+1即可。
既有增又有减:如用户A(关注/取消关注)用户B事件,需要给用户A关注数(+1/-1),也需要给用户B的粉丝数(+1/-1)。
又因为我们通过MQ消费数据是无序的,极端情况下可能会出现先减再加的情况从而导致负数的出现,因此存储层的字段需要支持有符号的数据,保证最终计算的结果是正确的即可。DB层持久完成后再直接操作缓存变更数字并延长有效期,若缓存不存在则不处理等待读场景有需要时再处理。
3.2 读场景
读场景整体逻辑比较简洁,就是先查缓存,缓存不存在就查询DB再写入缓存即可,可批量跨场景查询,需要注意对负数情况的处理。
4.总结及规划
4.1 总结
计数中心是业内比较常见的做法,相对于老方案能够降低各个业务对于复杂计数场景的维护成本,提升迭代效率和系统稳定性,独立出来后在出现异常时业务也可做短时间降级,从而降低对核心业务的影响面。
4.2 规划
目前社区已有多个场景接入计数中心,结合当前的现状及未来的可能性,考虑后续主要优化方向主要有:
文/小夏

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
一个简单的案例入门 gRPC
这篇文章本来要在年前和小伙伴们见面,但是因为我之前的 Mac 系统版本是 10.13.6,这个版本比较老,时至今天在运行一些新鲜玩意的时候有时候会有一些 BUG(例如运行最新版的 Nacos 等),运行 gRPC 的插件也有 BUG,代码总是生成有问题,但是因为系统升级是一个大事,所以一直等到过年放假,在家才慢慢折腾将 Mac 升级到目前的 13.1 版本,之前这些问题现在都没有了,gRPC 的案例现在也可以顺利跑起来了。 所以今天就来和小伙伴们简单聊一聊 gRPC。 1. 缘起 我为什么想写一篇 gRPC 的文章呢?其实本来我是想和小伙伴们梳理一下在微服务中都有哪些跨进城调用的方式,在梳理的过程中想到了 gRPC,发现还没写文章和小伙伴们聊过 gRPC,因此打算先来几篇文章和小伙伴们详细介绍一下 gRPC,然后再梳理微服务中的跨进程方案。 2. 什么是 gRPC 了解 gRPC 之前先来看看什么是 RPC。 RPC 全称是 Remote Procedure Call,中文一般译作远程过程调用。RPC 是一种进程间的通信模式,程序分布在不同的地址空间里。简单来说,就是两个进程之间互相调...
- 下一篇
开源轻量级前端显示框架LVGL简介
#01 LVGL简介 实用自行车码表 具有科技感的奖杯 实现这些DIY作品的背后,都有同样一个功能强大的GUI——LVGL。 LVGL的作者是来自匈牙利的Gabor Kiss-Vamosikisvegabor,LVGL用C语言编写,以实现最大的兼容性(与C ++兼容),模拟器可在没有嵌入式硬件的PC上启动嵌入式GUI设计,同时LVGL作为一个图形库,它自带着接近三十多种小工具可以供开发者使用。这些强大的构建块按钮搭配上带有非常丝滑的动画以及可以做到平滑滚动的高级图形,同时兼具着不高的配置要求以及开源属性,显著的优势使得LVGL蔚然成风,成为广大开发者在选择GUI时的第一选择。 -主要特性- 强大的构建块,如按钮,图表,列表,滑块,图像等。 高级图形动画,抗锯齿,不透明度,平滑滚动 各种输入设备,如触摸板、鼠标、键盘、编码器等 多语言支持与UTF-8编码 多显示器支持,即使用更多的TFT,单色显示器同时 完全可定制的图形元素与css类样式 硬件独立与任何微控制器或显示器使用 可扩展,使用少量内存(64kb Flash, 16kb RAM) 支持操作系统、外部内存和GPU,但不是必需的 单...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS7安装Docker,走上虚拟化容器引擎之路
- Linux系统CentOS6、CentOS7手动修改IP地址
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS关闭SELinux安全模块
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Hadoop3单机部署,实现最简伪集群
- CentOS6,7,8上安装Nginx,支持https2.0的开启