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 布局
目前社区已有多个场景接入计数核心,联合以后的现状及将来的可能性,思考后续次要优化方向次要有:
文 / 小夏