千万级数据的活动优化方案

27 篇文章 0 订阅

1 可以通过在H5端通过js控制,点击抽奖按钮以后,在请求返回之前将按钮置灰,禁止用户再次点击或者弹出一个loading动画来解决此问题。

2 如果发现一定时间内某个ip下的流量明显异常,可以对此ip进行限流。例如:一个ip的请求量超过1000/min时,拒绝此ip的请求。注意,此方案可能有误判,因为当多人使用同一个局域网时,
此时服务端收到的ip可能是相同的。
添加小黑屋功能,发现恶意用户、ip,将他们拉入小黑屋,一段时间内禁止他们后续的访问

3 可以将中奖用户放在缓存中,收到抽奖请求或抽中时,通过缓存校验此用户之前是否已中奖。

4 可以将抽奖次数放在缓存中,通过计数器自减的方式扣减抽奖机会。

5 缓存不常变动的数据
缓存非常适合存储不经常变动的数据,通过缓存他们可以极大的提升性能。
如,活动中奖品一般不会频繁改变,页面中需要展示奖品信息时,我们可以将奖品信息加载到缓存中,每次请求时直接读取缓存

6 缓存实时性要求不高的数据
业务上如果对某些数据的实时性要求并不高,那么也可以通过缓存降低系统的性能损耗,提升请求速度。
如:活动中需要播报中奖信息,业务上并不要求实时展示最新中奖的几人,所以可以通过启动一个线程,将最近一段时间内需要播报的名单加载到缓存中,播报时从缓存中直接返回数据

7 频繁变动的内容走缓存
频繁变动且持久化意义不大的数据非常适合走缓存。
如,用户完成一些任务以后,奖励一些抽奖机会,奖励的抽奖机会就很适合存储在缓存。使用redis或者tair的原子性加、减操作,每奖励一次抽奖机会,自增1,每抽奖一次,自减1

8 从缓存减库存
抽中奖品时,需要将此奖品总数减1,这其实就是一种减库存操作。并发情况下从DB中减库存,一来性能比较差,二来为了避免脏写可能导致DB更新失败概率大增。此时改为从缓存中减库存

9 活动开始前,将奖品库存加载到缓存。
抽奖时直接从缓存中扣除;如果扣除库存以后,剩余奖品数量>=0,表示扣减库存成功;如果库存扣除后,剩余奖品数量<0,表示扣减库存失败。
此种方案的缺点是:活动期间如果需要修改库存信息,则需要特别注意数据一致性,避免出现奖品超发问题

10 缓存更新模型
使用此方案时,如果活动期间运营希望增加/减少奖品库存,需要先暂停活动,更新库存并刷新到缓存,然后取消暂停,让用户继续抽奖。
暂停操作是为了防止因为异步扣减奖品库存而导致奖品超发

11 选择合适的数据结构
缓存中间件,例如Redis提供了多种数据结构,分别适合不同场景的需求。使用时根据具体场景,选择最合适的数据结构,尽量选择时间复杂度底的数据结构,尽可能减少与缓存的交互次数。
如:抽奖时需要扣减抽奖次数,有两种方式从缓存中扣减用户剩余抽奖次数:
方式一:先从查询当前剩余缓存;内存中扣减次数,最后将结果剩余次数重新放回缓存。
方式二:直接通过自减指令进行扣减操作,如果结果大于0,那么允许抽奖。
两种方式虽然都能满足需求(这里暂不考虑并发情况下更新缓存时的失败问题),但是第二种方式可以减少一次与缓存的交互。服务器与缓存服务器交换一次数据的时间约为1ms-3ms,
即便一次请求只节省一次交互,当请求量达到1000w次,可为服务器累计节省2.7-8.3h;当并发量非常高时,这种性能损耗也是不能忽略的

12 使用堆缓存
使用分布式缓存时,因为每次与缓存交互都要消耗1ms-3ms时间(如果返回数据量较大时,由于IO瓶颈的存在,耗时可能进一步增加)。一个抽奖请求需要与缓存进行多次交互,当高并发时,
累计出来的性能的损耗会非常明显,此时可以考虑将数据缓存在堆内存中。
例如:抽奖活动的各个页面中需要查看奖品信息,抽奖过程也需要根据奖品概率进行计算是否中奖,等等。如果每次都从缓存中取,性能损耗不可接受,那么可以将奖品信息放到内存中,
彻底省略掉这部分与缓存交互的时间。
此方案的缺点是:服务器重启时内存中数据会丢失;DB数据变更以后,需要确保每台服务器都更新到最新的数据

13 缓存失效
使用缓存时,需要小心应对缓存击穿问题。在高并发场景中一般采用异步将数据刷新到缓存;请求过程中即便发现缓存中数据不存,也不会从DB中读取。有几种种常见的做法应该尽量避免:
缓存没有数据时,从db中获取,然后放到缓存中。此方式无法防止缓存击穿时,将流量全部倾泻到底层服务或DB上,而引起的雪崩。
通过锁让一个线程从DB中获取数据,然后存到缓存中,其他线程等待。这种做法一来编程麻烦,二来等待的线程较多时占用的内存也会比较大,服务器相应速度明显降低

14 分布式队列方案
使用分布式队列,如Redis的队列,中奖时通过LPUSH命令向队列中加入中奖记录数据,每个服务器启动一个线程通过RPOP命令从队列中获取中奖记录数据,然后入库。因为Redis的性能很好,
所以往Redis队列中写记录的速度非常快,抽奖过程的性能损耗非常小,性能自然也就提上来了

15 放弃重试
失败重试会影响系统性能,重试次数越多,对系统性能的影响越大。
抽奖过程中,从抽奖信息验证到扣库存、中奖信息入库的整个过程中,任何一个环节异常或失败,我们都不会进行重试,全部当做未中奖处理,这是由抽奖的业务场景决定的,
即:抽奖本身是随机的,不需要保证100%中奖。如果业务上要求100%中奖,可以在流程最后添加一个“补偿奖品环节”,即:返回失败信息之前,在给用户发一个奖品,不修改前面的整个流程

16 隔离技术
隔离技术的核心是防止压力、异常等相互传导,导致服务不稳定甚至不可用。
在我们的抽奖活动中,我们使用到的隔离技术有:系统隔离、数据隔离、动静分离、故障隔离。如:营销活动的系统独立于负责常规业务的系统,以避免相互干扰;
DB、RocketMQ使用独立的集群,防止影响其他核心业务;通过动静分离技术,降低带宽占用;隔离各个系统的异常

17 限流技术
业务上主要通过计数器的方式进行防刷性限流,例如:单个ip的流量超过300/min,一段时间内不再接收此ip的其他请求;通过用户id限制抽奖次数、中奖次数;等等。
通过设置tomcat Connector、db连接池、缓存连接池等限制上游流量和对下游的压力

18 域名问题
活动如果做得好,分享一定少不了。
在现实中,朋友圈最常见的导流渠道,但遗憾的是一旦微信发现H5页面有诱导分享的风险,可能直接将域名封掉。
为了不影响其他业务在朋友圈中的可用性,最好为每个活动申请一个子域名,即便是被封了,也不影响其他业务的使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值