zoukankan      html  css  js  c++  java
  • 秒杀场景下mysql减库存逻辑优化

    【问题背景】

            某天早上做活动,流量大量增长,导致大量更新库存操作失败。

            操作mysql返回的错误均为“Lost Connection to mysql server”,即mysql服务端主动断开了连接,导致update操作失败。

            都是在sql执行过程中返回的“Lost”,且都是update操作返回“Lost”,同一时刻的“select”操作并无异常。

            都是update执行操过了1s后返回的“Lost”

    【原因】

            秒杀情景下是大量update同时操作同一表的同一记录

            对同一记录的写操作都要加“行锁”,且有“死锁检测”,使得sql操作串行执行,有阻塞

            猜测:某些请求由于等到超时了,被mysql服务关了连接

    【老流程】

    如果需要更新 item1(分库1)、item2(分库2)、item3(分库4)的库存

    • 流程

    =>所有分库,每个分库上均开启一个事务

    =>查询。。

    =>循环处理3个item

    =>=>如果该次操作以前没做过(没有对应<seqid,itemid>)继续;否则处理下一个item

    =>=>更新库存

    =>=>更新是否售空

    =>=>插入<seqid/item>

    =>所有分库,每个分库均提交事务

    1)如果有一个item更新失败,回滚所有事务

    2)尽量保证要不所有item都更新成功,要不都失败

    • seq表

            每次的请求对应一个唯一的seqid,而<seqid,itemid>记录了这次请求的item是否更新成功。

            如果seq表中有这条记录表示上次请求的item以更新成功。

            目的是为了防止由于上次操作成功,而返回结果时出现问题,下次重试导致重复的执行。

    • 问题

    1)一个事务中,sql操作太多;如果事务中有update操作,则从update操作执行到事务提交将会一直锁住操作行,因此事务越长,锁越长,性能损耗越大

    2)每个分库都要等所有item更新完后才提交,增长事务时间(也就是锁时间)

    【优化后】

    如果需要更新 item1(分库1)、item2(分库2)、item3(分库4)的库存

    • 流程

    =>循环在每个item所在分库对item进行处理

    =>=>在分库1中开启事务

    =>=>插入seq表<seq,item1>

    =>=>更新库存and是否售空

    =>=>分库1中提交事务

    =>=>分库2。。中操作item2

    =>=>分库4。。中操作item3

    • 更改

    1)并没有在所有分库中新起事务,而是每个事务中只处理自己所包含的item的减库存操作;当一次请求多个item时,减少每个库的事务的时间长度

    2)先插入seq表,再更新库存,如果插入失败直接退出;减少一次读seq操作,将事务中sql操作减到最少

    • 问题

    1)一次操作多个item时,不保证要不都成功,要不都失败

    2)只要有sql操作失败,就返回失败

    【对比】

  • 相关阅读:
    Leetcode [654] 最大二叉树 &[105] 从前序与中序遍历序列构造二叉树 & [106] 从中序与后序遍历序列构造二叉树
    Leetcode [226] 翻转二叉树 & [116] 填充每个节点的下一个右侧节点指针 & [114] 二叉树展开为链表
    Leetcode 链表&二叉树刷题总结
    Leetcode 动态规划刷题总结
    Leetcode [1312] 让字符串成为回文串的最少插入次数 动态规划
    Leetcode [234] 回文链表 回文 链表
    动态规划之 KMP 算法详解(转)
    Leetcode [99] 恢复二叉搜索树 二叉树
    统计代码行数
    二叉树遍历(递归、非递归、mirror)转
  • 原文地址:https://www.cnblogs.com/taoxinrui/p/6399691.html
Copyright © 2011-2022 走看看