抢红包设计
抢红包大致可以分为2步:1 发红包 ;2 抢红包
发红包流程

为了突出红包设计主题,以下设计会忽略支付流程、24H过期退款剩余金额、用户领取红包余额到账等业务,则简化后的相关表设计如下:
CREATE TABLE `red_record` (`id` bigint NOT NULL AUTO_INCREMENT,`user_id` bigint NOT NULL COMMENT '用户id',`total` int(11) NOT NULL COMMENT '人数',`amount` int(11) NOT NULL COMMENT '总金额(单位为分)',`status` tinyint(4) DEFAULT '1' COMMENT '状态:1 已发送,2 已抢完',`create_time` datetime DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8 COMMENT='发红包记录';
// 忽略 支付流程 和 24H过期退还剩余金额CREATE TABLE `red_rob_record` (`id` int(11) NOT NULL AUTO_INCREMENT,`user_id` int(11) NOT NULLL COMMENT '用户ID',`red_record_id` int(11) COMMENT '红包ID',`amount` int(11) NOT NULL COMMENT '红包金额(单位为分)',`rob_time` datetime DEFAULT NULL COMMENT '时间',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=118 DEFAULT CHARSET=utf8 COMMENT='抢红包记录';
红包算法选取二倍均值算法,保证无论用户是先抢还是后抢都保证抢到金额的概率一致。
二倍均值算法逻辑实现图:

算法代码实现:
/*** 二倍均值法计算红包金额* @param totalAmount 总金额 (单位分)* @param peopleNum 总人数* @return*/public static List<Integer> divideRedPackage(Integer totalAmount,Integer peopleNum) {List<Integer> list = new ArrayList<>();//金额和人数都必须大于0if (totalAmount > 0 && peopleNum > 0) {//重置入参Integer restAmount = totalAmount;Integer restNum = peopleNum;//计算红包while (restNum - 1 > 0) {//计算红包金额 高效随机数 随机范围 左闭右开 [1,restAmount / restNum * 2)//随机数使用高效的ThreadLocalRandomint amount = ThreadLocalRandom.current().nextInt(restAmount / restNum * 2 - 1) + 1;//金额减少 人数减一restAmount -= amount;restNum--;list.add(amount);}//最后一个人的红包list.add(restAmount);}return list;}
发红包代码实现:
/*** 发红包* @param totalAmount 总金额 (单位分)* @param peopleNum 总人数* @param userId 用户id* @return*/public void sendRedPackage(Integer totalAmount,Integer peopleNum,Long userId) {//金额和人数必须要大于0//持久化发红包信息RedRecordDO redRecordDO = new RedRecordDO();redRecordDO.setUserId(userId);redRecordDO.setAmount(totalAmount);redRecordDO.setTotal(peopleNum);//忽略支付流程 默认已支付redRecordDO.setStatus(1);redRecordService.save(redRecordDO);//计算发红包明细金额List<Integer> list = RedPackageUtil.divideRedPackage(totalAmount,peopleNum);//生成redis的key String key = "m:r:"+redId;//存储到redis中redisService.getListOps().rightPushAll(key,list);}
抢红包流程
抢红包直接使用redis作为数据源码,利用redis高吞吐量的特性,在发红包阶段先用红包算法将其拆分,存储到redis中的list类型中。
主要利用redis的list数据类型的lpop原子操作(移除并获取列表第一个元素)
可以在redis客户端上简单看一下 list的lpop操作:


具体代码实现如下:
/*** 抢红包* @param redId 红包id* @param userId 领取红包的用户id* @return null 表示红包已抢完*/public Integer robRedPackage(Long redId,Long userId){//redis key ,key建议缩写 m表示系统缩写 r 表示红包缩写String key = "m:r:"+redId;//先判断key是否存在if(redisService.exists(key)){//直接弹出list中的元素 lpop是原子性 ,且弹出list所有元素后会删除这个keyInteger amount = (Integer)redisService.getListOps().leftPop(key);//元素不为空,exists不是原子性指令,则 amount可能为null if(Objects.nonNull(amount)){//元素不为空则表示抢红包成功,异步更新红包流水redRobRecordService.robRecord(redId,userId,amount);}return amount;}//直接返回红包已被抢光return null;}
相关文章:
抢红包设计
抢红包大致可以分为2步:1 发红包 ;2 抢红包 发红包流程 为了突出红包设计主题,以下设计会忽略支付流程、24H过期退款剩余金额、用户领取红包余额到账等业务,则简化后的相关表设计如下: CREATE TABLE red_record (id…...
k8s集群-6(daemonset job cronjob控制器)
Daemonset 一个节点部署一个节点 当有节点DaemonSet 确保全部 (或者某些) 节点上运行一个 Pod 的副本。加入集群时,也会为他们新增一个 Pod 。当有节点从集群移除时,这些Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。 DaemonSet 的典型用…...
Compose 编译器版本和Kotlin版本对应关系
使用了最新的kotlin版本,compose报错,不兼容,在这里记录一下版本对应关系 值得注意的是Compose Kotlin 编译器扩展 (androidx.compose.compiler) 未关联到 Compose 库版本。相反,它会关联到 Kotlin 编译器插件的版本,…...
vite+vue+cesium
1.创建vite项目 npm create vite 项目名称 2. 选择vuejs/ts 3.在终端输入命令 npm install 4.安装cesium插件,在终端输入命令 npm i cesium vite-plugin-cesium vite -D 5.项目配置cesium 在vite.config.js里进行配置 import { defineConfig } from vite i…...
tcp滑动窗口原理
18.1 滑动窗口 我们再来看这个比喻: 网络仅仅是保证了整个网络的连通性,我们我们基于整个网络去传输,那么是不是我想发送多少数据就发送多少数据呢?如果是这样的话,是不是就会像我们的从一个池塘抽水去灌到另外一个…...
3.4 Android bpfloader初始化流程解读(二)
我继续看bpfloader是如何读取和处理bpf程序的。 4.2 读取代码段之readCodeSections static int readCodeSections(ifstream& elfFile, vector<codeSection>& cs, size_t sizeOfBpfProgDef,const bpf_prog_type* allowed, size_t numAllowed) {...ret = readSect…...
Linux0.12内核源码解读(2)-Bootsect.S
作者:小牛呼噜噜 | https://xiaoniuhululu.com 计算机内功、源码解析、科技故事、项目实战、面试八股等更多硬核文章,首发于公众号「小牛呼噜噜」 文章目录 回顾计算机启动过程8086、80x86是什么意思?寄存器初始化CS:IPCPU是如何和ROM相连的?加载MBR到…...
虚拟环境搭建、后台项目创建及目录调整、封装logger、封装全局异常、封装Response、后台数据库创建
1 虚拟环境搭建 #1 虚拟环境作用多个项目,自己有自己的环境,装的模块属于自己的# 2 使用pycharm创建-一般放在项目路径下:venv文件夹-lib文件夹---》site-package--》虚拟环境装的模块,都会放在这里-scripts--》python࿰…...
每日一练 | 网络工程师软考真题Day39
1、Windows Server 2003操作系统中,IIS6.0不提供以下 效劳。 A.web B.smtp C.pop3 D.ftp 2、Windows Server 2003操作系统中, 提供了远程桌面访问。 A.ftp B.email C…...
Android Studio编写xml布局不提示控件的部分属性问题的解决
最近突然发现Android Studio编写xml,发现有一部分控件的属性没有了代码提示,主要体现为id,margin等属性不再有代码提示,如下图。 但是手动输入仍然有效。然后删掉Android Sdk重新回来还是发现有问题,导一个之前的旧项目进来&#…...
BUGKU-simple_SSTI_1漏洞注入
SSTI漏洞注入 SSTI全称Server side template injection.服务端模板注入这节课主要讲flask的模板注入.flask会把类似于 的变量当做参数来渲染并填充到web页面,如果该参数可控并被后台解析则有可能被注入恶意代码导致注入漏洞请注意 模板注入只会存在于二次渲染中,无二次渲染不会…...
Python:dict
一些关于dict的奇妙观察 实验一 首先,创建两个一模一样的字典: dict1 {a: 1} dict2 {a: 1}然后,进行各种各样的相等判断: print(dict1 dict2) print(dict1.keys() dict2.keys()) print(dict1.values() dict2.values()) p…...
git和svn 的国内的下载地址
CNPM Binaries Mirror 下面是svn的地址 TortoiseSVN 64位下载-TortoiseSVN客户端官方版下载-华军软件园...
matplotlib制图进阶版
需求:两个产品销量的可视化折线图 1、使用pandas读取数据 2、生成销售数量的折线图...
【Java 进阶篇】HTML介绍与软件架构相关知识详解
HTML(Hypertext Markup Language)是一种用于创建网页的标记语言。它是互联网上信息传递和展示的基础,无论是在浏览器中查看网页还是在移动设备上浏览应用程序,HTML都扮演着关键角色。本文将向您介绍HTML的基础知识,并探…...
Python数据攻略-Pandas与机器学习数据准备
在机器学习项目中,大部分时间都花在了数据准备上。你可能听说过“数据是机器学习的燃料”的说法,这是因为高质量的数据是构建出色模型的关键。 在这篇文章中将使用Pandas库来进行数据准备。为了让内容更贴近实际将使用《三国志》游戏中的角色数据作为样本。 文章目录 数据编…...
阿里云/亚马逊云代理:aws账号购买:aws亚马逊云账号的优势
AWS 可以用多少付多少,无预付费用,无需签订长期使用合约。我们能够构建和管理大规模的全球基础设施,aws账号购买并以降低价格的形式将节约成本的优势传递给您。借助我们在规模和专业知识方面的效益,过去四年来,我们已在…...
JSON的MIME媒体类型是application/json
JSON(全称 JavaScript Object Notation)即JavaScript对象表示法,通知使用application/json媒体类型。 目录 1、JSON介绍 2、JSON语法 3、实践总结 运行环境: Windows-7-Ultimate-x64、Windows-10-BusinessEditions-21h2-x64 1…...
C++ 之如何将数组传递给函数?
在本文中,您将学习将数组传递给C 中的函数。您将学习如何传递一维和多维数组。 数组可以作为参数传递给函数。也可以从函数返回数组。考虑以下示例,将一维数组传递给函数: 示例1:将一维数组传递给函数 C 程序通过将一维数组传递…...
1.7 计算机网络体系结构
思维导图: 1.7.1 计算机网络的体系结构的形成 **1.7 计算机网络体系结构** 计算机网络体系结构中,分层的思想为核心。该方法使得复杂的网络设计变得更为简单和可管理。 **1.7.1 计算机网络体系结构的形成** - **计算机网络的复杂性**: 即使是简单的文…...
Degrees of Lewdity中文本地化技术解析:从安装到优化的实践指南
Degrees of Lewdity中文本地化技术解析:从安装到优化的实践指南 Degrees of Lewdity作为一款备受欢迎的游戏,其英文界面一直是中文用户体验的主要障碍。本文提供的Degrees of Lewdity中文本地化技术解析,将系统指导您完成游戏汉化的全过程&a…...
Starter计划配额耗尽预警失效?我们逆向解析其API响应头,发现3个未文档化的速率控制暗门
更多请点击: https://intelliparadigm.com 第一章:Starter计划配额耗尽预警失效?我们逆向解析其API响应头,发现3个未文档化的速率控制暗门 在对 Starter 计划的 API 调用行为进行深度监控时,我们观察到配额耗尽告警频…...
大模型上下文长度对Agent的影响:从4K到1M的质变
目录大模型上下文长度对Agent的影响:从4K到1M的质变引言:工作台革命一、上下文窗口演进史:从4K到1M的百倍跃迁1.1 时间线上的技术里程碑1.2 为什么2025年成为“百万Token元年”?二、长上下文的质变:Agent能力的三重跃迁…...
Claude Code环境变量配置全解析:从入门到精通
1. 项目概述:Claude Code 环境变量配置生成器如果你和我一样,是 Claude Code 的深度用户,那你一定经历过这样的时刻:面对一个复杂的开发任务,想调整一下模型的思考深度(Effort Level)来平衡成本…...
【ElevenLabs API接入黄金手册】:20年AI语音工程师亲授5大避坑要点与3小时极速上线实战路径
更多请点击: https://intelliparadigm.com 第一章:ElevenLabs API接入黄金手册:开篇导论与核心价值定位 ElevenLabs 以行业领先的语音自然度、情感表现力与多语言支持能力,成为生成式AI语音服务的事实标准。其API并非仅提供TTS基…...
FastAPI部署演进:从Gunicorn+Uvicorn镜像到原生多进程的迁移指南
1. 项目背景与演进:从“黄金搭档”到“历史遗产”如果你在过去几年里用 FastAPI 部署过 Web 服务,大概率听说过或者用过tiangolo/uvicorn-gunicorn-fastapi-docker这个 Docker 镜像。它一度是 FastAPI 官方文档里推荐的部署方案之一,由 FastA…...
光子储层计算在无人机动态补偿中的创新应用
1. 深度光子储层计算在无人机动态补偿中的创新应用在无人机控制领域,传统PID控制器面对复杂流体环境时往往力不从心。当无人机在狭窄空间或近地面飞行时,地面效应、天花板效应以及湍流再循环等未建模动力学因素会导致显著的性能下降。我在参与某城市峡谷…...
TigerVNC终极指南:快速掌握跨平台远程桌面控制
TigerVNC终极指南:快速掌握跨平台远程桌面控制 【免费下载链接】tigervnc High performance, multi-platform VNC client and server 项目地址: https://gitcode.com/gh_mirrors/ti/tigervnc TigerVNC是一款高性能、跨平台的VNC客户端和服务器软件࿰…...
STM32F103C8T6与DHT11单总线通信:从时序解析到数据校验的实战指南
1. 认识STM32F103C8T6与DHT11这对黄金搭档 第一次接触嵌入式开发的朋友可能会觉得,让单片机读取温湿度数据是个复杂的事情。但当你用STM32F103C8T6这颗性价比超高的Cortex-M3内核芯片,搭配DHT11这个经典温湿度传感器时,事情就变得简单多了。…...
DeepSeek模型服务Kubernetes化迁移 checklist(含CRD定义、ServiceMesh适配、TLS双向认证配置)
更多请点击: https://intelliparadigm.com 第一章:DeepSeek模型服务Kubernetes化迁移全景概览 将DeepSeek系列大语言模型(如DeepSeek-V2、DeepSeek-Coder)从单机或虚拟机部署迁移至Kubernetes集群,是支撑高并发推理、…...
