秒杀系统三层架构设计:缓存、消息队列与数据库

秒杀是一种极端高并发场景,短时间内数百万用户涌入,抢购有限库存的商品。为了保证系统稳定性和数据一致性,同时提升用户体验,我们可以设计一个三层架构缓存层消息队列层数据库层。本文将详细设计这一架构并探讨其优点与实现方式。


1. 秒杀三层架构简介

秒杀架构的三层功能分工如下:

第一层:缓存层

  • 快速处理用户请求,减少访问数据库。
  • 提供库存的预检功能,快速反馈请求结果。

第二层:消息队列层

  • 削峰填谷,缓解高并发对后端服务的冲击。
  • 保证秒杀请求的顺序性,防止超卖。

第三层:数据库层

  • 最终扣减库存并记录订单信息,确保数据持久化和一致性。

2. 架构设计流程

2.1 秒杀流程概览

  1. 用户发起秒杀请求,首先进入缓存层。
  2. 缓存层快速检查库存是否可用,若库存不足,直接返回失败;若库存充足,进入下一层。
  3. 请求进入消息队列,按顺序处理,避免并发超卖。
  4. 消息队列中的请求由消费者逐条处理,最终访问数据库扣减库存并生成订单。
  5. 秒杀结果异步通知用户,或用户自行查询。

3. 各层设计详解

3.1 缓存层设计

功能
  • 快速判断商品库存是否足够。
  • 将热点商品的库存信息缓存在内存中,避免频繁访问数据库。
  • 限制超量请求,提高秒杀效率。
实现
  • 使用 RedisMemcached 缓存商品的库存信息:
  • 在用户请求时,通过 Lua 脚本实现原子操作,快速检查和扣减库存:
local stock = redis.call('GET', KEYS[1])
if tonumber(stock) > 0 then
    redis.call('DECR', KEYS[1])
    return 1  -- 扣减成功
else
    return 0  -- 库存不足
end
注意事项
  1. 缓存穿透:对非法请求(如商品ID不存在)进行拦截,可以使用布隆过滤器。
  2. 缓存雪崩:设置不同商品的缓存过期时间,避免大规模缓存同时失效。
  3. 并发一致性:为缓存操作增加分布式锁,防止库存扣减不一致。

3.2 消息队列层设计

功能
  • 削峰填谷,缓解高并发对后端系统的冲击。
  • 按请求的先后顺序处理,保证秒杀公平性和库存的一致性。
实现


3.3 数据库层设计

功能

实现
  • 使用 RabbitMQKafkaRocketMQ,构建秒杀请求队列。
  • 用户请求通过缓存层验证后,写入消息队列:
  • 消费者从队列中拉取请求,逐条处理,调用数据库扣减库存。
  • 注意事项
  • 队列长度限制:设置队列的最大长度(如10万条),超过长度直接拒绝请求,返回“秒杀结束”。
  • 消息重复消费:使用唯一请求ID去重,避免重复扣减库存。
  • 队列高可用:采用主从模式或分区机制,确保队列的高可靠性。
  • 最终扣减库存,记录订单信息,确保数据持久化。
  • 保证库存扣减和订单生成的原子性。
  • 数据库表设计:
    库存表

CREATE TABLE stock (
    product_id BIGINT PRIMARY KEY,
    total_stock INT NOT NULL,
    reserved_stock INT NOT NULL
);

使用 事务存储过程 保证库存扣减与订单生成的原子性:

BEGIN;
-- 检查库存
SELECT total_stock - reserved_stock INTO available_stock
FROM stock WHERE product_id = ? FOR UPDATE;
IF available_stock >= ? THEN
    -- 扣减库存
    UPDATE stock SET reserved_stock = reserved_stock + ?
    WHERE product_id = ?;
    -- 创建订单
    INSERT INTO orders (user_id, product_id, quantity) VALUES (?, ?, ?);
END IF;
COMMIT;
注意事项
  1. 分库分表:对于大规模秒杀场景,按商品ID或用户ID进行分库分表,减少单表压力。
  2. 读写分离:库存查询和订单记录可采用主从同步,提升查询性能。
  3. 高可用设计:采用主备切换和故障恢复机制,保障数据库服务持续可用。

4. 架构优势

高性能

  • 缓存层快速响应用户请求,降低数据库访问压力。
  • 消息队列平滑处理高并发请求,避免系统过载。

高稳定性

  • 各层解耦,缓存、消息队列和数据库可独立扩展,提升整体可靠性。
  • 即使部分服务宕机,秒杀请求可在消息队列中暂存,确保请求不丢失。

高一致性

  • 缓存层、消息队列层和数据库层逐步确认库存状态,避免超卖问题。
  • 数据库层事务保证最终一致性,确保库存扣减和订单生成的原子性。

5. 秒杀流程总结

  1. 用户请求:进入缓存层,快速预检库存并扣减,确保高性能。
  2. 消息队列处理:请求写入消息队列,按顺序处理,削峰填谷。
  3. 数据库持久化:最终扣减库存,生成订单,确保数据一致性和持久性。

6. 实现挑战与优化方向

挑战

  • 高并发时缓存层可能成为瓶颈,需对 Redis 集群进行优化。
  • 消息队列的消费速度需要与数据库处理能力匹配。
  • 数据库扩展需要分库分表等复杂设计。

优化方向

  • 缓存与消息队列的多层组合,提升系统吞吐能力。
  • 使用分布式数据库(如TiDB)或NoSQL数据库(如MongoDB)提升数据库性能。
  • 利用异步通知和多级缓存,提高用户体验和响应速度。

7. 结论

通过三层架构设计,缓存、消息队列和数据库各司其职,能够有效应对秒杀场景中的高并发、高性能需求。缓存层负责快速响应,消息队列层平滑处理请求,数据库层保证数据一致性,三者结合为秒杀系统提供了稳定、高效的解决方案。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/922928.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LabVIEW引用类型转换问题

一、问题描述 在LabVIEW中,refnum(引用编号)用于引用各种资源,如文件、队列、控件等。这些引用是与具体类型相关的,通常情况下,LabVIEW会根据引用的类型自动进行处理。然而,当不同类型的引用需…

Redis五大基本类型——Set集合命令详解(命令用法详解+思维导图详解)

目录 一、Set集合类型介绍 二、常见命令 1、SADD 2、SMEMBERS 3、SISMEMBER 4、SCARD 5、SRANDMEMBER 6、SPOP 7、SMOVE 8、SREM ​编辑 9、集合间操作 (1)SINTER (2)SINTERSTORE (3)SUNION…

HTMLCSS:彩色灵动气泡效果

效果演示 这段代码是一个HTML文档&#xff0c;包含了内联的CSS样式&#xff0c;用于创建一个具有动画效果的网页背景&#xff0c;其中包含多个彩色浮动的气泡元素。 HTML <div class"container"><div class"bubble"><span></spa…

[工具分享] 根据Excel数据根据Word文档模板,批量创建生成Word文档并重命名,方便快速查找打印

前几天交楼的小姐姐要多份Word文档合同打印给客户&#xff0c;那么100份就需要修改100次 上面好多都是模板的制式文件&#xff0c;里面的部分数据都是要根据实际值来变动的&#xff0c; 那么有没有快速的方法来操作呢&#xff0c;还是只能一个个手动的改&#xff0c;又容易出…

《硬件架构的艺术》笔记(五):低功耗设计

介绍 能量以热量形式消耗&#xff0c;温度升高芯片失效率也会增加&#xff0c;增加散热片或风扇会增加整体重量和成本&#xff0c;在SoC级别对功耗进行控制就可以减少甚至可能消除掉这些开支&#xff0c;产品也更小更便宜更可靠。本章描述了减少动态功耗和静态功耗的各种技术。…

【Linux学习】【Ubuntu入门】2-3 make工具和makefile引入

1.使用命令新建三个.c文件vi main.c&#xff0c;vi input.c&#xff0c;vi caclcu.c&#xff0c;两个.h文件vi input.h&#xff0c;vi caclcu.h 2.vi Makefile&#xff1a;新建Makefile文件&#xff0c;输入一下内容 注意&#xff1a;命令列表中每条命令前用TAB键&#xff0c;不…

【初阶数据结构和算法】leetcode刷题之设计循环队列

文章目录 一、实现循环队列1.大致思路分析2.循环队列的结构定义和初始化结构定义初始化 3.循环队列的判空和判满判空和判满难点分析判空判满 4.循环队列的入队列和出队列入队列出队列 5.循环队列取队头和队尾元素取队头元素取队尾元素 6.循环队列的销毁7.最后题解源码 一、实现…

Otter 安装流程

优质博文&#xff1a;IT-BLOG-CN 一、背景 随着公司的发展&#xff0c;订单库的数据目前已达到千万级别&#xff0c;需要进行分表分库&#xff0c;就需要对数据进行迁移&#xff0c;我们使用了otter&#xff0c;这里简单整理下&#xff0c;otter 的安装过程&#xff0c;希望对…

#Java-常用API-BigInteger、BigDecima、正则表达式

1.BigInteger BigInteger可以表示非常大范围的整数&#xff0c;理论上来说无限大 a.构造方法 构造方法说明public BigInteger(int num, Random rnd)获取随机大整数,范围 : [0 ~ 2的num次方 - 1]public BigInteger(String val)获取指定的大整数public BigInteger(String val,…

C++设计模式-中介者模式

动机(Motivation) 多个对象相互关联的情况&#xff0c;对象之间常常会维持一种复杂的引用关系&#xff0c;如果遇到一些需求的更改&#xff0c;这种直接的引用关系将面临不断的变化。在这种情况下&#xff0c;可以使用一种”中介对象“来管理对象间的关联关系&#xff0c;避免…

cursor 使用经验分享

cursor 是一款基于 VSCode 的 AI 优先编辑器&#xff0c;如果你还没有体验过它&#xff0c;我强烈建议看完这篇&#xff0c;因为 cursor 真的在改变编程游戏的规则&#xff0c;在了解 cursor 前&#xff0c;可以先思考一下我们日常在编程环节都做哪些事情&#xff0c;我日常开发…

Linux系统编程之进程基础知识

概述 在Linux系统中&#xff0c;进程是指一个正在运行的程序实例。每个进程都有一个唯一的进程标识符&#xff0c;即PID&#xff0c;操作系统通过这个PID来唯一识别和管理各个进程。进程不仅仅是程序代码的运行实例&#xff0c;它还包含了程序运行时所需的各种资源&#xff0c;…

LabVIEW发动机热磨合试验台

在汽车发动机的研发和质量控制中&#xff0c;发动机热磨合试验是关键环节。它能够检验发动机在实际运行条件下的性能&#xff0c;及时发现异响、振动、漏油等潜在问题。通过搭建基于LabVIEW的高效测试平台&#xff0c;可以显著提高发动机的可靠性和使用寿命。下面介绍LabVIEW开…

【C++】C++11新特性详解:可变参数模板与emplace系列的应用

C语法相关知识点可以通过点击以下链接进行学习一起加油&#xff01;命名空间缺省参数与函数重载C相关特性类和对象-上篇类和对象-中篇类和对象-下篇日期类C/C内存管理模板初阶String使用String模拟实现Vector使用及其模拟实现List使用及其模拟实现容器适配器Stack与QueuePriori…

js+jquery实现经典推箱子游戏

纯前端项目&#xff0c;只使用html,css,js,jquery实现经典推箱子游戏&#xff0c;直接下载本地双击index.html即可运行体验。 游戏展示 开始界面 完成游戏 代码展示

【Pytest+Yaml+Allure】实现接口自动化测试框架

一、框架思想 requestsyamlpytestallure实现接口自动化框架。结合数据驱动和分层思想&#xff0c;将代码与数据分离&#xff0c;易维护&#xff0c;易上手。使用yaml编写编写测试用例&#xff0c;利用requests库发送请求&#xff0c;使用pytest管理用例&#xff0c;allure生成…

[HarmonyOS] 解决HMRouter路由地址无法抽取的问题

解决HMRouter路由地址无法抽取的问题 背景 最近开始学习HarmonyOS开发&#xff0c;搭建项目的时候采用了 HMRouter 路由框架&#xff0c;在项目里使用到路由跳转&#xff0c;官方链接在这&#xff1a; https://gitee.com/hadss/hmrouter/blob/master/HMRouterLibrary/README…

ElasticSearch学习了解笔记

搜索引擎的原理&#xff1a; 1、查询分析&#xff08;自然语言处理&#xff09;理解用户需求 2、分词技术 3、关键词搜索匹配 4、搜索排序 lucence Lucene 是一个成熟的权威检索库 Elasticsearch 的搜索原理简单过程是&#xff0c;索引系统通过扫描文章中的每一个词&#xff…

ffmpeg视频滤镜:提取缩略图-framestep

滤镜描述 官网地址 > FFmpeg Filters Documentation 这个滤镜会间隔N帧抽取一帧图片&#xff0c;因此这个可以用于设置视频的缩略图。总体上这个滤镜比较简单。 滤镜使用 滤镜参数 framestep AVOptions:step <int> ..FV....... set frame st…

【C++11】可变参数模板/新的类功能/lambda/包装器--C++

文章目录 一、可变参数模板1、基本语法及原理2、包扩展3、empalce系列接口 二、新的类功能1、默认的移动构造和移动赋值2、成员变量声明时给缺省值3、defult和delete4、final与override 三、STL中一些变化四、lambda1、lambda表达式语法2、捕捉列表3、lambda的应用4、lambda的原…