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

[Go]-抢购类业务方案

在这里插入图片描述

文章目录

    • 要点:
      • 1. 抢购/秒杀业务的关键挑战
      • 2. 技术方案
      • 3.关键实现点
      • 4.性能优化建议
      • 5.其他考虑因素
    • 细节拆分:
      • 1. **高并发处理**
      • 2.**限流与防护**
      • 3.**库存控制**
      • 4. **异步处理**
      • 5. **数据一致性**
      • 6. **常用架构设计**
      • 7. **代码示例**
      • 8. 进一步优化
      • 9. 注意事项

抢购类业务常用于促销活动,如热销白酒、大月饼、低价显卡、抢票,用户是想挤进去抢到东西,商家端是吸引更多的流量,但是东西就是固定数额,肯定不想被恶意刷单或者超卖等场景,
这就对系统有强烈要求,这类业务需要处理高并发请求,以确保系统的稳定性和公平性,同时避免超卖现象。

抢购类业务(如秒杀)是一种在限定时间内,以极低的价格向消费者提供少量商品的促销活动。

Go语言在此类业务中有相当的优势,内存消耗低,天生支持并发,还可以离线打包,做一些小工具很方便。

公司业务中,防止频繁搜索,爬虫等,会用到令牌桶,进行限流;增减库存、消息队列、锁等,自己遇到的毕竟不全,列举下更多处理形式。

以下列举一些场景,和针对高并发的处理方式

要点:

1. 抢购/秒杀业务的关键挑战

  • 高并发处理: 秒杀活动通常会吸引大量用户同时下单,服务器需要处理大量并发请求。
  • 库存管理: 需要确保库存的准确性,避免超卖。
  • 事务处理: 要保证多个操作的原子性,确保数据一致性。

2. 技术方案

  • 缓存层: 利用Redis等缓存技术,将库存数据保存在缓存中,减少数据库的压力。
  • 消息队列: 通过消息队列(如RabbitMQ、Kafka等)来削峰填谷,将高并发请求排队处理,避免服务器被瞬间击垮。
  • 乐观锁/悲观锁: 使用数据库锁或乐观锁来保证库存的正确性和事务的完整性。

3.关键实现点

  1. Redis 原子操作:通过 Lua 脚本确保扣减库存和判断库存是否充足的操作在 Redis 中是原子性的。
  2. 并发模拟:使用 sync.WaitGroup 模拟多个并发用户抢购。
  3. 库存管理:Redis 的 decr 函数用于减少库存,并且确保不会超卖。

4.性能优化建议

  • 本地缓存:使用内存缓存(如 sync.Map 或 LRU 缓存)减少频繁的 Redis 访问。
  • 读写分离:对高并发的读操作可以通过缓存层或数据库读写分离架构优化。
  • CDN 加速:对于静态资源或非关键请求,可以通过 CDN 缓解服务器压力。

5.其他考虑因素

  • 防止重复抢购:可以通过 Redis 的 setnx 或数据库唯一索引避免用户多次抢购同一商品。
  • 分布式锁:在高并发场景下,可以通过 Redis 分布式锁或数据库锁确保多个实例对库存的操作不会冲突。
  • 请求日志和监控:记录用户请求日志和库存变化,便于监控和追踪问题。

细节拆分:

1. 高并发处理

抢购类业务通常伴随着大量并发请求。Go 语言的高并发处理能力让它在这种场景下非常适用。

  • goroutine 并发:Go 的 goroutine 可以轻松处理大规模并发。抢购时每个用户的请求可以用 goroutine 处理。

  • 限流:为了防止服务器超载,可以引入限流机制。常见的限流方式包括:

    • 漏桶算法:按固定速率处理请求,防止过多请求冲击系统。
    • 令牌桶算法:允许一定程度的突发请求,超出限额后将请求拒绝。

    Go 中可以使用第三方库如

    golang.org/x/time/rate
    

    实现限流。

2.限流与防护

防止大量恶意请求和超高并发打垮系统,通常会采取以下策略:

  • 接口限流:通过令牌桶算法、漏桶算法或 Redis 实现接口限流,控制每秒允许的请求数量。
  • IP 限制:限制同一个 IP 的请求频率,防止 DDoS 攻击。
  • 用户限流:对于每个用户设置抢购次数的限制,防止恶意刷单。

3.库存控制

抢购业务中,库存的控制非常关键,不能超卖或少卖。常用的方法有:

  • 本地缓存库存:在抢购开始时将库存加载到应用层内存中进行扣减,以提高响应速度。用完库存后,再同步更新到数据库中。
  • 分布式锁:在多个应用实例之间控制库存时,可以使用分布式锁来保证同一时间只有一个实例操作库存,防止超卖。可以通过 Redis 的 SETNX 实现分布式锁,或使用诸如 Etcd、Zookeeper 等注册中心自带的锁机制。
  • 乐观锁:通过数据库字段(如版本号或库存数量)进行更新时的版本控制来防止超卖。MySQL 支持通过 UPDATE 操作中的 WHERE 条件来进行版本检查。
  • **Lua脚本:**Redis 可以用来存储库存数据,并且通过 Lua 脚本实现原子性操作,避免超卖的情况。Redis 的高性能特性也非常适合高并发场景。
  • 预减库存:当用户发起抢购请求时,先在 Redis 中预减库存,确保高并发情况下不会超卖。
  • 最终库存确认:抢购成功后,再将最终的订单写入数据库,并从 Redis 中同步更新实际库存。如果用户未成功下单,Redis 中的库存会回滚。

4. 异步处理

抢购业务中,许多操作可以异步化处理,如订单生成、库存核减、用户通知等。

  • 消息队列:可以将用户的抢购请求推入消息队列(如 Kafka、RabbitMQ),后续再异步处理订单生成和库存扣减。这样可以避免数据库的直接冲击,提高系统的稳定性。
  • 异步任务队列:针对抢购结束后的订单处理和支付,可以使用异步任务队列(如 Celery)来处理非实时任务。

5. 数据一致性

为了确保数据在高并发下的一致性,需要控制并发修改的顺序和处理好数据库事务。

  • 事务机制:在处理订单时,可以通过数据库的事务机制来保证库存扣减和订单生成的一致性。
  • 分布式事务:在分布式架构下,通过 TCC (Try-Confirm-Cancel) 模式、2PC (Two-phase Commit) 或 SAGA 模式来保证分布式系统中的事务一致性。
  • 分布式锁:如果多台服务器处理抢购订单,可以通过 Redis 分布式锁来保证同一时刻只有一台服务器操作库存数据,防止并发操作造成超卖。

6. 常用架构设计

抢购类业务的架构通常包括以下几部分:

  1. 前端限流:通过 Nginx 等代理服务器进行限流,过滤掉部分请求。
  2. 服务端限流:使用 Redis、令牌桶等方式在服务端进一步限流,防止请求压力过大。
  3. 库存预加载:将库存放入 Redis 或本地内存中进行预处理,以提高响应速度。
  4. 异步处理:将订单生成、库存扣减、用户通知等操作异步化处理,提升抢购效率。
  5. 数据持久化:最终将抢购结果持久化到数据库中,并同步更新库存信息。

7. 代码示例

以下是一个简单的Go实现,用Redis管理库存,并处理用户的抢购请求:

package mainimport ("fmt""github.com/go-redis/redis/v8""context""sync"
)var ctx = context.Background()func main() {rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",})// 初始化库存数量rdb.Set(ctx, "item_stock", 100, 0)// 模拟并发抢购var wg sync.WaitGroupfor i := 0; i < 200; i++ {wg.Add(1)go func(userID int) {defer wg.Done()err := purchaseItem(rdb, userID)if err != nil {fmt.Printf("User %d failed to purchase: %s\n", userID, err)} else {fmt.Printf("User %d successfully purchased the item.\n", userID)}}(i)}wg.Wait()
}// 处理抢购请求
func purchaseItem(rdb *redis.Client, userID int) error {// 乐观锁机制,减少库存err := rdb.Watch(ctx, func(tx *redis.Tx) error {stockStr, err := tx.Get(ctx, "item_stock").Result()if err != nil {return err}stock, err := strconv.Atoi(stockStr)if err != nil || stock <= 0 {return fmt.Errorf("Out of stock")}// 使用事务保证库存减少的原子性_, err = tx.TxPipelined(ctx, func(pipe redis.Pipeliner) error {pipe.Decr(ctx, "item_stock")return nil})return err}, "item_stock")return err
}

这个示例采用乐观锁,当然也可以采用Lua脚本配合Redis扣减库存(为了防止库存超卖,通常会使用 Redis 的原子操作 来实现库存扣减)

// Redis 脚本实现原子扣减库存
local inventory = redis.call('GET', KEYS[1])
if (tonumber(inventory) <= 0) thenreturn 0
end
redis.call('DECR', KEYS[1])
return 1

8. 进一步优化

  • 防止重复下单: 利用Redis的SETNX命令可以防止用户重复下单。
  • 分布式锁: 在分布式系统中,使用Redis的分布式锁机制,确保只有一个请求能修改库存。
  • 动态限流: 利用令牌桶等算法对并发请求进行限流,防止流量瞬间过载。

9. 注意事项

  • 幂等性: 秒杀系统中,每个操作必须是幂等的,以防止因网络延迟或重试机制造成数据的不一致。
  • 数据库优化: 针对热点数据表的读写,需要做好索引优化、分库分表等设计。

通过这些手段,能够有效地提高抢购类业务的性能和稳定性。

相关文章:

[Go]-抢购类业务方案

文章目录 要点&#xff1a;1. 抢购/秒杀业务的关键挑战2. 技术方案3.关键实现点4.性能优化建议5.其他考虑因素 细节拆分&#xff1a;1. **高并发处理**2.**限流与防护**3.**库存控制**4. **异步处理**5. **数据一致性**6. **常用架构设计**7. **代码示例**8. 进一步优化9. 注意…...

Android 源码多个Launcher设置默认Launcher

目录 第一部分、android10之前 一.多个launcher 启动设置默认launcher的核心类 二 在自定义服务里面设置默认Launcher 第二部分、android10之后 一、Launcher应用内置并设置为默认Launcher 1.通过ResolverActivity.java设置为默认Launcher 改法一&#xff1a; 改法二&am…...

计算机毕业设计 网上体育商城系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…...

深度学习中实验、观察与思考的方法与技巧

在深度学习中&#xff0c;实验、观察与思考是理解和改进模型性能的关键环节。以下是一些有效的方法与技巧&#xff0c;可以帮助你在深度学习实践中系统性地开展实验、分析结果并进行深入思考&#xff1a; 1. 明确实验目标 在开始实验前&#xff0c;确保对实验的目标有清晰的定…...

记一次 FastDFS 存储节点迁移:基于 scp 的实践与经验分享

一、背景 某某项目&#xff0c;机房到期&#xff0c;需要迁移至其他机房&#xff1b; 此项目已经运行了3年多&#xff0c;fastdfs累计数据大概在250G 左右&#xff0c;现需要把旧的fastdfs数据迁移到新的fastdfs上&#xff1b; 采用scp物理迁移数据的方式&#xff0c;停机迁移…...

http连接github远程仓库密码问题解决办法

目录 一、问题&#xff1a;使用http连接失败 二、解决办法&#xff1a;使用个人访问令牌。 1、生成访问令牌&#xff1a; 步骤 1: 登录 GitHub 步骤 2: 进入设置页面 步骤 3: 生成新的访问令牌 步骤 4: 配置访问令牌 步骤 5: 复制令牌 2. 使用访问令牌 一、问题&#…...

LAMP环境下项目部署

目录 目录 1、创建一台虚拟机 centos 源的配置 备份源 修改源 重新加载缓存 安装软件 2、关闭防火墙和selinux 查看防火墙状态 关闭防火墙 查看SELinux的状态 临时关闭SELinux 永久关闭SELinux&#xff1a;编辑SELinux的配置文件 配置文件的修改内容 3、检查系统…...

Visual Studio 2022从外部引入dll导致的问题

这里以我学MapGIS二次开发的一个小demo为例 一、如何引入dll 1、在解决方案资源管理器中&#xff0c;有个引用的选项 2、然后右键点击添加引用 点击之后会出现如下&#xff1a; 3、点击浏览选项&#xff0c;选择想要引入dll的路径&#xff0c;这里我选择下载MapGIS 10的路径 …...

大模型从失败中学习 —— 微调大模型以提升Agent性能

人工智能咨询培训老师叶梓 转载标明出处 以往的研究在微调LLMs作为Agent时&#xff0c;通常只使用成功的交互轨迹&#xff0c;而丢弃了未完成任务的轨迹。这不仅造成了数据和资源的浪费&#xff0c;也可能限制了微调过程中可能的优化路径。论文《Learning From Failure: Integ…...

10.web应用体系以及windows网络常见操作应用

一、Dos命令 1.启动方式&#xff1a;winR&#xff0c;输入cmd 2.切换盘符/路径&#xff1a;盘符名称&#xff1a; &#xff08;C:) cd 目录 &#xff08;cd B111&#xff09;&#xff08;目录名按table键自动补全&#xff09; 3.查看目录&#xff1a;dir dir /p 分页展示目录及…...

【数据结构与算法 | 灵神题单 | 前后指针(链表)篇】力扣19, 61,1721

1. 力扣19&#xff1a;删除链表的倒数第N个节点 1.1 题目&#xff1a; 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5]示例 2&#xff1a; …...

机器学习之实战篇——MNIST手写数字0~9识别(全连接神经网络模型)

机器学习之实战篇——Mnist手写数字0~9识别&#xff08;全连接神经网络模型&#xff09; 文章传送MNIST数据集介绍&#xff1a;实验过程实验环境导入模块导入MNIST数据集创建神经网络模型进行训练&#xff0c;测试&#xff0c;评估模型优化 文章传送 机器学习之监督学习&#…...

ICLR2024: 大视觉语言模型中对象幻觉的分析和缓解

https://arxiv.org/pdf/2310.00754 https://github.com/YiyangZhou/LURE 背景 对象幻觉&#xff1a;生成包含图像中实际不存在的对象的描述 早期的工作试图通过跨不同模式执行细粒度对齐&#xff08;Biten et al.&#xff0c;2022&#xff09;或通过数据增强减少对象共现模…...

数据库系统 第54节 数据库优化器

数据库优化器是数据库管理系统&#xff08;DBMS&#xff09;中的一个关键组件&#xff0c;它的作用是分析用户的查询请求&#xff0c;并生成一个高效的执行计划。这个执行计划定义了如何访问数据和执行操作&#xff0c;以最小化查询的执行时间和资源消耗。以下是数据库优化器的…...

微服务杂谈

几个概念 还是第一次听说Spring Cloud Alibaba &#xff0c;真是孤陋寡闻了&#xff0c;以前只知道 SpringCloud 是为了搭建微服务的&#xff0c;spring boot 则是快速创建一个项目&#xff0c;也可以是一个微服务 。那么SpringCloud 和 Spring boot 有什么区别呢&#xff1f;S…...

【Pandas操作2】groupby函数、pivot_table函数、数据运算(map和apply)、重复值清洗、异常值清洗、缺失值处理

1 数据清洗 #### 概述数据清洗是指对原始数据进行处理和转换&#xff0c;以去除无效、重复、缺失或错误的数据&#xff0c;使数据符合分析的要求。#### 作用和意义- 提高数据质量&#xff1a;- 通过数据清洗&#xff0c;数据质量得到提升&#xff0c;减少错误分析和错误决策。…...

如何分辨IP地址是否能够正常使用

在互联网的日常使用中&#xff0c;无论是进行网络测试、网站访问、数据抓取还是远程访问&#xff0c;一个正常工作的IP地址都是必不可少的。然而&#xff0c;由于各种原因&#xff0c;IP地址可能无法正常使用&#xff0c;如被封禁、网络连接问题或配置错误等。本文将详细介绍如…...

Sqoop 数据迁移

Sqoop 数据迁移 一、Sqoop 概述二、Sqoop 优势三、Sqoop 的架构与工作机制四、Sqoop Import 流程五、Sqoop Export 流程六、Sqoop 安装部署6.1 下载解压6.2 修改 Sqoop 配置文件6.3 配置 Sqoop 环境变量6.4 添加 MySQL 驱动包6.5 测试运行 Sqoop6.5.1 查看Sqoop命令语法6.5.2 测…...

【数据结构】排序算法系列——希尔排序(附源码+图解)

希尔排序 算法思想 希尔排序&#xff08;Shell Sort&#xff09;是一种改进的插入排序算法&#xff0c;希尔排序的创造者Donald Shell想出了这个极具创造力的改进。其时间复杂度取决于步长序列&#xff08;gap&#xff09;的选择。我们在插入排序中&#xff0c;会发现是对整体…...

c++(继承、模板进阶)

一、模板进阶 1、非类型模板参数 模板参数分类类型形参与非类型形参。 类型形参即&#xff1a;出现在模板参数列表中&#xff0c;跟在class或者typename之类的参数类型名称。 非类型形参&#xff0c;就是用一个常量作为类(函数)模板的一个参数&#xff0c;在类(函数)模板中…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别

一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

基础测试工具使用经验

背景 vtune&#xff0c;perf, nsight system等基础测试工具&#xff0c;都是用过的&#xff0c;但是没有记录&#xff0c;都逐渐忘了。所以写这篇博客总结记录一下&#xff0c;只要以后发现新的用法&#xff0c;就记得来编辑补充一下 perf 比较基础的用法&#xff1a; 先改这…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

HTML前端开发:JavaScript 常用事件详解

作为前端开发的核心&#xff0c;JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例&#xff1a; 1. onclick - 点击事件 当元素被单击时触发&#xff08;左键点击&#xff09; button.onclick function() {alert("按钮被点击了&#xff01;&…...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...