大流量活动下钱包提现方案的设计与实现对问题进行梳理和沉淀,对后续类似活动有所帮助。一、活动背景及互动流程2022春节活动的目标是在抖音、火山、西瓜等八个终端启动。希望抖音终端能够分流多终端流量,实现“一字节一春节”活动。对用户来说,可以在任意端参与春节活动,在钱包里可以看到玩收集卡、红包雨等游戏获得的所有收入,最后可以在任意端将春节收入提现到个人账户中确保用户在活动中的奖励能够得到保障。登陆以增加用户对春节活动的参与度。交互流程进入活动钱包页面后,用户可以查看参与活动获得的奖励收益,点击【前往提现】按钮跳转到提现页面。在提现页面,用户输入提现金额并选择绑定的账户方式,然后点击【确认提现】即可将提现活动的收益划入自己选择的个人账户。2、大流量下的主要问题是用户将参与领卡、红包雨等活动的奖励收入提取到银行卡、支付宝或抖音零钱等用户个人账户中。由于春节活动集中抽奖带来的流量大,活动中分享的奖励数额巨大,所以在开发春节活动提现的过程中需要考虑几个方面:1.账户延迟和提款限额。每小时点击开启红包雨,19:30开始春节活动领取卡抽奖和烟花汇演。此时,面对百万QPS的用户奖励入账,部分请求入账可能会出现延迟,导致用户提现时看到的金额与参与活动获得的奖励金额不一致.此外,今年春节活动提现提高了1元/单的门槛限额。在跨年卡抽奖、红包雨、烟火大会等多种游戏方式的支持下,用户轻松赚到1元以上。但是,如果您在收入达到门槛后立即提现,可能会导致您参与后续游戏获得的奖励减少,无法提现。2、高并发抽卡红包雨过后,提现入口打开时,会有几十万的请求流量。用户选择账户方式并输入提现金额后,还会有数万条QPS提现订单请求。钱包服务器收到请求后会操作扣除用户活跃账户的余额,然后调用金融方(字节内部的支付平台)请求支付,金融方维护接入各个支付机构(支付宝,BankNet))相互影响。但是,每个支付机构分配给每个单元的取款请求流量是有限的,Byte获得的容量与取款是一个数量级的差异。这个时候需要保证用户的提现体验不受影响,同时保证下游渠道侧不会因为高流量导致可用性波动。3、安全提现是春节活动的最后一道工序。公司将从用户的春节活动收入账户中扣除资金,通过预先设置的储备账户将资金划入终端绑定的个人账户,使获得的奖励最终落地。如果用户在终端的操作显示支付超过限额,一旦支付成功,基本没有追回的可能。因此,资金安全是提现业务开展过程中必须考虑和保障的一环,确保每一笔支付都有迹可循,遵守提现规则。3、设计方案为了解决以上问题,我们采用RocketMQ进行异步支付,保证用户体验。同时,使用RocketMQ还可以对银行卡等支付渠道进行削峰,减少下游流量过大。在资金安全方面,每笔订单在从春节活动账户中扣除收入和提取现金时都进行了幂等操作,并增加了对账任务,对所有交易进行对账和验证。1、除夕夜,抽奖时间为抽卡活动当晚19:30。用户进入主会场即可看到卡牌收集奖励。全天红包如雨,用户春节活动奖励不断,进入钱包页面查看个人收入。为保证用户领卡抽奖和红包下雨事件顺利入账,不会出现看到奖励但没有收入或钱包收入不足导致提现错误的问题,我们将使用用户进入提现页面时,终端请求参数中的红包代币列表进行入场请求,确保用户在确认提现前账户内金额未完成时,可以通过代币列表进行强制入场撤单。但是为了让用户在提现页面有更好的体验,这里引入了弱依赖请求。当用户确认提现订单时,我们设置一个强依赖强制录入作为最终的后备方案,使得奖励金额已经成功录入,并支持在最终提现扣除时提现。同时,为保证用户参与活动获得的奖励在活动结束后可以全部提现,减少用户参与后续玩法获得的奖励较少而无法提现的情况,我们在春节期间启用了延迟大规模提现。取款入口于19:00至凌晨1:00关闭。用户只能在主会场参与活动获得奖励,不能进入钱包页面进行提现操作。当用户在活跃钱包页面点击【提现】时,会有弹窗提示用户在2月1日01:00后提现。此外,在弹窗中,我们还添加了营销策略为用户绑定卡,引导用户预绑定卡,提现快一步。由于提现入口在凌晨1点开放,可能会有大量用户涌入提现页面进行提现。这个时候为了防止流量突然暴增可能导致的数据库连接问题,我们在配置平台上进行配置,对用户id取模后批量发布结果。在有限的情况下,保证用户账号正确,请求不受限,是判断我们用户体验好坏的重要因素。提现批量延迟至凌晨1:00发布,有效降低了用户提现的并发度,保障了用户的提现体验。2、除夕19:00至春节凌晨01:00MQ异步提现时间段内,春节活动钱包页面将暂时关闭提现功能,进行部分营销导流。随着凌晨01:00开启提现开关,请求蜂拥而至,逐渐攀升至数万QPS。但由于银联处理能力有限,目前支持的银行卡支付QPS最高只有几千。此时如果取款模块不限速下单,可能会存在下游系统不堪重负造成雪崩的风险。同时,用户会觉得提现功能卡顿,经常失败。为了解决这个问题,我们引入了用于异步支付的RocketMQ。当用户在钱包页面进行提现操作时,服务器会在春节活动收入账户扣款完成后立即返回结果并跳转到提现结果页面显示当前状态,并在同时将当前请求参数发送给MQ进行异步消费提现。这样给用户的感觉是账户余额被扣了,正在提现,提现结果也可以稍后通过账单查询。消息发送给MQ后,提现模块利用MQ消费者提现订单的提现订单,通过下游消费者有限的消费能力来处理消息。同时加入自定义限流器对各个支付通道进行流量限制,使用MQ进行流量削峰和限流支付两种方式双重保证下游支付不会因为流量过大而抖动。消费成功后,即可顺利完成支付。当消费失败或限流时,会返回错误,MQ会重试消费。这里我们设置MQ的最大重试次数为3次。如果消息没有超过最大重试次数,则将其放入重试队列;如果消息达到最大重试次数,则将其放入死信队列,不予处理。2.1定时任务为了防止由于多次MQ重试消费失败或其他原因导致撤单被卡在中间状态而停止更新,我们额外设置了一个定时任务进行补单操作来推进撤单状态。创建时间超过4小时且当前处于未完成状态的订单,每小时从数据库中取出,并根据当前状态进行提升:待扣订单,表示用户账户收入未扣.此时订单状态直接提升为失败状态;对于等待支付的订单,请求财务接口执行支付操作,并将状态推送到支付或支付完成;支付中的订单,查询金融支付订单,如果金融方成功或失败,状态会同步更新到提款订单。如果财务端无法查单,则调用财务提现接口重试;对于从任何状态流向失败的订单,我们都会查询该账户的订单流向。如果账户端有余额扣款流程,操作会返还余额,保证失败的订单不会扣款用户的收益。3.提现资金安全在提现过程中,一旦技术方案设计出现问题,很可能会出现资金安全问题:账户没有扣款,但现金已经转入用户账户个人账户,账户被多次扣款或多次提取现金等。因此,在春节活动提现模块的设计中,资金安全问题是重点考虑的问题。当出现提现请求时,服务器需要保证每笔订单必须对应一次账户余额扣款和一次提现。提现完成后,需要一个对账任务,与账户和提现进行对账,分别核对提现订单的金额和状态,确保事件中的核对无误。3.1订单是幂等的,即任意多次执行的影响与一次执行的影响相同。取款针对orderID进行幂等控制,账户侧每个orderID只有一次扣款操作,保证用户活跃账户余额不会被重复扣款;同时,用户当前订单提现失败后,账户余额将回滚操作时,先查看账户端是否有扣款订单,如有,则退回余额。退货时,控制一个退货流量对应的扣款操作,防止超额退款。账户扣款后,需要调用财经的提现接口,将资金从公司预先设置的备付金账户划入终端绑定的个人账户。这时候需要保证每次提现请求只能提现一次。我们每次操作提现订单进行提现,都是使用redis分布式锁来锁定orderID。锁定成功后,我们会判断当前订单状态。接口调用后立即更新订单状态为支付中,防止重复调用导致可能的重复支付操作。同时,财务端也对orderID进行幂等控制,保证每个orderID对应一个支付。3.2对账核对涉及资金流向,需要对账任务保证上下游资金数据的一致性,及时发现因处理金额或状态差异造成的资金损失。我们在对账平台上增加了准实时对账和天际对账,来验证资金。准实时对账在出金过程中,我们在对账平台中增加了与下游服务(账户、财务)出金数据的准实时对账,确保每次状态变化时出金单准确无误:1.与账户方实时对账:余额扣款成功后,账户端会保存一个提现数据流。此时需要核对扣款流水和提现单的金额和状态,确保扣款状态与金额一致;b.当提现失败时,如果此时账户已经扣款成功,需要将之前扣款的金额退回用户的活跃账户。返回流水,查看提现单的状态和金额。2、与财务端实时对账:当取款订单状态更新为成功或失败时,获取财务端取款订单数据和取款订单数据进行一致性校验,判断双方数据状态和金额是否一致。对账平台中的数据校验是基于双方对数据的binlog消费的准实时对账。如果对账双方数据缺失或双方对账状态不一致,飞书会发出告警通知。此外,我们还在在线服务中添加了一个自对账任务,通过消费取款数据库的binlog消息。对于已经进入最终状态的订单,我们会根据订单状态通过接口调用来查询账户和财务端。对于提现成功的订单,您可以在账户的清单界面找到扣款交易,在财经的清单界面也会有支付成功的订单。对于提现失败的订单,您可以在账户查询界面找到扣款和退余额。如果可以在财务订单查看界面查看订单,只有失败的订单。如果没有顺序,则表示提现过程在到达提现前失败,此时可以忽略遗漏的差额。天层对账此外,我们还增加了与下游服务(账务、财务)的天层对账,作为准实时对账之外的一种自下而上的对账。由于调用失败或回调失败,上下游之间的状态同步可能不及时,我们增加了一个定时任务来推进订单状态,以保证每一个提现订单最终都能到达最终状态。天空级对账是为了解决由于状态同步不及时可能导致的准实时对账差异,通过每天产生的蜂巢数据验证状态和金额,减少时间差带来的误报。4.前期准备为了保证活动上线后用户可以在钱包页面正常提现,我们添加了活动前的准备计划。1、前期预演在活动正式开始前,我们组织了三场预演,包括内部划定团体、内部业主、外部划定城市。我们对春节活动期间的红包雨和提现进行了提前演练,模拟了春节活动的正常流程和突发事件。情况的处理。通过演练,提前发现整个活动过程是否顺利,提前暴露和解决可能存在的问题。2.充分的压力测试为了支撑春节活动期间产生的大流量请求,保证用户良好的活动体验,我们将春节活动的提现功能与钱包的日常收入提现功能进行了分离。代码开发上线后,申请压测资源,对各业务流程进行预估流量压测。集群隔离也避免了压测操作对正常线上业务产生任何影响。在对提现业务进行压测的过程中,有两方面需要做一些数据准备:查询账户方法接口需要将绑定账户账户方法的结果返回给压测的uid;确认提现接口需要进行压力测试,在uid绑定账户的同时,还需要uid对应的活跃账户中有足够的钱来支持余额抵扣。为了解决这个问题,财经同学在压测前提供了一批测试uid绑定account方法生成的文件,方便我们在进行account方法查询时从文件中指定uid参数接口压力测试。另外,账号同学在压测账号录入接口的时候,我们提供了这个文件,帮助他们录入这批uid。这样下单压测提现时,我们使用已经绑定账户方法的测试uid数据,活跃账户中已经存在余额,支持提现余额的抵扣。最终,在对支付方式查询、提现订单确认等接口进行全链路压测后,我们能够准确评估出支持春节活动最高QPS所需的资源容量,从而使春节活动可以按照预先计算好的流程进行,支持用户操作和退出。3、在除夕执行脚本除夕是我们春节活动开始后的一个重要时间点。当天红包雨很多,还会有烟花秀、抽卡等游戏。整个活动将在春晚伊始达到高潮。在参加这种大型活动的过程中,大家或多或少都会有一些压力。即使经过前期多次演练,代码已经过验证,没有任何问题,但在处理重要活动的启动时,还是要慎之又慎。在大脑记忆力有限的情况下,为了防止遗漏,我们写了一个跨年夜的执行脚本:执行细节。从除夕夜10点到大年初一凌晨2点,每次红包雨前需要做哪些准备,红包雨发生时需要查看哪些监控指标,是否需要记录下红包下雨后的数据等,执行脚本需要详细记录每次需要做的事情。配置验证。春节期间提现业务有活动配置和限流。在活动开始之前,您需要再次检查以确保所有配置和限流都正确无误。灾难恢复计划。除了执行细节和配置校验之外,我们还在脚本中加入了容灾预案,这样当某个流程出现问题时,可以按照预案及时处理。交叉检查。脚本中的操作细节和配置检查由两个人进行,采用交叉检查的方式,防止一个人的疏忽和错误的更改。五、活动总结春节活动上线后,用户积极参与各种玩法,并在活动钱包中进行提现。跨年夜,虽然延迟加量导致用户一收到收益就无法提现,但用户的奖励还是正常到账的。延迟解除后,提现请求不受提现通道的限制,有效保障了用户的提现体验。同时,在通道侧支付能力有限的情况下,使用MQ进行异步支付,有效的限制了对下游服务的请求流量,不至于出现流量过大导致支付异常的情况。此外,在春节活动全时段,通过梳理提现流程风险,在对账平台新增准实时、小时级对账支持和在线服务对账支持,双重保障春节活动提现模块对账任务全覆盖,让用户在参与活动和提现领取奖励的过程中不造成任何经济损失,保证了用户的参与度。
