热点账户处理
作者:互联网
热点账户(数据)处理
关于程序员技术面试,高并发、高可用是肯定躲不过的知识点,面试官不会直接这么问,而是嵌入到某些具体场景中。
比如,让你设计一个促销活动,紧俏的商品;或者发放优惠券,某事某刻发1000张5.5折优惠券等等。
这类题目一是考察你的整体架构设计能力,二是看你的回答中有没有高并发高可用的实现。
还可以再直接一些,比如有个商户账户,会频繁的更新,如何去实现?
这三类问题,不管是秒杀商品库存还是打骨折的优惠券,亦或是商户账户,最根源的在于热点账户(数据)在高并发下如何正确的处理问题。
下面就试着给出这些问题的一个标准答案。
一、理解业务,确定业务类型。
你可能会问,业务不是很清楚的了,秒杀啊,热点商户更新啊,还怎么确定业务?
这里要确定的是更新哪些数据?哪些是热点数据?热点数据是加还是减少。
比如秒杀,数据库中一条商品数据是频繁更新的数据,操作是做减法,业务上不允许出现商品为负数,也就是出现“超卖”的结果。
优惠券呢,和商品几乎一样,优惠券的数量是热点数据,同样是做减法,不能出现负值。
热点商户余额呢,有些不一样,客户余额的减少,引起商户余额增加,也可以是相反,客户增加,商户减少,总之是客户的操作引起的商户热点数据更新,可加可减,当然也不能出现负值。
说了这么多,业务的关键出现了,这就是热点商户的更新是否接受某些延迟。
比如优惠券和库存,不接受延迟,数据比如是实时的,而商户的热点账户,没有必要追求高的实时性,延迟个几秒,也是可以接受的,最终一致性必须保证就OK了。
所以,这一步很关键,业务的梳理决定了后续的你有哪些高并发高可用的“武器”来用。
二、“实时性”要求高的解决方案
面对秒杀和打折扣的优惠券类活动,我想说的第一点是,如果有条件,首先做到“隔离”。
隔离的目的是为了保护,不要因为促销活动将整个系统搞挂。
可以单独的数据库,单独的服务部署,尽量做到不影响核心流程。
我们知道,单机不管多牛的程序员写出多牛的程序,瓶颈是很容易达到的,其中各种组件中,数据库又是木桶中“最短”的那块,所以很多的业务操作都是围绕着数据库来展开。
热点数据,放到数据库就是一条条的更新操作,排着队等着被执行,高并发情况下,数据库层面其实就是串行化操作,不管是多牛的update Sql,也必须排着队等着,性能的瓶颈就出现在这。
有什么好办法?
在单条热点数据,数据库层面可以有两种方案进行优化。
单条数据库执行慢,主要是因为并发操作,冲突多,如果能让数据库在最理想的状态下才能达到他的最优秀,而现实呢,不断地有请求进入,已经超过了他的承受范围,永远的高负荷运转,性能能好吗?
两种优化方案:
一是,在数据库层面进行排序,让数据库在保持最佳状态下执行SQL 语句;
二是,“批量”,较少更新语句,给数据库减压。
这两种方案,其实是很多大厂才有能力去做的,像阿里巴巴,在MySQL 内核下进行优化,从而提高数据库能力。
不过想批量,后面可以去讲一下,不一定是在数据库层面上去解决。
多说两句,在数据库层面上关于库存不能超卖,也有几个小窍门;
1.利用事务更新数据,如果数据更新为了负数,进行回退;
2.可以将库存设置为无符号的整数,不可能为负值。
3.where 条件下做优化,库存必须大于要减少的值。
很多公司不会像阿里那样有能力在数据库内核下,也有其他手段。
热点账户往往是因为更新集中在一条,那么如果有多条不就能分担其压力了?
确实是这样的,我们可以将热点账户进行拆分,拆分成多条,同时将库存数分布到众多子账户上,这样高并发情况下,可以达到分流的效果,性能也就上去了。
不过拆分热点账户也有很多副作用,如果需要库存整理,当某些账户快要为空时,其他账户库存还有很多;还有最后各账户的库存很少,不能满足下单需求,需要整理众多子账户进行汇总。
这些都是拆分子账户带来的副作用,当然了,副作用还是能比如热点账户,还是简单多了。
我们再极端一下,拆分子账户当然不能太多,不然带来的麻烦比好处还多,子账户一定时,如果并发还是比较高,又形成了新的热点账户,问题回到了原点,此时该如何?
这时候,传统的数据库已经被压榨到了极限,我们需要外援了。
nosql该上了,比如redis,我们完全可以将库存数量放到Redis缓存上,一是Redis的并发能力在万的级别,二是其单线程,恰恰是库存更新最好的特性,所以很多公司的活动依靠Redis的颇多。
当然了,Redis同样具有副作用,数据存在多份,Redis一份,关系型数据库一份,数据库的一致性问题需要去保证。
Redis不代表着容易丢失,只不过相对于数据库来讲差一些,所以会用数据库娄底,不管是以数据库为准还是以缓存,数据都需要保证一致性。
讲到这,对于实时性要求比较高的秒杀活动,我们可以使用数据库层优化、拆分子账户、使用缓存等手段进行改进优化。
那么对于商户类,可以接受一定延迟的热点数据我们又能怎么办?
三、“接受延迟”的热点数据处理方案。
先说结果,上面使用的手段,在此同样适用。
我们还可以增加两种新方案:异步和批量。
只要能接受延迟的,首先想到的就是异步化。
对于商户的余额更新,我们可以先将操作记录下来,剩下的慢慢更新,这就是异步。
高并发的情况下,我们原来需要实时的进行update这条这点账户,我们可以将一条update语句,变成insert语句,另起线程,将insert语句,进行账户操作。
这样的话,插入没有热点,异步将被动变为主动,性能上也上去了。
再加上一招:批量。
我们可以将多条更新语句,进行合并,例如200条更新合并成100条,瞬间讲操作减少了一半,性能可想而知。
几个关键字:拆分子账户、缓存、异步、批量就够了。
本文完。
标签:商户,处理,数据库,账户,更新,并发,热点 来源: https://www.cnblogs.com/myf008/p/16182980.html