谈谈电商秒杀高并发的处理

谈谈电商秒杀高并发的处理众所周知现在连市场卖菜的大妈都快知道高并发了,哈哈,那么我们生活中是否接触过高并发呢。当然了哈哈,比如你给你女朋友抢秒杀的化妆品什么的了。秒杀最棘手的问题就是解决并发带来的问题。下面我们一起聊聊喽。首先我们来说下问题:秒杀高并发带来的最大问题,就是库存超卖。(如果你没看过我的文档,导致你写公司秒杀业务时库存超卖了,公司损失了,将你开除了,你会多么不开心,哈哈我来给你写稻草救救你)嘻嘻嘻嘻嘻…

大家好,又见面了,我是你们的朋友全栈君。

众所周知现在连市场卖菜的大妈都快知道高并发了,哈哈,那么我们生活中是否接触过高并发呢。当然了哈哈,比如你给你女朋友抢秒杀的化妆品什么的了。秒杀最棘手的问题就是解决并发带来的问题。下面我们一起聊聊喽。

首先我们来说下问题:秒杀高并发带来的最大问题,就是库存超卖。(如果你没看过我的文档,导致你写公司秒杀业务时库存超卖了,公司损失了,将你开除了,你会多么不开心,哈哈我来给你写稻草救救你)

嘻嘻嘻嘻嘻嘻嘻

解决方案:解决高并发导致库存超卖问题的核心思想就是,库存扣减要保证串行化操作

1.数据库层面解决方案:

    这种方式实现起来最简单,就是利用乐观锁。

    update product set num=num-1 where num-1>0 and pid=#{pid}

    使用此方法一定要注意,set num 时一定不要使用,set num=#{num},这样做的话不能保证原子化操作,并发还是会有问题(覆盖更新)。

    缺点:数据库存在瓶颈,首先是连接数,更重要是多个请求更新一条数据,会互相检查是否死锁(笛卡尔积)。而秒杀问题就是请求量大并发高。那怎么办?继续看小老弟说咯。

2.使用缓存(Redis等)解决方案:

    使用缓存确实可以解决数据库瓶颈的问题,例如Redis天然的串行化操作(Redis单线程),并且在数据内存中做操作很快。

    使用Redis的自增incr或自减decr操作库存,判断返回结果是否为0,如果为0表示秒杀失败。这样不就保证了库存的不超卖。

    此时你可能说,啊我明白了不就是用Redis的缓存来搞吗,简单简单。本大侠哈哈一笑,要是这样的话本大侠不也去BAT了。

=================下面才是关键=========================================

说说我们目前满意的Redis方案的问题吧。

先说一个优化的问题:

1.每次我们通过Redis查询库存都是通过远程连接的方式,虽然很快,但是并发大的时候,这里还是要优化一下的。

怎么优化?简单的说就是,当发现Redis库存为0时,我们在程序中设置一个标识位,秒杀逻辑中每次进来先判断标志位。这样库存为0时就直接返回,而不用再远程连接查询Redis了。

你可能会说这样就行了吧?对于一般的秒杀来说应该可以了,但我还要和大家说说更多的优化和优化时的问题,希望对大家的工作有好的提示或者帮助,那样我会很高兴的。哈哈

2.每次当我们秒杀成功后,会创建订单、通知库房、通知快递等一系列操作,如果我们把这些操作也放在秒杀时来处理,那么我们程序处理起来可想而知,会很慢的。那么这时我们就要优化,怎么优化?

实现异步处理,我们可以通过MQ(RocketMQ等消息队列)来实现异步处理,当用户秒杀成功后,我们发送消息给其他服务,然后返回给用户秒杀结果,这样是不是就很快了呢。对是快了。

那么问题来了:用户秒杀成功后需要付款,但是此时是异步操作,队列可能并没有处理完消息,怎么办怎么办?哈哈,这时我们需要在前端加一个轮询,轮询什么?轮询查询秒杀的结果(象征的意思意思用户,排队中什么什么的了)。下面代码

谈谈电商秒杀高并发的处理

简单讲讲这段代码:首先判断登录就不说了,后面通过用户名查询下当前用户是否秒杀成功了,然后然后问题来了,哈哈为什么我下面要使用了数据库查询?而不是查询缓存中的商品数量是否为0,因为还是之前的问题,队列没有消化完,用户秒杀成功的记录还没有生成,如果查询数据库商品没有了,那就代表队列已经处理完了,代表你秒杀失败了GG。如果还有库存,那么返回success(0)告诉用户排队中。直到数据库中库存没有了,那么代表队列处理完了,这时候你在查询Redis应该有订单信息的,如果没有那么你真的是秒杀失败了。讲到这里可能大家理会的差不多了,但是这段代码中还是存在问题?什么问题呢,那就是当他查询Redis时队列消息还是没处理她的消息,当他查询数据库之前,队列处理完了,这样你查数据库发现库存没有了,你就会返回秒杀失败,但其实你是秒杀成功的。这样还是会影响用户体验的。你可能会说不能吧,那么巧。哈哈我就是要和你说高并发下这种情况出现很正常。所以呢,我们要防止,怎么防止呢?

终极解决方案:

谈谈电商秒杀高并发的处理

我们在查数据库判断库存为0时(标记:数据库库存为0,消息肯定处理完了,也就是redis肯定有订单了,因为有妹子问了,我必须更新一下哈哈),我们再次查询Redis里是否已经有生成的订单了,这样就避免了问题咯。这也就是江湖中传闻的江湖秘诀,双重校验锁,哈哈,其实关于秒杀啊高并发的问题还有很多,这类问题每一行代码都是要考虑很多情况的,希望我再这里能给大家一个抛砖引玉的作用。小老弟要睡觉了,如果哪里说得不对别喷啊,都同行哈哈哈。

   

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/138411.html原文链接:https://javaforall.net

(0)
上一篇 2022年5月31日 下午1:46
下一篇 2022年5月31日 下午1:46


相关推荐

  • archlinux安装教程以及自己踩过的坑

    archlinux安装教程以及自己踩过的坑引言 linux 是一种哲学 最近喜欢上了 arch 的简洁 可高度定制化 滚动更新和设计哲学 准备日常办公从 ubuntu 转向 arch 目前已完成安装 正在使用 arch 写这篇博客 而事实证明 arch 确实没让我失望 它的确是一个非常不错的发行版 安装环境 cpu i5ram 12G 台式电脑一块硬盘 有剩余空间或新硬盘都可以 我这里用的是 1T 新硬盘 GPT 分区 UEFI 启动 一块 8GU 盘从

    2026年3月17日
    2
  • 简单剖析B树(B-Tree)与B+树

    简单剖析B树(B-Tree)与B+树注意 首先需要说明的一点是 B 树就是 B 树 没有所谓的 B 减树引言 我们都知道二叉查找树的查找的时间复杂度是 logN 其查找效率已经足够高了 那为什么还有 树和 树的出现呢 难道它两的时间复杂度比二叉查找树还小吗 答案当然不是 树和 树的出现是因为另外一个问题 那就是磁盘 众所周知 操作的效率很低 那么 当在大量数据存储中 查询时我们不能一下子将所有数据加载到

    2026年3月17日
    3
  • 我用OpenClaw,5分钟写出一个skill的7个步骤(第三讲,思路通用)

    我用OpenClaw,5分钟写出一个skill的7个步骤(第三讲,思路通用)

    2026年3月13日
    3
  • 浅谈 JMeter 运行原理

    浅谈 JMeter 运行原理

    2021年7月13日
    98
  • C++实现内存池

    C++实现内存池1 内存池设计 1 1 目的在给定的内存 buffer 上建立内存管理机制 根据用户需求从该 buffer 上分配内存或者将已经分配的内存释放回 buffer 中 1 2 要求尽量减少内存碎片 平均效率高于 C 语言的 malloc 和 free 1 3 设计思路将 buffer 分为四部分 第 1 部分是 mem pool 结构体 第 2 部分是内存映射表 第 3 部分是内存 chunk 结构体缓冲区 第 4 部分是实际

    2026年3月17日
    1
  • CSS-界面滚动时不显示滚动条

    CSS-界面滚动时不显示滚动条最近产品提出一个需求 在界面滚动时 元素右侧不显示滚动条 查了网上的答案 最后总结了一下几个情况 1 设置常规的滚动条 使用 overflow auto 父元素需要设置一个高度 设置相对定位 这样子元素的高度大于父元素高度才能显示滚动条 如果父元素的高度完全由子元素撑开 界面上不会出现滚动条 设置 overflow auto 失效的主要问题 可能是这个 div 没有设置 100 然后父元素清除浮动

    2026年3月19日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号