Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >秒杀场景实践之抢红包(一) —— 常用解决方案

秒杀场景实践之抢红包(一) —— 常用解决方案

作者头像
草堂笺
发布于 2019-12-20 09:31:35
发布于 2019-12-20 09:31:35
1.3K00
代码可运行
举报
文章被收录于专栏:代码如诗代码如诗
运行总次数:0
代码可运行

.example_responsive_1 { width: 200px; height: 50px; } @media(min-width: 290px) { .example_responsive_1 { width: 270px; height: 50px; } } @media(min-width: 370px) { .example_responsive_1 { width: 339px; height: 50px; } } @media(min-width: 500px) { .example_responsive_1 { width: 468px; height: 50px; } } @media(min-width: 720px) { .example_responsive_1 { width: 655px; height: 50px; } } @media(min-width: 800px) { .example_responsive_1 { width: 728px; height: 50px; } } (adsbygoogle = window.adsbygoogle || []).push({});

秒杀场景实践之抢红包(一) —— 常用解决方案

目录

  • 秒杀场景实践之抢红包(一) —— 常用解决方案
    • 前言
    • 分析
      • 场景
      • 业务
      • 技术
    • 方案一 —— 预分配
      • 适用场景
      • 简要描述
      • 实现细节
        • 流程
        • 备注
    • 方案二 —— 实时分配
      • 适用场景
      • 实现细节
        • 流程
        • 备注
    • 细节及优化
    • 结语

秒杀场景实践之抢红包常用解决方案 文章地址: https://cloud.tencent.com/developer/article/1557573

前言

秒杀场景在生活中几乎随处可见, 不论是商品抢购、春运抢票还是一个随处可见的红包, 都会涉及到秒杀的场景. 在面试中, 秒杀业务的设计也成为热门题目为面试官和应聘者津津乐道.

接下来, 本文将针对秒杀场景中的抢红包实现方案进行分享, 包括红包业务常见的实现方案, 瓶颈及优化.

分析

场景

红包的应用场景有很多, 如随机红包、定额红包等, 甚至还有结合其他促销业务的红包变种如抢购物津贴等. 但从技术的角度来看, 不论玩法有多少变化, 其核心都是相似的:

  • 稳定: 扛得住突发的大流量, 确保红包都能成功派发.
  • 准确: 数据一定要正确, 不能出现超额派发的情况.

业务

抢红包可能会由于业务需求不同而产生很多变种, 设计上要足够抽象, 不能为了抢现金红包和抢购物津贴红包写多份相似的代码. 抢到红包的后置操作可以作为消息, 由不同的业务模块自行处理.

技术

抢红包核心业务不复杂, 其关键点在于应对高并发、资源争用等.

  • 高并发: 异步、横向扩展负载均衡、限流等.
  • 读多写少: 缓存.
  • 资源争用: 原子操作, 缓存或数据库等层面可进行控制. 如使用Lua脚本进行减库存操作.

方案一 —— 预分配

适用场景

红包数量相对合理, 很少产生库存剩余的情况、用户量级不大的情况.

  • 优势: 实现简单、配合缓存很容易应对高并发
  • 不足: 频繁发放较多数量大的红包会导致一次性写入大量分配记录, 如果领取的人不多, 会产生很多无效数据.

简要描述

预分配是在发放红包时, 根据红包总额和数量、按照既定算法进行分配, 提前创建好全部的红包分配记录. 领取时只是将红包分配记录进行更新.

比较适合系统发放的红包(面向某一标签的全部用户群体, 发出的红包基本会被领取完), 不适合用户群组红包(无法控制领取红包人数, 当红包个数远大于群组人数的情况下, 无效数据比较多, 比如在一个10人群组发放一个数量为1000的红包).

实现细节

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
graph LR
A(创建红包, 个数为N) --> B(预分配N条红包领取记录)
B --> C(开始抢红包)
C --> D(先到先得)
流程
  • 在红包开抢前, 预先分配好红包领取记录, 领取记录的用户ID为负值.
  • 开抢后, 开放唯一领取红包的入口
  • 领取操作核心就是更新红包分配记录: -- 此处划重点 ( ̄▽ ̄)" UPDATE IGNORE record SET user_id = {userId}, gmt_receive = UNIX_TIMESTAMP() WHERE red_envelop_id = 1 AND user_id < 0 LIMIT 1; -- red_envelop_id + user_id 有唯一约束

红包发放记录

ID

总金额

数量

1

100

3

红包分配记录

unique: 红包ID+领取用户ID

ID

红包ID

金额

领取用户ID

领取时间

1

1

10

-1

0

2

1

60

-2

0

3

1

30

-3

0

备注
  • UPDATE IGNORE ... LIMIT 1 : 解决了资源争用问题, 确保并发请求下红包的领取的数据正确性.
  • red_envelop_id + user_id : 创建索引并唯一约束, 确保对于同一个红包同一用户只能领取一次.
  • 预分配的user_id为负值: 因为red_envelop_id + user_id 有唯一约束.
  • 对于一般流量的小型活动, 这种方式实现简单、成本低, 不引入缓存的情况下只用一个MySQL基本也能扛得住.

版权声明

代码语言:txt
AI代码解释
复制
 本文发布于[朴瑞卿的博客](https://blog.piaoruiqing.com/), 允许非商业用途转载, 但转载必须保留原作者[朴瑞卿](https://blog.piaoruiqing.com/) 及链接:[https://blog.piaoruiqing.com](https://blog.piaoruiqing.com/).
代码语言:txt
AI代码解释
复制
 如有授权方面的协商或合作, 请联系邮箱: [piaoruiqing@gmail.com](https://blog.piaoruiqing.com/mailto:piaoruiqing@gmail.com). 

方案二 —— 实时分配

适用场景

领取人数无法估计、频发退款, 如群组红包(经常发生剩余退款)

实现细节

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
graph LR
A(创建红包, 个数为N) --> B(首次写入缓存)
B --> C(抢红包)
C --> D(读取或加载缓存)
D --> E(分配红包金额)
E --> F(写入缓存--原子操作)
F --> G(落库)
流程
  • 开抢前将红包信息加载到缓存, 首次加载时间可长一些
  • 抢红包: 从缓存读取(没有则加载), 分配红包后原子更新缓存(若已发放完毕则直接返回失败)
  • 缓存更新后写入数据库(校验数据正确性)

红包发放记录

ID

总金额

数量

剩余金额

剩余数量

1

100

3

100

3

红包分配记录

unique: 红包ID+领取用户ID

ID

红包ID

金额

领取用户ID

领取时间

备注
  • 首次缓存加载时间要稍长一点: 红包刚开始发放时可能会有较大的突发流量, 此时去DB加载缓存不合适.
  • 缓存可以不用和数据库保证强一致: 数据的正确性由数据库进行维护, 如: 缓存扣除了红包额度, 但更新数据库时发生了异常, 此时缓存不需要回滚, 待缓存失效后重新加载即可.(所以缓存时间可以是几秒钟, 不用太长)
  • 更新缓存可以考虑使用Lua脚本以保证原子性.
  • 实时分配红包不会产生无效的记录, 适合大多数场景, 但实现比预分配复杂的多.

细节及优化

  • 客户端点击频率控制能在一定程度上减少流量.
  • 红包领光后在缓存一层拦截掉全部请求, 直接返回失败.
  • 网关层进行限流.

结语

秒杀场景其特点是高并发、读多写少、资源争用, 每一个点都需要根据其业务场景选择适合的解决方案, 如使用缓存解决频繁读取的问题、使用队列解决数据库性能瓶颈等.

对于抢红包业务来说, 预分配和实时分配都是行之有效的方案, 各有优劣, 具体选择哪种, 还是要看业务需求.

© 2019, 朴瑞卿.

版权声明

代码语言:txt
AI代码解释
复制
 本文发布于[朴瑞卿的博客](https://blog.piaoruiqing.com/), 允许非商业用途转载, 但转载必须保留原作者[朴瑞卿](https://blog.piaoruiqing.com/) 及链接:[https://blog.piaoruiqing.com](https://blog.piaoruiqing.com/).      如有授权方面的协商或合作, 请联系邮箱: [piaoruiqing@gmail.com](https://blog.piaoruiqing.com/mailto:piaoruiqing@gmail.com).
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Kubernetes(二) 应用部署
.example_responsive_1 { width: 200px; height: 50px; } @media(min-width: 290px) { .example_responsive_1 { width: 270px; height: 50px; } } @media(min-width: 370px) { .example_responsive_1 { width: 339px; height: 50px; } } @media(min-width: 500px) { .example_responsive_1 { width: 468px; height: 50px; } } @media(min-width: 720px) { .example_responsive_1 { width: 655px; height: 50px; } } @media(min-width: 800px) { .example_responsive_1 { width: 728px; height: 50px; } } (adsbygoogle = window.adsbygoogle || []).push({});
草堂笺
2019/12/20
1K0
Kubernetes(二) 应用部署
开放API网关实践(三) —— 限流
.example_responsive_1 { width: 200px; height: 50px; } @media(min-width: 290px) { .example_responsive_1 { width: 270px; height: 50px; } } @media(min-width: 370px) { .example_responsive_1 { width: 339px; height: 50px; } } @media(min-width: 500px) { .example_responsive_1 { width: 468px; height: 50px; } } @media(min-width: 720px) { .example_responsive_1 { width: 655px; height: 50px; } } @media(min-width: 800px) { .example_responsive_1 { width: 728px; height: 50px; } } (adsbygoogle = window.adsbygoogle || []).push({});
草堂笺
2019/12/20
1.3K0
开放API网关实践(三) —— 限流
一些秒杀以及抢红包场景下的技术分析
抢红包的场景有点像秒杀,但是要比秒杀简单点。 因为秒杀通常要和库存相关。而抢红包则可以允许有些红包没有被抢到,因为发红包的人不会有损失,没抢完的钱再退回给发红包的人即可。 另外像小米这样的抢购也要比淘宝的要简单,也是因为像小米这样是一个公司的,如果有少量没有抢到,则下次再抢,人工修复下数据是很简单的事。而像淘宝这么多商品,要是每一个都存在着修复数据的风险,那如果出故障了则很麻烦。
小勇DW3
2018/09/29
1.3K0
一些秒杀以及抢红包场景下的技术分析
用了这么久HTTP, 你是否了解Content-Length和Transfer-Encoding ?
.example_responsive_1 { width: 200px; height: 50px; } @media(min-width: 290px) { .example_responsive_1 { width: 270px; height: 50px; } } @media(min-width: 370px) { .example_responsive_1 { width: 339px; height: 50px; } } @media(min-width: 500px) { .example_responsive_1 { width: 468px; height: 50px; } } @media(min-width: 720px) { .example_responsive_1 { width: 655px; height: 50px; } } @media(min-width: 800px) { .example_responsive_1 { width: 728px; height: 50px; } } (adsbygoogle = window.adsbygoogle || []).push({});
草堂笺
2019/12/20
8140
用了这么久HTTP, 你是否了解Content-Length和Transfer-Encoding ?
开放API网关实践(二) —— 重放攻击及防御
.example_responsive_1 { width: 200px; height: 50px; } @media(min-width: 290px) { .example_responsive_1 { width: 270px; height: 50px; } } @media(min-width: 370px) { .example_responsive_1 { width: 339px; height: 50px; } } @media(min-width: 500px) { .example_responsive_1 { width: 468px; height: 50px; } } @media(min-width: 720px) { .example_responsive_1 { width: 655px; height: 50px; } } @media(min-width: 800px) { .example_responsive_1 { width: 728px; height: 50px; } } (adsbygoogle = window.adsbygoogle || []).push({});
草堂笺
2019/12/20
2K0
开放API网关实践(二) —— 重放攻击及防御
MySQL查漏补缺
.example_responsive_1 { width: 200px; height: 50px; } @media(min-width: 290px) { .example_responsive_1 { width: 270px; height: 50px; } } @media(min-width: 370px) { .example_responsive_1 { width: 339px; height: 50px; } } @media(min-width: 500px) { .example_responsive_1 { width: 468px; height: 50px; } } @media(min-width: 720px) { .example_responsive_1 { width: 655px; height: 50px; } } @media(min-width: 800px) { .example_responsive_1 { width: 728px; height: 50px; } } (adsbygoogle = window.adsbygoogle || []).push({});
草堂笺
2019/12/20
2.4K0
记一次Redis连接超限排查
.example_responsive_1 { width: 200px; height: 50px; } @media(min-width: 290px) { .example_responsive_1 { width: 270px; height: 50px; } } @media(min-width: 370px) { .example_responsive_1 { width: 339px; height: 50px; } } @media(min-width: 500px) { .example_responsive_1 { width: 468px; height: 50px; } } @media(min-width: 720px) { .example_responsive_1 { width: 655px; height: 50px; } } @media(min-width: 800px) { .example_responsive_1 { width: 728px; height: 50px; } } (adsbygoogle = window.adsbygoogle || []).push({});
草堂笺
2019/12/20
1.6K0
记一次Redis连接超限排查
我是如何通过Nginx日志实时封禁风险IP的
.example_responsive_1 { width: 200px; height: 50px; } @media(min-width: 290px) { .example_responsive_1 { width: 270px; height: 50px; } } @media(min-width: 370px) { .example_responsive_1 { width: 339px; height: 50px; } } @media(min-width: 500px) { .example_responsive_1 { width: 468px; height: 50px; } } @media(min-width: 720px) { .example_responsive_1 { width: 655px; height: 50px; } } @media(min-width: 800px) { .example_responsive_1 { width: 728px; height: 50px; } } (adsbygoogle = window.adsbygoogle || []).push({});
草堂笺
2019/12/20
1.2K0
我是如何通过Nginx日志实时封禁风险IP的
Redis 秒杀实战
原文链接:https://www.cnblogs.com/chenyanbin/p/13587508.html
cxuan
2020/09/04
8540
Redis 秒杀实战
社交软件红包技术解密(十一):最全解密微信红包随机算法(含代码实现)
这个系列文章已经整理了10篇,但都没有涉及到具体的红包算法实现,主要有以下两方面原因。
JackJiang
2020/08/26
1.4K0
最全解密微信红包随机算法(含代码实现)
这个系列文章已经整理了10篇,但都没有涉及到具体的红包算法实现,主要有以下两方面原因。
JackJiang
2020/09/18
15K0
最全解密微信红包随机算法(含代码实现)
高频面试题:秒杀场景设计
秒杀这个话题到现在来说已经是一个老生常谈的话题了,不过因为又临近一年一度的双11,而且发现前段时间无论是阿里还是腾讯一些大厂其实还是在频繁的问到这个场景题,所以还是准备拿出来说说。
艾小仙
2021/01/05
1.6K0
高频面试题:秒杀场景设计
QQ 红包技术方案全解密 (一)
serena
2017/06/06
6.3K3
QQ 红包技术方案全解密 (一)
听说你会架构设计?来,弄一个红包系统
大家好,我是小❤,一个漂泊江湖多年的 985 非科班程序员,曾混迹于国企、互联网大厂和创业公司的后台开发攻城狮。
xin猿意码
2023/12/14
1.3K0
听说你会架构设计?来,弄一个红包系统
微信红包后台系统设计
微信作为一款国民应用,已经进入每个互联网用户手中,微信支付作为其杀手级功能,在每一次佳节期间都会产生巨大流量,以2017年除夕为例,峰值QPS在76w左右,整个系统核心功能和金融相关,需要做好高可用。
春哥大魔王
2020/06/02
8K0
微信红包后台系统设计
如何搭建一个红包架构?
做技术将来想做架构师,就要多见多想,大家都有过使用微信红包的经验,如何做一个能够承受高并发的红包架构是一个值得探讨的问题。 微信金额什么时候算? 微信的金额是拆出来时候实时算的,不是预先分配的,采用纯内存计算,不需要预先空间存储。 注:京东金融的红包是预先算出来放到CDN上,后期抢红包的行为主要是分配红包ID的行为。所以这样看来京东红包还是取巧了。 实时性:明明抢到了红包,点开后发现没有? 2015年以后红包的拆和抢是分离的,需要点两次,会出现抢到红包,点开之后红包领完的情况。 注:每个业务逻辑的拆分都可以
春哥大魔王
2018/04/16
1.9K0
高并发业务场景下的秒杀解决方案
本文内容是对并发业务场景出现超卖情况而写的一pian解决方案。主要是利用到了 Redis 中的队列技术。
兔云小新LM
2019/10/16
1.4K0
Kubernetes(一) 跟着官方文档从零搭建K8S
.example_responsive_1 { width: 200px; height: 50px; } @media(min-width: 290px) { .example_responsive_1 { width: 270px; height: 50px; } } @media(min-width: 370px) { .example_responsive_1 { width: 339px; height: 50px; } } @media(min-width: 500px) { .example_responsive_1 { width: 468px; height: 50px; } } @media(min-width: 720px) { .example_responsive_1 { width: 655px; height: 50px; } } @media(min-width: 800px) { .example_responsive_1 { width: 728px; height: 50px; } } (adsbygoogle = window.adsbygoogle || []).push({});
草堂笺
2019/12/20
2.1K0
Kubernetes(一) 跟着官方文档从零搭建K8S
社交软件红包技术解密(五):微信红包系统是如何实现高可用性的
微信红包业务量级的高速发展,对后台系统架构的可用性要求越来越高。在保障微信红包业务体验的前提下,红包后台系统进行了一系列高可用方面的优化设计。
JackJiang
2025/01/15
2170
社交软件红包技术解密(五):微信红包系统是如何实现高可用性的
阿里、百度、美团都在用的‘高并发系统设计’秒杀、抢红包、12306抢票等高并发场景
"秒杀活动"、"抢红包"、"微博热搜"、"12306抢票"、"共享单车拉新"等都是高并发的典型业务场景,那么如何解决这些业务场景背后的难点问题呢? 秒杀系统中,QPS达到10万/s时,如何定位并解决业
欧阳愠斐
2020/05/22
1.6K0
阿里、百度、美团都在用的‘高并发系统设计’秒杀、抢红包、12306抢票等高并发场景
相关推荐
Kubernetes(二) 应用部署
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验