当前位置: 首页 > news >正文

分布式环境并发场景下,如何操作抢红包(或者减少库存)

文章目录

  • 简介
  • 思考
  • lua 对 redis 的原子操作
  • 其他解决方式
  • 一些问题

简介

在分布式场景高并发环境中,无论是抢红包还是减库存,其实本质上都是如何处理高并发中共享资源的问题,保证高并发资源分配的安全性

相互学习,如有错误还请指正~

思考

比如抢红包的场景,高并发访问数据库会给 mysql 带来较大压力,因此可以考虑把红包数据放在 redis 中,通过并发请求 redis 内存的红包数据,来快速响应请求

但是大量请求并发访问 redis 内存数据,如何保证这个资源的安全性呢?肯定要用到锁或者进行某种原子操作

lua 对 redis 的原子操作

逻辑思路:

  • 首先红包创建的时候,它会对应一个红包 id,创建时候预先知道它要分 10 个红包,那么就把总金额随机分成 10 个数字的数组预先 random 出来
  • 然后把红包 id 对应的金额数组,和红包 id 对应的 10 这个库存存到 redis 中,方便后续请求直接访问 redis
  • 注意 redis 中还需要维护一个 hashmap 用来判定一个用户是否领取过红包,如果用于领取过就把 userId 存进 map
  • 当多个请求并发进来(这里使用 lua 原子操作,保证线程安全)
    • 判定用户是否领过:线程 A 会线判定 map 中用户是否领取过,如果领取过直接返回,如果没有领取过就开始判定库存
    • 判定库存是否充足:如果库存 <= 0,那么直接返回红包被抢光,如果库存 > 0,就把库存减少一,然后 map 中添加上当前 userId,金额 list 弹出一个红包金额
  • 判定如果 redis 中库存为 0 就需要写入库存(同时需要考虑到红包可能还有剩余,因此也需要有一种定时机制把 redis 红包领取记录同步到 mysql)
  • 后续业务操作
  • 最终把金额 list 弹出的金额返回给前端

其他解决方式

  • 分布式锁

    对于一些大型打公司可能有分布式锁调用的以来包,这样写起来比较方便

    操作:先把红包库存数据导到 redis 中,然后兵法请求过来查询 redis,在查询前先有分布式锁的代码来看是否要阻塞,如果阻塞,等在运行的运行玩之后释放就可以了,锁住的内容包括查询 redis 红包库存是否充足,以及 redis 内存中改库存的操作。锁释放之后,可以判定红包库存如果为 0 就把 redis 记录同步到 mysql 中(也需要有一种定制机制定时同步 redis 到 mysql,因为可能存在红包领取不完),再可以进行后续业务操作。分布式锁里头的实现本质也是用了 lua 脚本保证 redis 多个操作的原子性

    特点:万一某个 server 实例宕机了,锁就没法释放,其他人就用抢红包锁住了,所以需要设置一个分布式锁的超时时间

  • 悲观锁:(不推荐,但是实际企业开发中可能有人在用)

    实际开发中,偷懒的程序员可能比较喜欢用,因为也最简单方便

    操作:其实就是事务操作中,进行 select for update(它只能在事务中使用)先锁住数据,直到事务提交才会释放锁

    特点:没有解决大量请求打向 mysql 的问题,而且完全串行执行性能很差,还需要注意一旦索引失效,行级锁就变成了表级锁(其他操作表里其他数据的操作也被锁住了)

  • 乐观锁

    操作:为了解决悲观锁效率问题,使用乐观锁,即 A 线程先看下版本号为 1,这个时候把 mysql 红包库存 - 1 且判定条件是 version == 1,但是突然发现 version == 2 了,这是因为有线程 B 并发执行完了并且把 version 再 ++ 了,这时候 A 线程执行数据库失败,返回 err 给到用户,并且线程 A 事务会回滚,这会到大量失败,并且大量回归操作也给 mysql 带来压力,但我们可以再稍微优化一下,就是引入重试机制,如果线程 A 操作数据库更新失败了,按照限定时间内重试或者设置重试次数,这样可以减少很多用户抢红包(扣库存)失败的返回

    特点:适合更新的并发操作不多的场景。存在出现部分并发用户被返回数据库操作 err 的情况

一些问题

  • 数据怎么从 mysql 存入到 redis 呢?
    对于促销来讲,我们再开发一个定时任务,把符合秒杀促销条件的商品存储到 redis 中,促销前定时执行触发。对于抢红包场景,原代码中加上,当用户创建出红包的时候,就把红包库存以及红包 random 金额数组存储到 redis 中
  • 什么场景会去查找 redis 而不是直接访问 mysql 呢?
    高并发访问数据库时候考虑上层加一个 redis
  • redis 如和同步到 mysql?什么时机
    可以通过定时任务方式定时同步到 mysql
http://www.lryc.cn/news/24132.html

相关文章:

  • 明星的孩子也在做的感统训练,真的有用吗?
  • 守护进程与TCP通讯
  • 在线文本翻译能力新增14个直译模型,打造以中文为轴心语言的翻译系统
  • CVE-2022-42889 Apache Commons Text 漏洞
  • 20- widedeep及函数式构建模型 (TensorFlow系列) (深度学习)
  • 大家一起做测试的,凭什么你现在拿20k,我却还只有10k?...
  • >>数据管理:DAMA简介「考试和续期」
  • React的生命周期详细讲解
  • 蓝蓝算法二期工程day3,一万年太久,只争朝夕
  • 程序代码的自动化生成方案设计
  • Go 稀疏数组学习与实现
  • MySQL 学习笔记(借鉴黑马程序员MySQL)
  • 中级工程师职称申报到底需要参加答辩不?
  • MM32开发教程(LED灯)
  • win10安装docker
  • 设计模式系列 - 代理模式及动态代理详解
  • 【分享】订阅集简云畅捷通T+cloud连接器自动同步财务费用单至畅捷通
  • GPT的发展历程
  • iOS开发笔记之九十八——关于Memory Leak总结笔记
  • HTML基础语法
  • 微软新版必应gpt人工智能体验教程
  • 你问我答|虚拟机、容器和无服务器,怎么选?
  • 某建筑设计研究院“综合布线管理软件”应用实践
  • R语言绘制SCI论文中常见的箱线散点图,并自动进行方差分析计算显著性水平
  • redux-saga
  • 【C++】-- 智能指针
  • 数据结构与算法——4时间复杂度分析2(常见的大O阶)
  • IIS解析漏洞
  • 2023 年腾讯云轻量和CVM服务器租用价格表出炉(CPU/内存/带宽/系统盘)
  • Java学习之路002——面向对象编程