当前位置:首页 > SEO优化 > 正文

12306系统深度优化-(预扣库存,异步下单,MySQL高可用)

  在节假日和春节时候,火车票提前预售。在预售的点会有大量人们抢购车票。由于高并发,导致服务瘫痪。

  内存计算余票

  异步交易系统(削峰方案)

  数据库进行高可用搭建(读写分离)

  1. 削峰方案:

  对于瞬时流量我们最先想到的是中间件进行削峰,把直接调用转化为间接异步推送。中间队列在一瞬间接受流量锋,在另外一端平滑的将消息推送。

  

  2. 答题:

  在下单时候,我们需要答题。因为每个人的答题速度不一样,错开抢票时间。

  3. 分时间段发放票:

  将票分多个时间段进行发放

  

  后台管理员按照日期生成乘车计划、座位信息、车次信息,并通过logstash将数据同步到ES和redis中。

  用户在下单时候,用户经历下单、扣库存、支付。在高并发场景下保证,车票不多买也不少卖,且支付后车票真实有效。

  1. 方案一

  

  用户在下单完,立马扣除库存,等待用户支付。且创建订单和扣除库存是原子操作。能保证不超卖问题。方案问题:

  在极度并发请求下,每次创建订单对内存操作对性能影响很大。订单数据需要保存到数据库,对数据库压力很大。如果很多人下了订单,但是不支付。会导致很多票没有卖掉。

  2. 方案二

  

  在极度并发场景下,库存减为0时候,很多用户抢到订单却不能支付。而且也不能避免数据的IO操作。

  3. 方案三

  

  用户选择乘车计划,点击下单-->进入下单服务集群中,--》判断redis库存是否充足,否(直接响应票已售空)、是(预扣库存)-》把下单信息发送给mq,es同步库存信息-》如果用户支付,订单处理服务进行订单信息入库,并响应成功信息。如果超时未支付,redis进行库存回退,es进行库存回退。

  2.1.1 nginx进行限流配置

  为了防止一些抢票助手发送无用请求,采用nginx进行限流操作。

  1. 限制访问频率:limit_req_zone:单位时间内请求数,采用漏斗算法。

  2. 限制并发连接数:limit_conn_zone:同一时间的连接数。

  1. 订单生成:

  找对应日期对应车次对应座位类型的乘车计划库存(站票,坐票,硬卧、软卧等),进行库存扣减。

  遍历所有指定座位类型车厢的key(集合)。

  遍历集合获取每个车厢的座位(集合)。遍历集合获取每一个座位对应状态。如果座位没有售出,标记座位并更改座位的状态。

  在创建订单时候,我们可以采用一个线程完成。且线程执行完毕,我们要获取线程的执行结果,采用Callable执行订单创建。

  在线程中创建订单对象。

  将指定日期的乘车计划封装到一个对象中。

  生成订单。

  采用 Redis 中的 ZSet 集合存储排队信息,使用:列车编号 + 乘车日期 + 用户 id 作为 key,使用当前系统时间的纳秒值作为 value。

  2. 同步ES库存:

  下单服务发送同步信息(乘车日期、座位性质、列车车次)到mq中。es同步服务监听mq,获取发送信息。根据搜索条件查询到数据,并进行库存扣减。

  3. 发送订单数据:

  创建订单和用户信息,并设置交换机和队列。发送订单信息,发送完订单数据,跳转到下单成功界面。下单成功界面调用排队接口,显示排队信息。

  1. 环境准备:

  因为下单,写的操作远大于读的操作,因此mysql采用双主双从搭建模式。

  2. 保存订单:

  下单服务监听mq,如果有订单生成,对订单信息进行入库。

  3. 删除排队信息:

  订单保存成功后,删除排队信息。

  

  4. 将下单结果通过websocket发送给客户端:

  保存完订单数据以后,调用 WebSocketServer ,完成消息推送。

  用户已经下单了,再次提交订单是否扣除订单?用户虽然下单了但是一直没有支付。预扣减库存是否存在线程安全问题。

  2.2.1 预扣库存优化

  当该用户已经购买了指定列车的火车票,那么我们就不能再进行预扣库.

  根据用户信息和乘车计划id查询订单信息,查询到信息,不进行库存扣减。

  2.2.2 库存回退

  1. 方案一(延迟队列):

  

  延迟队列:消息发送后,特定时间后消费者才能拿到消息进行消费。

  2. 方案二(死信队列):

  死信队列:一个消息在队列中变成死信队列之后,消息会被从新发送到另外一个交换机中,这个交换机就是死信队列。一个消息成为死信队列情况:

  消息被拒绝,并且设置 requeue 参数为 false

  消息过期

  队列达到最大长度

  

  在进行库存扣减时候,加锁。因为扣除库存是多服务,因此需要用分布式锁来解决(mysql实现,zookeeper实现,redis实现)。

  【编辑推荐】

  鸿蒙官方战略合作共建——HarmonyOS技术社区

  中国程序员开发的远程桌面火了!Mac可用,仅9MB,支持自建中继器

  3分钟带你彻底搞懂 Kafka

  抖音服务器带宽有多大,才能供上亿人同时刷?

  火爆Github!这个号称后现代编辑能超越Vim么?

  2021年最危险的七大攻击技术

  【责任编辑:姜华 TEL:(010)68476606】

  点赞 0

有话要说...