当前位置: 首页 > 科技观察

阿里云Redis读写分离典型场景:如何轻松搭建电商秒杀系统

时间:2023-03-19 13:36:26 科技观察

背景秒杀活动是大多数电商选择的低价促销和品牌推广方式。不仅可以为平台带来用户,还可以增加平台的知名度。一个好的秒杀系统可以提高平台系统的稳定性和公平性,获得更好的用户体验,提高平台的美誉度,从而增加秒杀活动的营销价值。本次主要讨论为阿里云数据库Redis缓存设计的高并发秒杀系统。秒杀的特点秒杀活动定期销售稀缺或特价商品,吸引大量消费者抢购,但只有小部分消费者能够成功下单。因此,秒杀活动会在短时间内产生比平时大几十倍、上百倍的页面访问流量和订单请求流量。秒杀活动分为3个阶段:秒杀前:用户不断刷新商品详情页,页面请求达到瞬时峰值。秒杀开始:用户点击秒杀按钮,订单请求达到瞬时峰值。秒杀后:部分下单成功的用户不断刷新订单或产生退款,大部分用户继续刷新商品详情页面等待退货机会。消费者提交订单的一般方法是使用数据库的行级锁。只有抢到锁的请求才能进行库存查询和下单操作。但是,在高并发的情况下,数据库无法承受这么大的请求,往往会导致整个服务被阻塞,在消费者看来就是服务器宕机了。秒杀系统系统架构图虽然秒杀系统的流量很高,但实际有效流量非常有限。利用系统的层次结构,在每个阶段提前检查,拦截无效流量,可以减少大量无效流量涌入数据库。使用浏览器缓存和CDN抵御静态页面流量尖峰,用户不断刷新商品详情页面,导致页面请求量大。因此,我们需要将秒杀商品详情页与普通商品详情页分开。对于秒杀商品详情页,尽量做到可以静态化的元素。除了秒杀按钮需要服务器动态判断外,其他静态数据可以缓存在浏览器和CDN中。这样秒杀之前刷新页面导致进入服务段的流量只有一小部分使用阿里云读写分离Redis缓存拦截流量CDN是一级流量拦截,二级流量拦截我们使用支持读写分离的阿里云Redis。现阶段我们主要是读取数据,Redis可以支持60万以上的qps读写分离,完全可以支撑需求。首先,通过数据控制模块,将闪购商品提前缓存到阿里云读写分离Redis,并设置闪购开始标志:闪购开始前,服务集群读取goodsId_Start为0,直接退货未开始。数据控制模块将goodsId_start改为1,标志秒杀开始。服务集群缓存开始标记位开始接受请求,在redis中记录goodsId_access,剩余商品数量为(goodsId_count-goodsId_access)。当接受的订单数达到goodsId_count时,继续拦截所有请求,此时商品剩余数量为0。可见只有少量成功参与订单的请求才能被接受。在高并发的情况下,允许稍微多一点的流量进入。因此,可以控制接受订单的比例。使用阿里云主从版Redis缓存,加速库存扣除。参与下单成功,进入下级服务,开始订单信息核对和库存扣除。为了避免直接访问数据库,我们使用阿里云主从版本的Redis进行库存抵扣。阿里云主从版Redis提供10万级QPS。我们使用Redis来优化库存查询,提前拦截失败的闪购请求,这将大大提高系统的整体吞吐量。我们也通过数据控制模块将库存提前存储在Redis中;//当我们在redis中使用一个hash结构来表示每个秒杀商品的扣减金额时,服务器通过请求Redis获取下单资格。我们通过lua脚本来实现。由于Redis使用单线程模型时,lua可以保证多个命令的原子性;lua脚本:先使用SCRIPTLOAD将lua脚本提前缓存在Redis中,然后调用EVALSHA调用脚本,相比直接调用EVAL节省网络带宽:秒杀服务判断是否Redis可以知道是否扣除了请求成功与否,返回抢购次数n。使用阿里云主从版Redis实现简单的消息队列异步订单入库扣费,需要订单入库。如果商品数量少,可以直接操作数据库。如果闪购商品是10000甚至100000,那么数据库锁冲突会带来很大的性能瓶颈。因此,使用消息队列组件,当秒杀服务将订单信息写入消息队列时,可以认为订单完成,避免了直接操作数据库。消息队列组件仍然可以使用Redis来实现,在R2中用一个列表数据结构来表示:将订单内容写入Redis:异步订单模块从Redis中顺序获取订单信息,并将订单写入数据库:我们使用Redis作为消息队列,异步处理订单入库,有效提高用户订单完成速度。数据控制模块,管理秒杀数据同步一开始我们使用阿里云读写分离Redis来限制流量,只允许部分流量进入订单。对于订单验证失败、订单退款等情况,我们需要允许更多的流量进来。所以数据控制模块需要周期性的对数据库中的数据进行一定的计算,同步到主从版本的Redis,同时同步到读写分离的Redis,让更多的流量进来。