当前位置: 首页 > 科技观察

Redis闪杀

时间:2023-03-21 16:10:44 科技观察

为什么要写这个微信抢红包项目?2020年8月22日,公司庆周年,抢到100多个红包🧧,O(∩_∩)O哈哈~业务流程分析功能拆解新建红包在DB和Redis中新增记录抢红包(并发)【使用技术】Redis中数据类型String特性的原子自减(DECR键)和指定值自减(DECRBY键自减)《业务》请求Redis,当剩余红包数大于0,红包数量原子递减,随机获取计算的红包数量。当收到最后一个红包时,最后一个红包的数量=总数量-已抢到的红包总数量。更新数据库“查询红包记录”查询DB可以设计红包表CREATETABLE`red_pa??cket_info`(`id`int(11)NOTNULLAUTO_INCREMENT,`red_pa??cket_id`bigint(11)NOTNULLDEFAULT0COMMENT'红包id,使用timestamp+5随机数',`total_amount`int(11)NOTNULLDEFAULT0COMMENT'红包总量,单位分',`total_packet`int(11)NOTNULLDEFAULT0COMMENT'红包总数',`remaining_amount`int(11)NOTNULLDEFAULT0COMMENT'剩余金额红包数量,单位分',`remaining_packet`int(11)NOTNULLDEFAULT0COMMENT'剩余红包个数',`uid`int(20)NOTNULLDEFAULT0COMMENT'新红包用户用户ID',`create_time`timestampCOMMENT'创建时间',`update_time`timestampNOTNULLDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMPCOMMENT'更新时间',PRIMARYKE`))ENGINE=InnoDBAUTO_INCREMENT=1DEFAULTCHARSET=utf8mb4COMMENT='红包信息表,新建一个红包并插入一条记录';红包记录表CREATETABLE`red_pa??cket_record`(`id`int(11)NOTNULLAUTO_INCREMENT,`amount`int(11)NOTNULLDEFAULT'0'COMMENT'抢红包Amount',`nick_name`varchar(32)NOTNULLDEFAULT'0'COMMENT'抢红包用户名',`img_url`varchar(255)NOTNULLDEFAULT'0'COMMENT'抢红包用户名头像',`uid`int(20)NOTNULLDEFAULT'0'COMMENT'抢红包用户的用户ID',`red_pa??cket_id`bigint(11)NOTNULLDEFAULT'0'COMMENT'红包id,使用时间戳+5位随机数',`create_time`timestampCOMMENT'创建时间',`update_time`timestampNOTNULLDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMPCOMMENT'更新时间',PRIMARYKEY(`id`))ENGINE=InnoDBAUTO_INCREMENT=1DEFAULTCHARSET=utf8mb4COMMENT='插入红包记录表,抢红包记录';发红包API发红包接口开发添加一条新的红包记录到mysql添加一条红包记录到redis添加一条红包金额记录到redis添加一条红包金额记录到db简单存储一条记录,Service层和Mapper层,只是一个简单的sql语句,主要是提供思路,下面会附上案例的源码,大家不要慌,这时候以后进来的用户都抢红包失败,不会进入开箱红包抢红包环节。将请求红包ID的请求放入请求队列。如果发现红包数量超过数量,直接返回公告。如果抢红包,可能无法成功拆解。运气最好的概率很小,运气最好。往往后面发100元,一共10个红包,然后平均一个10元,发的红包数额在0.01到20元之间波动。前4个红包合计为收到30元时,还剩70元,共6个红包,则这6个红包的金额在0.01~23.3元之间波动红包抢接口开发“测试”》redenvelope》模拟高并发抢红包(Jmeter压测工具)因为我发了10个红包,金额20000,所以我用压测工具模拟了50个请求,只允许前10个请求抢红包,并且数量等于20,000BloomfilterBloomfilter简介Bloomfilter是1970年由Bloom提出的,它实际上是一个长二进制向量和一系列随机映射函数。布隆过滤器可用于检索元素是否在集合中。其优点是空间效率和查询时间远超一般算法,缺点是存在一定的误识别率和删除难度。优点与其他数据结构相比,布隆过滤器在空间和时间上具有巨大的优势。布隆过滤器存储空间和插入/查询时间都是常数。其他三列函数相互之间没有任何关系,便于硬件并行实现。布隆过滤器不需要存储元素本身,这在一些保密性要求非常严格的场合具有优势。缺点但是Bloomfilters的缺点也是有那么一点点明显。误算率就是其中之一。随着沉积元素数量的增加,误算率也会增加。但是如果元素个数太少,一个哈希表就足够了。Bloomfilter有什么用黑客流量攻击:故意访问不存在的数据,导致搜索程序不断访问DB数据黑客安全拦截:当黑客访问不存在的缓存时,快速返回,避免缓存和DB挂起网络爬虫到URLDeduplication,避免抓取相同的URL地址反垃圾邮件,从数十亿垃圾邮件列表(类似垃圾短信)缓存分解中判断某封邮件是否为垃圾邮件,将已有的缓存放入Bloom中,当黑客访问某个缓存时不存在,会快速返回,避免缓存和DB挂掉布隆过滤器。会员轮播抽奖需要抽奖程序,仅对会员用户有效。通过GoogleBloom过滤器存储会员数据。当程序启动时,数据将被存储。放入内存,google会自动创建布隆过滤器。用户ID进来后会判断是不是会员码。实现会引入依赖com.google.guavaguava29.0-jre数据库成员表CREATETABLE`sys_user`(`id`int(11)unsignedNOTNULLAUTO_INCREMENT,`user_name`varchar(11)CHARACTERSETutf8mb4DEFAULTNULLCOMMENT'用户名',`image`varchar(11)CHARACTERSETutf8mb4DEFAULTNULLCOMMENT'用户头像',PRIMARYKEY(`id`))ENGINE=InnoDBAUTO_INCREMENT=11DEFAULTCHARSET=utf8;初始化Bloomfilterdao层和dao映射文件,只是一个简单的sql查询,看核心方法,下面会附上源码,不要Panic,controllayertest缺点memorylevelproductiondepartment重启会失败本地内存无法使用在分布式场景下不支持大数据存储成本劣势需要网络IO,性能低于基于内存的过滤器布隆过滤器安装“下载”github:https://github.com/RedisBloom/RedisBloom链接:https://pan.baidu.com/s/16DlKLm8WGFzGkoPpy8y4Aw密码:25w1“编译”make“LoadRebloomintoRedis”首先停止Redis!!!在redis.conf中添加一行命令->loadmoduleloadmodule/usr/soft/RedisBloom-2.2.4/redisbloom.so"TestBloomfilter"SpringBoot集成RedisBloomfilter写两个lua脚本给Bloomfilter添加数据指定名称的脚本从指定名称的布隆过滤器中获取key是否存在localbloomName=KEYS[1]localvalue=KEYS[2]--bloomFilterlocalresult_1=redis.call('BF.ADD',bloomName,value)returnresult_1localbloomName=KEYS[1]localvalue=KEYS[2]--bloomFilterlocalresult_1=redis.call('BF.EXISTS',bloomName,value)returnresult_1在RedisService.java中添加2个方法验证秒杀业务流程图数据落地存储方案采用分布式redis减少库存并将最终订单信息存储在数据库中。API性能调优性能瓶颈在于高并发秒杀技术问题在于超卖问题。实现步骤将秒杀数据提前缓存到redissetskuId_start_10_1554045087--秒杀识别setskuId_access_112000--允许抢购次数setskuId_count_10--快速购买次数setskuId_booked_10--秒杀实际次数秒杀开始前,skuId_start为0,表示该活动还没有开始。当skuId_start改为1时,activity启动,秒杀开始。当接受订单数达到sku_count*1.2时,继续拦截所有请求,商品剩余数量为0(为什么接受抢购数量为10000?看业务流程图,涉及“验证订单信息”.一般设置的值应该比总数多一点,多少你决定)使用Redis缓存加速增加库存"skuId_booked":10000//从0开始累加,秒杀数量只能加到10000,将用户订单数据写入MQ(异步方式)另一台服务器Monitormq并将订单信息写入DB。好了,以上就是完整的开发步骤了,下面开始写代码代码和实际网关浏览拦截层1,先判断秒杀是否启动2,使用Redis缓存incr拦截流量使用incr方法添加当前skuId_access通过atom加上Panusingle是否达到最大值订单信息验证层1.验证当前用户是否已经购买了这个商品,需要存储用户的uid。数据库存储效率太低。Redis值的存储方式太大。推荐)2.验证lua脚本开发成功直接返回抢购实现扣库存1.扣库存成功,获取当前最新库存。保证原子性的方法是使用lua脚本。使用lua脚本来确保原子性带来了缺点。性能下降并不能保证原子性。导致超卖4.返回抢购结果。抢购成功。库存没了,抢购失败。控制层Service层Bloomfilter初始化redis缓存。验证jmeter配置压测秒杀验证原子性项目下载链接:https://pan.baidu.com/s/1hZUPRAljkqO05fYluqJBhQ密码:1iwr最后演示,我用的是Redis单机,吞吐量不是很大,有兴趣的,可以自己搭建一个Redis主从复制+sentinel+集群,然后测试一下。最近比较忙,没时间完善微信抢红包的原子性。在下面的完整案例中,我使用Jmeter进行了多次压力测试。是原子的,可以参考。有兴趣的同学可以借鉴以下抢股票代码,完善微信抢红包功能。不要修改它。本文转载自微信公众号“JavaBuilder”,可通过以下二维码关注。如需转载本文,请联系Java开发者公众号。