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+统计类型+统计变化值。第四步,调用数据持久化方法。场景二、用户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规划目前,社区内设有多个场景接入统计中心。考虑到目前的情况和未来的可能性,未来主要的优化方向是:文/小霞
