Redis项目实战——优惠券秒杀

这篇具有很好参考价值的文章主要介绍了Redis项目实战——优惠券秒杀。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Redis自增功能解决全局唯一ID

  • 如果用MySQL的自增长ID,ID的规律性太明显,会暴漏一些信息(比如销量等)
  • 数据量太大时一张表存不下,需要多张表,MySQL多张表的自增长都是独立的,会出现重复ID
  • 需要一种在分布式系统下可以生成全局唯一ID的工具,必须唯一且递增
  • 在某项目里,不管数据库的表有多少个,Redis只有一个,因此Redis递增功能生成的ID一定是全局唯一的
  • 为了保证递增的同时且没有规律,保证安全性,可以在Redis自增数值的基础上拼接一些其它信息
    Redis项目实战——优惠券秒杀,# 数据库,redis,数据库,缓存

Redis实现优惠券秒杀的主要思路

Redis项目实战——优惠券秒杀,# 数据库,redis,数据库,缓存

实现过程中出现的问题及解决方法

超卖问题

  • 在高并发场景下,多个线程同时操作共享的资源(库存),导致实际卖出的数量超出了库存数量

方案1 悲观锁

  • 态度比较悲观,认为线程安全问题肯定会发生,在操作数据之前提前获取锁
  • 例子:Synchronized、Lock
  • 优点:安全性高
  • 缺点:性能低,实现简单

方案2 乐观锁

  • 态度比较乐观,认为线程安全问题不一定会发生,因此不加锁,只在数据更新时去判断在它之前有没有其它线程修改数据。如果没有修改认为是安全的,直接更新数据,如果已经被修改说明不安全,重试或报异常
  • 版本号法:给库存增加一个版本字段,线程1查询并记录下库存和版本号,然后将库存-1,版本号+1,来表示线程1修改了一次数据,然后在更新数据之前再判断一下版本号,是否是自己当时记录的版本号+1,若是,说明没有并发线程在期间修改过数据,安全,可以放心更新,若不是,说明正好有并发线程在期间修改过了数据,不安全,重试或者报异常
  • CAS法:版本号法的简化版本,去掉版本号这个多余的字段,直接用库存本身代替版本号,根据库存本身有没有发生变化来确定是否更新
  • 优点:性能高
  • 缺点:实现复杂

一人一单问题

  • 常见的业务问题,要求同一个优惠券,一个用户只能下一单
  • 在库存充足判断成功后再增加一个判断,用用户ID和优惠券ID联合查询,来判断该用户是否已经买过一优惠券
  • 在单机模式下,可以加Synchronized锁来保证线程安全
  • 在集群模式下,Synchronized锁无效,需要用分布式锁来确保线程安全。Synchronized锁无效的原因是因为每台服务器有自己的常量池,锁监视器便保存在常量池中,用户尝试获取锁便是访问锁监视器,因此,主要问题是因为多个服务器的锁监视器是独立的,所以多个服务器上的用户能在同一时刻同时获取锁,进而导致线程安全问题

分布式锁

  • 在单机情况下,只有一个JVM,JVM中只有一个锁监视器,只有一个程序可以获取到锁。但在集群情况下,有多个JVM,多个JVM中有多个锁监视器,程序可以获取到多个锁,甚至同一个程序也可以获得多个锁,就会出现线程安全问题
  • 需要在多个JVM之外做一个共享的 多进程可见的 互斥的 锁监视器——分布式锁
  • 实现分布式锁的三大方式:MySQL、Redis、Zookeeper,MySQL和Zookeeper比Redis安全性更好,Redis性能比二者更好
    Redis项目实战——优惠券秒杀,# 数据库,redis,数据库,缓存
如何用Redis实现分布式锁?
  • 获取互斥锁:SET lock thread1 NX EX 10,NX是互斥,确保只有一个线程可以获取到锁,EX是设置超时时间。
  • 释放锁:直接手动删除。
  • 死锁问题:若获取到锁后线程宕机,容易出现死锁,应该增加过期时间,超时自动释放锁。
  • 误删问题:若线程1获取到锁,但业务执行时间过长,超过了TTL,会自动释放锁,此时线程2尝试获取锁成功,并正常执行业务,但期间线程1业务执行完毕,正常执行释放锁操作,此时就会把线程2的锁误删。为了避免这种情况,应该在获取锁时增加一个标识,来表示谁占有了这个锁,且只有它才有资格释放锁,因此在释放锁之前需要增加判断步骤
  • 基于setnx实现的分布式锁存在的问题:不可重入(同一个线程无法多次获取同一把锁),不可重试(获取锁只尝试一次,失败不会重试),超时释放(业务执行耗时较长会导致锁释放,存在安全隐患)
  • Redission组件:Redis基础上实现的分布式工具集合

Redis优化秒杀

  • 优化主要思路:将涉及到数据库的减库存创建订单等耗时操作用异步独立线程慢慢做,Redis只需要判断用户有没有抢成功并返回结果
  • 原来的秒杀流程:主要是Tomcat里面的一系列操作,有四个会直接操作数据库,耗时非常久。相当于一个饭店,来了一位顾客,派了一个服务员为这位顾客一条龙服务,从点菜(查询秒杀资格)到做饭(减库存和创建订单)都是这一个服务员做,效率非常低下。
  • 优化后的秒杀流程:在NGINX和Tomcat之家增加Redis,用于判断该用户能不能抢上优惠券,并将判断结果和优惠券id、用户id、订单id一起保存到阻塞队列,然后Tomcat从队列中读取消息,进行比较耗时的减库存和创建订单操作
    Redis项目实战——优惠券秒杀,# 数据库,redis,数据库,缓存
  • 其中Redis判断秒杀库存的操作可以封装到Lua脚本中执行,以确保该操作的原子性
    Redis项目实战——优惠券秒杀,# 数据库,redis,数据库,缓存
  • 基于阻塞队列的异步秒杀存在的问题?
  • 阻塞队列用的时JDK的,会占用JVM内存,大量消息会造成内存溢出

消息队列实现异步秒杀

  • 消息队列:存储管理消息
  • 生产者:发送消息到消息队列
  • 消费者:从消息队列获取消息并处理消息
  • Redis实现消息队列的三种方式:List、发布订阅模式、Stream

List

  • 链式的双端队列,LPUSH存,RPOP取,但并没有阻塞效果(队列空时不会阻塞等待),BRPOP有阻塞效果。
  • 优点:独立于JVM存在,不占JVM内存,不担心上限,且可以持久化,还能保证消息有序性
  • 缺点:无法避免消息丢失,只支持一对一

发布订阅模式

  • 消费者订阅一个或多个channel,生产者向对应channel发送消息
  • 优点:支持一对多,一个生产者可以把消息发给多个消费者。天生支持阻塞
  • 缺点:不支持数据持久化,无法避免消息丢失,消息堆积有上限

Stream

  • 优点:消息可回溯,支持一对多,支持阻塞读取
  • 缺点:可能会漏读消息
  • 消费者组:将多个消费者划分到一个组中,监听同一个消息队列,那么多个消费者就会竞争这些消息,可以加快处理消息的速度,避免消息堆积。消费者组还会维护一个标识,记录最后一个被处理的消息,可以很快恢复突发情况,避免漏读消息。此外,消费者拿到消息后,Redis并不会直接不管这条消息,而是将消息置为pending状态,表示这条消息取上了但还没处理完,处理完后通过XACK确认消息,标记为已处理,此时Redis才会放心地把消息从队列中移除,可以防止消息丢失。
  • 消费者组优点:消息可回溯,可以多消费者争抢消息,加快消费速度,可以阻塞读取,不会漏读消息,有消息确认机制,保证消息至少被消费一次

三种消息队列对比总结
Redis项目实战——优惠券秒杀,# 数据库,redis,数据库,缓存文章来源地址https://www.toymoban.com/news/detail-687664.html

到了这里,关于Redis项目实战——优惠券秒杀的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【java爬虫】将优惠券数据存入数据库排序查询

    本文是在之前两篇文章的基础上进行写作的 (1条消息) 【java爬虫】使用selenium爬取优惠券_haohulala的博客-CSDN博客 (1条消息) 【java爬虫】使用selenium获取某宝联盟淘口令_haohulala的博客-CSDN博客  前两篇文章介绍了如何获取优惠券的基础信息,本文将获取到的基本信息存到数据库中

    2024年02月16日
    浏览(53)
  • 微信小程序实现一些优惠券/卡券

    👏 前几周有小伙伴问我如何用css实现一些优惠券/卡券,今天就来分享一波吧!速速来Get吧~ 🥇文末分享源代码。记得点赞+关注+收藏! 2.1 实现内凹圆角 假设我们要实现这样的一个效果,两侧透明内圆角+外侧投影,有几种实现方式呢? 2.1.1 方法一:半圆伪元素(投影不准确

    2024年02月09日
    浏览(42)
  • 小程序中如何核销订单和优惠券

    小程序已成为许多商家线上线下开展业务的重要渠道。客户在小程序中下单/领券后,可能需要商家现场扫码核销,例如超市购物、卖票、游乐园等线下场景。下面就介绍小程序中如何核销订单和优惠券。 一、订单核销 订单核销是指商家在小程序中确认顾客已经支付的订单并

    2024年03月21日
    浏览(48)
  • 机器学习:基于逻辑回归对优惠券使用情况预测分析

    作者:i阿极 作者简介:Python领域新星作者、多项比赛获奖者:博主个人首页 😊😊😊如果觉得文章不错或能帮助到你学习,可以点赞👍收藏📁评论📒+关注哦!👍👍👍 📜📜📜如果有小伙伴需要数据集和学习交流,文章下方有交流学习区!一起学习进步!💪 订阅专栏案

    2024年02月02日
    浏览(44)
  • 两天撸一个优惠券小程序,记录下开发的小小经验

    下载微信开发者工具😃😃 新建项目文件夹project,比如 D:workProjectproject 在project下创建src目录放微信小程序的源码,.gitignore文件是用来git上传gitee上忽略一些文件用的,另外三个js文件时用来混淆小程序源码的脚本,将脚本和小程序源码分开是为了脚本更好处理混淆过程。

    2023年04月08日
    浏览(55)
  • 【实践篇】教你玩转JWT认证---从一个优惠券聊起

    最近面试过程中,无意中跟候选人聊到了JWT相关的东西,也就联想到我自己关于JWT落地过的那些项目。 关于JWT,可以说是分布式系统下的一个利器,我在我的很多项目实践中,认证系统的第一选择都是JWT。它的优势会让你欲罢不能,就像你领优惠券一样。 大家回忆一下一个

    2024年02月05日
    浏览(43)
  • 智慧影院--java开源电影票优惠券制作系统快速开发

    搭建一个智慧影院可以通过使用Java开源电影票优惠券制作系统来快速开发。这个系统可以帮助影院管理电影票的销售和优惠活动,提供便捷的购票方式和优惠券的生成与使用功能。 首先,我们需要建立一个数据库来存储电影、影厅、放映计划、订单等信息。在数据库中,我

    2024年02月13日
    浏览(71)
  • 淘宝APP商品详情接口(商品信息,价格销量,优惠券信息,详情图等)

    淘宝APP商品详情接口(商品信息接口,价格销量接口,优惠券信息接口,详情图接口等)代码对接如下: 公共参数 名称 类型 必须 描述 key String 是 调用key(必须以GET方式拼接在URL中),点击获取请key和secret secret String 是 调用密钥 api_name String 是 API接口名称(包括在请求地址

    2024年02月12日
    浏览(51)
  • 业务安全情报第16期 | 大促8成优惠券竟被“羊毛党”抢走!?

    近期,某电商小程序举办美食节营销活动,提供高额折扣券,并允许用户进行秒杀。然而,羊毛党团伙利用作弊手段,抢购囤券,然后倒卖变现,严重损害了商家的利益。 根据顶象防御云编号为BSI-2023-rutq业务安全情报发现,某电商平台为吸引人气和促进销售推,推出高额折

    2024年02月07日
    浏览(49)
  • 斐讯1200M四天线双频路由器PSG1208只要88元 快来领取优惠券

    斐讯斐赛克斯专卖店针对1200M斐讯PSG1208无线路由器启动淘抢购活动,现价88元(原价98元),其拥有1200M传输速率、2.4G/5.8G双频并发、WISP中继等特性。 立刻下单 。 斐讯PSG1208使用802.11ac协议,2.4G/5.8G双频并发,数据传输速率达1167Mbps;配以联发科SOC MT7620A处理器、4天线4*4MIMO架构

    2024年02月08日
    浏览(62)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包