天天看点

小红书-2022冬奥活动总结

文章目录

  • ​​一、业务介绍‍‪‭‪‪‬⁣​​
  • ​​二、技术‪‭‪‪‬⁣实现​​
  • ​​1、总览‍‪‭‪‪‬⁣​​
  • ​​2、监控‍‪‭‪‪‬⁣​​
  • ​​2.1 业务指标监控​​
  • ​​2.2 技术指标监控​​
  • ​​2.3 数据逻辑巡检​​
  • ​​2.4 异常监控‍‪‭‪‪‬⁣​​
  • ​​3、赛程/金牌榜信息‍‪‭‪‪‬⁣​​
  • ​​4、任务完成‍‪‭‪‪‬⁣入账​​
  • ​​5、数据藏品兑换‍‪‭‪‪‬⁣​​
  • ​​6、数字藏品兑换模拟‍‪‭‪‪‬⁣​​
  • ​​7、前端兜底配置‍‪‭‪‪‬⁣​​
  • ​​三、团队协作​​
  • ​​1. 会议需要主持人​​
  • ​​2. 多部门的信息及时交流​​
  • ​​四、回顾总结‍‪‭‪‪‬⁣​​

一、业务介绍‍‪​‭‪‪‬⁣

引用自产品文档:

结合冬奥营销节点,抓准冬奥期间国民对于冰雪运动的高关注度,主打小红书的内容差异化优势,在11月底-2月初期间,产出一系列品牌传播物料,并进行线上线下的整合营销活动,对外构建“玩冰雪,上小红书”的品牌认知,提升运动垂直人群对小红书的好感度,全网用户对小红书运动的认知度。

二、技术‪​‭‪‪‬⁣实现

(以下只提一些有意思的点,而不会全盘介绍整个技术实现内容,纯业务内容也没啥好介绍)

1、总览‍‪​‭‪‪‬⁣

小红书-2022冬奥活动总结

1.1 技术调研

  • 确定某些功能设计能否实现、如何实现、耗时多少。比如要在app端搞个冬奥活动的挂件,因为当前没有现成或者类似的,所以就要和客户端团队聊聊能不能实现。‍‪​‭‪‪‬⁣
  • 和依赖方确认,能否抗住冬奥带来的新增流量。比如冬奥活动页面需要查询笔记信息,那么需要和笔记团队确认,新增的这部分活动流量能否支撑的住。‍‪​‭‪‪‬⁣

1.2 技术方案设计

在这个环节,需要很细致的把所有需要开发的功能点都罗列出来,针对每个功能点,需要:技术实现方案、流程图、风险点等等。

之所以要做的这么细致,主要原因是活动很重要,所以务必要把该考虑的地方都考虑到,避免开发中返工耽误进度,或者上线出问题;次要原因则是,在技术评审时,众多大佬在场,不能出纰漏。

1.3 技术评审

这个环节就是众多大佬在场,一起审验你的技术方案是否完善,风险点处理是否妥当。

在评审之前,技术方案最好就要做的完善点,到了评审上,就基本不要出问题了,毕竟大佬当面,留下坏印象可不好。

1.4 资源评估与保障

  • 自己:评估下qps大概是多少,需要多少机器资源‍‪​‭‪‪‬⁣
  • 依赖方:‍‪​‭‪‪‬⁣
  • mysql、redis等存储服务:具体到每个sql和操作指令,数据量是多少、qps是多少,需要申请什么配置(是否使用读写分离,要多少实例等)‍‪​‭‪‪‬⁣
  • 第三方应用服务:冬奥流量下,需要增加多少机器配置才能扛得住‍‪​‭‪‪‬⁣

因为临近春节,一来大家都在做活动,对于云服务器的需求比较旺盛,二来因为过年放假,云服务的人也放假去了,所以量大的机器资源要在过年前提前敲定好,最好不要临时去采购。

2、监控‍‪​‭‪‪‬⁣

2.1 业务指标监控

专门建了一个报数群,定时播报业务指标信息,样例如下:

奖品兑换情况:‍‪‭‪‪‬⁣
抽奖券: 前15分钟兑换x, 总兑换:xxx‍‪‭‪‪‬⁣
数字藏品: 前15分钟兑换x,      

为什么要专门创建一个群,在群里播报消息,而不是给每个人单独发消息?

主要是因为,如果对于数据有问题,那么相关人员可以直接在群里就地讨论,但是给每个人单发消息的话,就没有这么方便了。

2.2 技术指标监控

需要监控的技术指标,比如每个表的数据量‍‪​‭‪‪‬⁣、接口qps等等

这个直接私发给所有开发人员的,示例如下:

[2022-02-21 00:05:01] 数据库表数据量统计‍‪‭‪‪‬⁣
--olympics_xxxx:  xxxx‍‪‭‪‪‬⁣
--olympics_xxxx:  xxxx‍‪‭‪‪‬⁣
--olympics_xxxx:  xxxx‍‪‭‪‪‬⁣
[2022-02-21 00:05:03]      

主要作用是为了在技术侧,对业务发展进度心里有个谱,防止出现业务发展太快,当前的技术设计无法支撑的情况。

次要作用,则是做汇报的时候挑些好看的数据装逼用(装逼是人类的永恒需求)。

2.3 数据逻辑巡检

主要作用是校验数据逻辑的正确性,及时发现问题并修正‍‪​‭‪‪‬⁣,比如检测用户账户的碎片总额,与任务完成明细是否匹配等。

示例如下:

[2022-02-21 00:41:41] 累计获取碎片数与任务完成明细不一致的用户数:xxx‍‪‭‪‪‬⁣
用户采样:[xxxx]‍‪‭‪‪‬⁣      

(ps:实际业务运行中,这个数据逻辑巡检,确实也发现存在数据不匹配的异常情况,还好影响范围不大)

2.4 异常监控‍‪​‭‪‪‬⁣

在关键逻辑(比如任务完成入账)出现异常时,直接企微消息发送异常信息给相关人员(不过要控制频率,不要就成信息轰炸了)。

主要目的,是为了在关键逻辑出现异常时,能更快速的感知并排查、修复。在实际业务运行过程中,也确实发现了一些奇奇怪怪的问题,还好影响都不大。

示例如下:

冬奥活动异常通知:‍‪‭‪‪‬⁣
--异常类型:xxxx‍‪‭‪‪‬⁣
--异常次数:xxxx‍‪‭‪‪‬⁣
--异常信息:xxxx‍‪‭‪‪‬⁣
--上次触发异常时间:yyyy-MM-dd HH🇲🇲ss‍‪‭‪‪‬⁣      

3、赛程/金牌榜信息‍‪​‭‪‪‬⁣

这部分数据是和第三方平台直播吧对接,从直播吧获取数据的。采用的方案如下:

小红书-2022冬奥活动总结

‍‪​‭‪‪‬

为什么使用redis缓存?为了与第三方服务不做强依赖。

直接从直播吧查询并返回,如果直播吧挂了,那我们岂不是也要凉凉?风险太高。

作为程序猿,公司里的自己人都要抱着怀疑的态度去审视,更别说这种外部公司提供的数据接口了。

在实际运行过程中,与直播吧的交互确实也暴露出两个问题:

  • 后期时,直播吧接口偶尔会出现调不通的情况‍‪​‭‪‪‬⁣
  • 在冬奥最后一天时,直播吧那边数据下线比小红书这边冬奥活动定的时间更早‍‪​‭‪‪‬,他们提前下线查不到数据了⁣

4、任务完成‍‪​‭‪‪‬⁣入账

小红书-2022冬奥活动总结

后端记录任务完成与奖励入账,一共需要用到两把锁,依次加锁,然后再逆序解锁。

  • 用户-任务关联锁:避免并发情况下,用户重复完成任务。虽然从业务流程上来讲,重复完成任务应该不存在,但是实际上,因为网络延迟、前端逻辑等,在后端是可以监控到少量重复任务完成请求的。‍‪​‭‪‪‬⁣
  • 用户账户锁:避免对用户账户进行并发更改,导致数据错乱。用户兑换奖品等业务场景,也会影响到到用户账户碎片总额的变化,因此在这些场景中,也都必须要获得用户锁之后才能对账户进行操作。‍‪​‭‪‪‬⁣

5、数据藏品兑换‍‪​‭‪‪‬⁣

小红书-2022冬奥活动总结

5.1 为啥要先扣总额,再去领取数字藏品?‍‪‭‪‪‬⁣

因为领取数字藏品这个操作,是调用第三方服务的,无法回滚,但是总额扣减是数据库操作,可以在数字藏品领取失败后回滚。

5.2 为什么不用藏品锁?‍‪‭‪‪‬⁣

  • 数字藏品的库存总额,都是提前配置好保存在redis中,而不是每次从第三方接口中查询。‍‪​‭‪‪‬⁣
  • 数字藏品的库存是一定满足用户领取需求的,所以在设计方案时,可以直接先redis扣减库存,如果库存不足或者调用第三方接口失败,就把扣减的库存加回去就好了(库存加回去失败了怎么办?可以承受一定限度的浪费,所以问题不大)。‍‪​‭‪‪‬⁣
  • 为什么不采用藏品锁的方案?如果采用藏品锁,每个藏品一把锁,那么藏品兑换的并发度就要受限,在高峰期可能很多人都兑换不了,如果一个藏品多把锁,并发度的问题倒是能解决一些,但是复杂了。综合看下来,就把藏品锁的方案pass了。‍‪​‭‪‪‬⁣
  • 为什么不先查询库存总额,判断是否有库存,再进行扣减,而是使用decrBy,发现库存不够还要再加回去?要保证库存扣减是个原子操作,不然可能存在查询到是有库存的,但是扣减的时候已经没库存了。‍‪​‭‪‪‬⁣

6、数字藏品兑换模拟‍‪​‭‪‪‬⁣

数字藏品氛围精品款和基础款,精品款的发放会受到掉率和每日发放上限的限制,在未获得精品款的情况下,随机获得一个基础款。

之前我们在测试的时候,只测试了藏品是否能正常兑换,还是产品和运营提出,希望能模拟一下当前藏品配置,每日x次兑换的情况下,藏品发放的情况。

之前我觉得这个模拟没啥意义的,事实证明我想岔了。

第一版的藏品兑换逻辑大致是这样的:

List[String] ids = [精品款1,精品款2,精品款3,精品款4,基础款1]‍‪‭‪‪‬⁣
// 精品款获取‍‪‭‪‪‬⁣
int index = (int) (System.currentTimeMillis() % ids.size());‍‪‭‪‪‬⁣
for (int indexInc = 0; indexInc < ids.size(); indexInc++) {‍‪‭‪‪‬⁣
  String id = ids[(index + indexInc) % ids.size()];‍‪‭‪‪‬⁣
  if (该id对应数字藏品不是精品款) {continue;}‍‪‭‪‪‬⁣
  if (获取该数字藏品成功) {return;}‍‪‭‪‪‬⁣
}‍‪‭‪‪‬⁣
// 基础款获取‍‪‭‪‪‬⁣
index = (int) (System.currentTimeMillis() % ids.size());‍‪‭‪‪‬⁣
for (int indexInc = 0; indexInc < ids.size(); indexInc++) {‍‪‭‪‪‬⁣
  String id = ids[(index + indexInc) % ids.size()];‍‪‭‪‪‬⁣
  if (该id对应数字藏品不是基础款) {continue;}‍‪‭‪‪‬⁣
  if (获取该数字藏品成功) {return;}‍‪‭‪‪‬⁣
}      

从左向右的第一个基础款,命中概率要比其他基础款高很多,因为只要随机到的起始index落在精品款上,那么必然最终会选到向右的第一个基础款。同样的道理,第一个位置的精品款,也有这个问题,会比其他精品款的掉率高不少。

第二版的方案,与第一版差不多,区别在于,将精品款id和基础款id拆分成两个数组了,并没有放在同一个数组当中。

所以,测试还是要全面呀。

7、前端兜底配置‍‪​‭‪‪‬⁣

这个是前端同事提出来的,让运营提供一份默认配置,在后端接口异常时,前端展示这份默认配置。

这个设计方案是真的惊艳到我了,之前我做的所有技术方案中,出现问题的兜底方案都是直接展示空就完了,还没想到过可以提前准备一份默认配置的。

当然,这个方案的实施,也要看具体业务场景能否适用。

三、团队协作

1. 会议需要主持人

  1. 主持人有什么用?

    把控整个会议的进度,保证高效的达成会议目标,常见作用比如:

  1. 在出现争执时及时拍板下结论,避免一直争论下去导致会议其他议题没聊完
  2. 会议跑偏的时候,及时把大家拉回来
  3. 对每个比较大的议题,在讨论结束时,做总结,并和所有成员确认总结结论无异议
  4. 。。。

ps:为啥我专门提这个点呢?因为开会效率真的有够低的,开了一周多了,要是不及时制止,可能还要开更长。可是这个活动是有明确的deadline的,在期限之前必须完成上线,现在开会浪费的时间,都需要我后面加班加点的补回来,我当然坐不住了。

  1. 列举下我遇到的,开会过程中的存在的一些问题
  1. 已经拍板确定的问题,反复拿出来讨论

    典型场景就是这样的:

上一次的会议,已经和支持部门的人,讨论过针对某个功能点的对接方案,当时有方案A/B/C可选,最终拍板定下采用A方案。

然后在下一次和支持部门的人开会讨论时,话题突然聊到上次聊过的功能点,然后就又开始讨论有哪些实现方案,要怎么选择。

我作为一个两次开会都在的人,给我的感觉就像是陷入轮回不停穿越一样。

  1. 已经开会讨论得到的结论,可以再次确认下,也可以提出新的质疑,但是完全一副上次没开会重新再讨论一遍的架势,就过分了,尤其是讨论的人里面有上次开过会的。

    这个时候,就需要有个人站出来,直接制止他们的讨论,然后明确的告诉他们:这个问题上次讨论过了,结论是xxx,你们觉得有啥问题嘛?

  2. 在拉了很多人的会议上,过分讨论一些无意义的细节

    比如需要某个支持部门,提供一份数据,数据量不大,完全可以人工从数据库手动获取的。只需要讨论下,数据需求能否支持就可以了,至于怎么提供这个数据,就完全没有必要在会上聊,会下的时候相关方自己去对一下就行了。

    数据量这么小,特殊操作一下就完事了,没必要那么正经的还讨论下http接口、rpc接口、数据库下载等等一堆方案哪个好点,浪费时间。

  3. 暂时无法得到结论的争议,先搁置

    比如某个功能点实现,需要依赖其他部门,但是其他部门能否支持、可以支持到什么程度还没结论。

    这个功能点实现,就完全可以先搁置,等依赖部门有结论了或者到我们必须做决定的期限了,再讨论怎么实现。可以提前简单聊下各种实现方案,但没必要去争论,更没必要提前花时间去做技术方案,纯属浪费时间。

2. 多部门的信息及时交流

四、回顾总结‍‪​‭‪‪‬⁣

  1. 重要的活动,要专门做运维支持,根据业务发展情况,随时会有各种需求产生。‍‪​‭‪‪‬⁣
  2. 异常监控确实很有必要,及时发现了问题。主会场配置,运营承诺配置修改后都会去线上check一下,实际上并没有严格遵守,而且也确实出现线上配置错的情况,还是后端开发看到监控去通知他们改的。‍‪​‭‪‪‬⁣
  3. 活动关键时间点,最好选在上班时间,不然就得要么熬夜,要么早起,太难了。‍‪​‭‪‪‬⁣

继续阅读