0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看威廉希尔官方网站 视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Redis抢红包项目

数据分析与开发 来源:数据分析与开发 作者:数据分析与开发 2020-09-24 15:09 次阅读

业务流程分析

功能拆解


新建红包

在 DB、Redis 分别新增一条记录

抢红包(并发)

「使用威廉希尔官方网站 」

Redis 中数据类型的 String 特性的原子递减(DECR key)和减少指定值(DECRBY key decrement)

「业务」

请求 Redis ,当剩余红包个数大于 0,红包个数原子递减,随机获取红包

计算金额,当最后一个红包时,最后一个红包金额=总金额-总已抢红包金额

更新数据库

「查询红包记录」

查询 DB 即可

数据库设计

红包流水表

CREATE TABLE `red_packet_info` ( `id` int(11) NOT NULL AUTO_INCREMENT, `red_packet_id` bigint(11) NOT NULL DEFAULT 0 COMMENT '红包id,采⽤ timestamp+5位随机数', `total_amount` int(11) NOT NULL DEFAULT 0 COMMENT '红包总⾦额,单位分', `total_packet` int(11) NOT NULL DEFAULT 0 COMMENT '红包总个数', `remaining_amount` int(11) NOT NULL DEFAULT 0 COMMENT '剩余红包⾦额,单位 分', `remaining_packet` int(11) NOT NULL DEFAULT 0 COMMENT '剩余红包个数', `uid` int(20) NOT NULL DEFAULT 0 COMMENT '新建红包⽤户的⽤户标识', `create_time` timestamp COMMENT '创建时间', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='红包信息 表,新建⼀个红包插⼊⼀条记录';

红包记录表

CREATE TABLE `red_packet_record` ( `id` int(11) NOT NULL AUTO_INCREMENT, `amount` int(11) NOT NULL DEFAULT '0' COMMENT '抢到红包的⾦额', `nick_name` varchar(32) NOT NULL DEFAULT '0' COMMENT '抢到红包的⽤户的⽤户 名', `img_url` varchar(255) NOT NULL DEFAULT '0' COMMENT '抢到红包的⽤户的头像', `uid` int(20) NOT NULL DEFAULT '0' COMMENT '抢到红包⽤户的⽤户标识', `red_packet_id` bigint(11) NOT NULL DEFAULT '0' COMMENT '红包id,采⽤ timestamp+5位随机数', `create_time` timestamp COMMENT '创建时间', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='抢红包记 录表,抢⼀个红包插⼊⼀条记录';

发红包 API

发红包接口开发

新增一条红包记录

往 mysql 里面添加一条红包记录

往 redis 里面添加一条红包数量记录

往redis里面添加一条红包金额记录

往db中就单纯存入一条记录,Service层和Mapper层,就简单的一条sql语句,主要是提供思路,下面会附案例源码,不要慌

抢红包 API

抢红包功能属于原子减操作

当大小小于 0 时原子减失败

当红包个数为0时,后面进来的用户全部抢红包失败,并不会进入拆红包环节

抢红包功能设计

将红包ID的请求放入请求队列中,如果发现超过红包的个数,直接返回

注意事项

抢到红包不一定能拆成功

抢红包算法拆解

img

通过上图算法得出,靠前面的人,手气最佳几率小,手气最佳,往往在后面

发 100 元,共 10 个红包,那么平均值是 10 元一个,那么发出来的红包金额在 0.01~20 元之间波动

当前面 4 个红包总共被领了 30 元时,剩下 70 元,总共 6 个红包,那么这 6 个红包的金额在 0.01~23.3 元之间波动

抢红包接口开发

「测试」

「发红包」

interwetten与威廉的赔率体系 高并发抢红包(Jmeter压测工具)

因为我发了 10 个红包,金额是 20000,使用压测工具,模拟50个请求,只允许前10个请求能抢到红包,并且金额等于20000。

布隆过滤器

介绍

布隆过滤器是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。

优点

相比于其他的数据结构,布隆过滤器在空间和时间方面都有巨大的优势。布隆过滤器存储空间和插入/查询时间都是常数。另外三列函数相互之间没有关系,方便由硬件并行实现。布隆过滤器不需要存储元素本身,在某些对保密要求非常严格的场合有优势。

缺点

但是布隆过滤器的缺点和有点一样明显。误算率是其中之一。随着存入的元素数量增加,误算率随之增加。但是如果元素数量太少,则使用散列表足矣。

布隆过滤器有什么用

黑客流量攻击:故意访问不存在的数据,导致查程序不断访问DB的数据

黑客安全阻截:当黑客访问不存在的缓存时迅速返回避免缓存及DB挂掉

网页爬虫对 URL 的去重,避免爬取相同的URL地址

反垃圾邮件,从数十亿个垃圾邮件列表中判断某邮件是否垃圾邮件(同理,垃圾短信)

缓存击穿,将已存在的缓存放到布隆中,当黑客访问不存在的缓存时迅速返回避免缓存及 DB 挂掉

布隆过滤器实现会员转盘抽奖

需求

一个抽奖程序,只针对会员用户有效

通过google布隆过滤器存储会员数据

程序启动时将数据放入内存中

google自动创建布隆过滤器

用户ID进来之后判断是否是会员

代码实现

引入依赖

com.google.guava guava 29.0-jre

数据库会员表

CREATE TABLE `sys_user` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `user_name` varchar(11) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '⽤户名', `image` varchar(11) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '⽤户头像', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;

初始化布隆过滤器

dao 层和 dao 映射文件,就单纯的一个 sql 查询,看核心方法,下面会附源码滴,不要慌好嘛

控制层

测试

缺点

内存级别产部

重启即失效

本地内存无法用在分布式场景

不支持大数据量存储

Redis布隆过滤器

优点

可扩展性 Bloom 过滤器

不存在重启即失效或定时任务维护的成本

缺点

需要网络IO,性能比基于内存的过滤器低

布隆过滤器安装

下载

github:https://github.com/RedisBloom/RedisBloom

链接:https://pan.baidu.com/s/16DlKLm8WGFzGkoPpy8y4Aw密码:25w1

「编译」

make

「将 Rebloom 加载到 Redis 中」

先把 Redis 给停掉!!!在 redis.conf 里面添加一行命令->加载模块

loadmodule/usr/soft/RedisBloom-2.2.4/redisbloom.so

「测试布隆过滤器」

SpringBoot 整合 Redis 布隆过滤器

编写两个lua脚本

添加数据到指定名称的布隆过滤器

从指定名称的布隆过滤器获取key是否存在的脚本

localbloomName=KEYS[1] localvalue=KEYS[2] --bloomFilter localresult_1=redis.call('BF.ADD',bloomName,value) returnresult_1

localbloomName=KEYS[1] localvalue=KEYS[2] --bloomFilter localresult_1=redis.call('BF.EXISTS',bloomName,value) returnresult_1

在 RedisService.java 中添加 2 个方法

验证

秒杀

秒杀业务流程图

数据落地存储方案

通过分布式redis减库存

DB存最终订单信息数据

API性能调优

性能瓶颈在高并发秒杀

威廉希尔官方网站 难题在于超卖问题

实现步骤

提前将秒杀数据缓存到 redis

setskuId_start_10_1554045087--秒杀标识 setskuId_access_112000--允许抢购数 setskuId_count_10--抢购计数 setskuId_booked_10--真实秒杀数

秒杀开始前,skuId_start为0,代表活动未开始

当skuId_start改为1时,活动开始,开始秒杀叭

当接受下单数达到sku_count*1.2后,继续拦截所有请求,商品剩余数量为0(为啥接受抢购数为1万2呢,看业务流程图,涉及到“校验订单信息”,一般设置的值要比总数多一点,多多少自己定)

利用 Redis 缓存加速增库存数

"skuId_booked":10000//从0开始累加,秒杀的个数只能加到1万

将用户订单数据写入 MQ(异步方式)。

另外一台服务器监听 mq,将订单信息写入到 DB。

好了,以上就是完整的开发步骤,下面我们开始编写代码

代码实战

网关浏览拦截层

1、先判断秒杀是否已经开始

2、利用 Redis 缓存 incr 拦截流量

用 incr 方法原子加

通过原子加帕努单当前 skuId_access 是否达到最大值

订单信息校验层

1、校验当前用户是否已经买过这个商品

需要存储用户的uid

存数据库效率太低

存Redis value方式数据太大

存布隆过滤器性能高且数据量小(推荐)

2、校验通过直接返回抢购成功

开发lua脚本实现库存扣除

1、库存扣除成功,获取当前最新库存

2、如果库存大于0,即马上进行库存扣除,并且访问抢购成功给用户

3、考虑原子性问题

保证原子性的方式,采用 lua 脚本

采用lua脚本方式保证原子性带来缺点,性能有所下降

不保证原子性缺点,放入请求量可能大于预期

当前扣除库存场景必须保证原子性,否则会导致超卖

4、返回抢购结果

抢购成功

库存没了,抢购失败

控制层

Service 层

布隆过滤器

初始化redis缓存

setskuId_start_10_1554045087--秒杀标识 setskuId_access_112000--允许抢购数 setskuId_count_10--抢购计数 setskuId_booked_10--真实秒杀数

秒杀验证

jmeter 配置

压测秒杀验证原子性

项目下载

链接:https://pan.baidu.com/s/1hZUPRAljkqO05fYluqJBhQ密码:1iwr

尾声

演示的时候,我使用的 Redis 单机的,吞吐量不是很大,感兴趣的,可以自己搭建个 Redis 主从复制+哨兵+集群,然后再测试。

最近比较忙,没时间完善微信抢红包秒杀的原子性。下面那个完整案例抢库存的,亲自使用 Jmeter 压测几次,是原子性的,可以拿来借鉴,感兴趣的同学,可以借鉴下面抢库存的代码,把微信抢红包的功能在完善下,我就不修改啦。

原文标题:Redis 秒杀实战

文章出处:【微信公众号:数据分析与开发】欢迎添加关注!文章转载请注明出处。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • C语言
    +关注

    关注

    180

    文章

    7604

    浏览量

    136764
  • Redis
    +关注

    关注

    0

    文章

    374

    浏览量

    10872

原文标题:Redis 秒杀实战

文章出处:【微信号:DBDevs,微信公众号:数据分析与开发】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    Redis缓存与Memcached的比较

    Redis和Memcached都是广泛使用的内存数据存储系统,它们主要用于提高应用程序的性能,通过减少对数据库的直接访问来加速数据检索。以下是对Redis和Memcached的比较,涵盖了它们的一些
    的头像 发表于 12-18 09:33 124次阅读

    Redis 开源协议调整,我们怎么办?

    许可,时间点恰逢刚刚完成最新一轮融资,宣布的时机耐人寻味。 Redis 协议调整,对云计算厂商的影响 Redis 协议调整听起来可能没什么,但在开源项目领域是一个大问题。这并不是 Redis
    的头像 发表于 05-09 22:59 430次阅读
    <b class='flag-5'>Redis</b> 开源协议调整,我们怎么办?

    Redis 开源社区持续壮大,华为云为 Valkey 项目注入新的活力

    华为云云原生中间件产品团队在过去的几年里,通过向 Redis 开源社区提交代码优化、性能改进和安全性增强的建议,以及积极参与社区讨论和贡献文档,为 Redis 的发展做出了积极的贡献。作为
    的头像 发表于 05-09 22:59 724次阅读
    <b class='flag-5'>Redis</b> 开源社区持续壮大,华为云为 Valkey <b class='flag-5'>项目</b>注入新的活力

    Redis为什么这么快?

    Redis 是基于内存的数据库,那不可避免的就要与磁盘数据库做对比。对于磁盘数据库来说,是需要将数据读取到内存里的,这个过程会受到磁盘 I/O 的限制。而对于内存数据库来说,本身数据就存在于内存里,也就没有了这方面的开销。
    发表于 04-12 10:32 215次阅读
    <b class='flag-5'>Redis</b>为什么这么快?

    Redis开源版与Redis企业版,怎么选用?

    点击“蓝字”关注我们数以千计的企业和数以百万计的开发人员Redis开源版来构建应用程序。但随着用户数量、数据量和地区性的增加,成本、可扩展性、运营和可用性等问题也随之而来。Redis企业版
    的头像 发表于 04-04 08:04 1064次阅读
    <b class='flag-5'>Redis</b>开源版与<b class='flag-5'>Redis</b>企业版,怎么选用?

    数据安全没保障?GaussDB(for Redis) 为你保驾护航

    近日,一些用户反馈,使用的开源 Redis 中新增了几个未知来源的 Key。通过分析发现,用户使用的开源 Redis 没有设置密码,很可能是遭到了 Redis 扩散病毒的攻击,表面上只是新增了几个
    的头像 发表于 03-28 22:09 673次阅读
    数据安全没保障?GaussDB(for <b class='flag-5'>Redis</b>) 为你保驾护航

    GaussDB(for Redis) 特性揭秘:多租户管理

    华为云 GaussDB(for Redis)持续完善企业级增强特性,是名副其实的 "Redis Plus" ,其中很经典的企业级特性是 多租户能力 ,支持添加只读账号、读写账号,且具备强大的 DB
    的头像 发表于 03-28 22:06 743次阅读
    GaussDB(for <b class='flag-5'>Redis</b>) 特性揭秘:多租户管理

    GaussDB(for Redis) 特性揭秘:大 key 治理

      从 DBA 的视角看,大 Key 无疑是引起 Redis 线上问题的常见原因。为了解决大 Key 隐患,业务首先要遵守合理的开发规范,减少大 Key 的产生和访问依赖。但有时大 Key 是在程序
    的头像 发表于 03-28 22:06 666次阅读
    GaussDB(for <b class='flag-5'>Redis</b>) 特性揭秘:大 key 治理

    GaussDB(for Redis) 游戏实践:玩家下线行为上报

    为保护未成年人的身心健康,2007 年国家推出网络游戏防沉迷系统,对未成年人的游戏时间进行限制,游戏厂家需要及时感知用户的下线时间并上报。Redis 是游戏数据库重要选型之一,在基于开源 Redis
    的头像 发表于 03-28 22:03 521次阅读

    新版 Redis 不再“开源”,对使用者都有哪些影响?

    2024 年 3 月 20 日,Redis Labs 宣布从 Redis 7.4 开始,将原先比较宽松的 BSD 源码使用协议修改为 RSAv2和 SSPLv1协议。该变化意味着 Redis
    的头像 发表于 03-27 22:30 490次阅读
    新版 <b class='flag-5'>Redis</b> 不再“开源”,对使用者都有哪些影响?

    Redis实现分布式多规则限流的方式介绍

    市面上很多介绍 Redis 如何实现限流的,但是大部分都有一个缺点,就是只能实现单一的限流,比如 1 分钟访问 1 次或者 60 分钟访问 10 次这种,但是如果想一个接口两种规则都需要满足呢,我们的项目又是分布式项目,应该如何
    的头像 发表于 02-26 10:07 496次阅读
    <b class='flag-5'>Redis</b>实现分布式多规则限流的方式介绍

    Redis官方搜索引擎来了,性能炸裂!

    RediSearch 是一个 Redis 模块,为 Redis 提供查询、二级索引和全文搜索功能。
    的头像 发表于 02-21 10:01 2347次阅读
    <b class='flag-5'>Redis</b>官方搜索引擎来了,性能炸裂!

    Redis7单线程与多线程详解

    主要是指Redis的网络IO和键值对读写是由一个线程来完成的。
    的头像 发表于 01-16 17:33 1851次阅读
    <b class='flag-5'>Redis</b>7单线程与多线程详解

    Redis为LangChain定制AI代理——OpenGPTs

    于构建定制化的人工智能代理。因为Redis具有高速和稳定性的优点,所以LangChain选择了Redis来作为OpenGPTs的默认向量数据库。文
    的头像 发表于 01-13 08:03 836次阅读
    用<b class='flag-5'>Redis</b>为LangChain定制AI代理——OpenGPTs

    linux下Redis常用命令使用

    redis重启,缓存数据还在,redis清缓存数据
    的头像 发表于 12-27 09:56 6573次阅读
    linux下<b class='flag-5'>Redis</b>常用命令使用