分布式系统秒杀交易性能优化
1、背景
首先介绍一下这个交易的功能: 该交易是一个定期存款交易,利率非常高,存期有三个月,六个月、一年、两年、三年、五年,年化利率基本上每天发布的产品中都有4%以上的。其中六个月和一年的年化利率最受欢迎。这个定期产品只能每天9点开始购买,并且支持的渠道只有手机银行,因此在每天8点59-9点这个区间会收到非常的请求。根据指标控制中心查询的数据大概在9点到9点01秒这一秒中大概需要处理1000个请求。不过老核心那边怕给系统搞宕机做了一个并发控制,也就是达到性能瓶颈时会限制购买,打印“系统繁忙”反馈给前端.大概在不久前,老核心反馈给我们分布式核心说该交易也还需要持续进行优化,因为目前该产品实在是太火爆了,导致老核心也一直无法处理短时间内的大量请求,只能反馈系统繁忙。
2、分析
我对老核心的这个交易逻辑进行了分析,其实他们已经做了不少优化了,不过目前看起来也还是很慢,从9点到9点1分我统计了这一分钟成功交易的平均耗时,大概是370ms左右。这个标准在老核心的交易中其实已经是比较慢的了。而分布式这边目前观察并行生产跑的性能更是非常慢,成功交易的平均耗时大概900ms左右。。。而这个交易又是我负责的产品,因此对它进行性能优化是当务之急。该交易的大致逻辑如下:
前端请求进来,先做一些必输项校验,包括客户信息,密码校验等。接着是查询该产品的产品信息表,获取该产品信息,与客户信息做一些校验。后面会做一些额度的扣减。因为该款产品每次发布是有限额的。比如1000万美元的额度,抢完就没了,因此每次购买完了需要做一个额度的扣减。完了之后就需要记一笔账务。即从该客户的备用金账户扣除一笔钱到该客户的定期账户。最后再落一张表存储该客户购买的信息。
其实老核心之前做的优化是把额度扣减从交易的前面移到了交易的最后。这样做的目的是,在并发请求打进来时,在做额度扣减的时候,会锁表,把这块逻辑放在最后做,能把锁表的时间减少的最短,如果放在前面做额度扣减,那么锁表的时间就是整个交易做完的时间,但是放在最后,就是最后几十ms。其他他们也没有做什么优化,
但是分布式这边就很麻烦了。我这边也是把额度扣减放在最后的,按照他们的想法是把锁表的时间降低到最少。但是这样的话,因为我们是分布式,我得调两次额度服务,两次RPC所耗费得的时间也是很长的。而且分布式按照之前卡服务提供的接口,需要查询三次卡服务的表才能满足业务逻辑。所以我这边所做的优化大概如下:
3、优化
4、总结
该交易涉及账务和额度增减,也就是说,如果交易失败,还需要进行事务回滚。在老核心单核系统处理起来是非常简单粗暴的。但是分布式由于各种RPC的原因,处理的手法就得麻烦点,不过也非常考验对分布式事务和消息队列的理解。其实整个系统达到1000tps在之前的性能测试中已经压到这个指标了,不过还没有涉及到这个秒杀的情况。虽然做了上面的这几个优化,但是肯定还是无法从900ms的平均耗时降下来很多。根据投产后的观察,大概能到500ms,和单核系统相比仍然差距很大。后续要需要持续的进行优化。
这里涉及到的分布式事务知识点还是很重要的。而且我们在框架设计中使用的是乐观锁,也就是已经使得系统性能不会受到很大限制了。但是我觉得在这个秒杀交易这不太适合使用乐观锁。。。。。因为可能会导致很多请求冲突无功而返浪费时间
大致的一个工作总结吧,其实这个产品我也买了。。,但是在查询的时候,明显的在9点的时候刷不到产品信息,提示系统繁忙,其实这个产品的查询也是需要优化的,因为大家在购买产品的时候刷新这个页面看产品信息的时候可能那一秒中的并发量就破万了,这可能就是单核的局限性吧,后面还分布式了应该不会出现这种尴尬的情况。不过仅仅是查询的化从后端的角度来说,优化其实也只是在缓存和SQL上面进行优化。我也是第一次在工作中实际遇到秒杀交易的优化,也让我更加深入的理解了一下这块所涉及的分布式系统设计和后端优化上的知识点。