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

抢红包设计

抢红包大致可以分为2步:1 发红包 ;2 抢红包

发红包流程
image.png
为了突出红包设计主题,以下设计会忽略支付流程、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='抢红包记录';

红包算法选取二倍均值算法,保证无论用户是先抢还是后抢都保证抢到金额的概率一致。
二倍均值算法逻辑实现图:
image.png
算法代码实现:

/*** 二倍均值法计算红包金额* @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);}

抢红包流程
image.png抢红包直接使用redis作为数据源码,利用redis高吞吐量的特性,在发红包阶段先用红包算法将其拆分,存储到redis中的list类型中。
主要利用redis的list数据类型的lpop原子操作(移除并获取列表第一个元素)
可以在redis客户端上简单看一下 list的lpop操作:
image.png
image.png

具体代码实现如下:

    /*** 抢红包* @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步&#xff1a;1 发红包 &#xff1b;2 抢红包 发红包流程 为了突出红包设计主题&#xff0c;以下设计会忽略支付流程、24H过期退款剩余金额、用户领取红包余额到账等业务&#xff0c;则简化后的相关表设计如下&#xff1a; CREATE TABLE red_record (id…...

k8s集群-6(daemonset job cronjob控制器)

Daemonset 一个节点部署一个节点 当有节点DaemonSet 确保全部 (或者某些) 节点上运行一个 Pod 的副本。加入集群时&#xff0c;也会为他们新增一个 Pod 。当有节点从集群移除时&#xff0c;这些Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。 DaemonSet 的典型用…...

Compose 编译器版本和Kotlin版本对应关系

使用了最新的kotlin版本&#xff0c;compose报错&#xff0c;不兼容&#xff0c;在这里记录一下版本对应关系 值得注意的是Compose Kotlin 编译器扩展 (androidx.compose.compiler) 未关联到 Compose 库版本。相反&#xff0c;它会关联到 Kotlin 编译器插件的版本&#xff0c;…...

vite+vue+cesium

1.创建vite项目 npm create vite 项目名称 2. 选择vuejs/ts 3.在终端输入命令 npm install 4.安装cesium插件&#xff0c;在终端输入命令 npm i cesium vite-plugin-cesium vite -D 5.项目配置cesium 在vite.config.js里进行配置 import { defineConfig } from vite i…...

tcp滑动窗口原理

18.1 滑动窗口 我们再来看这个比喻&#xff1a; 网络仅仅是保证了整个网络的连通性&#xff0c;我们我们基于整个网络去传输&#xff0c;那么是不是我想发送多少数据就发送多少数据呢&#xff1f;如果是这样的话&#xff0c;是不是就会像我们的从一个池塘抽水去灌到另外一个…...

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

作者&#xff1a;小牛呼噜噜 | https://xiaoniuhululu.com 计算机内功、源码解析、科技故事、项目实战、面试八股等更多硬核文章&#xff0c;首发于公众号「小牛呼噜噜」 文章目录 回顾计算机启动过程8086、80x86是什么意思?寄存器初始化CS:IPCPU是如何和ROM相连的?加载MBR到…...

虚拟环境搭建、后台项目创建及目录调整、封装logger、封装全局异常、封装Response、后台数据库创建

1 虚拟环境搭建 #1 虚拟环境作用多个项目&#xff0c;自己有自己的环境&#xff0c;装的模块属于自己的# 2 使用pycharm创建-一般放在项目路径下&#xff1a;venv文件夹-lib文件夹---》site-package--》虚拟环境装的模块&#xff0c;都会放在这里-scripts--》python&#xff0…...

每日一练 | 网络工程师软考真题Day39

1、Windows Server 2003操作系统中&#xff0c;IIS6.0不提供以下 效劳。 A&#xff0e;web B&#xff0e;smtp C&#xff0e;pop3 D&#xff0e;ftp 2、Windows Server 2003操作系统中&#xff0c; 提供了远程桌面访问。 A&#xff0e;ftp B&#xff0e;email C&#xf…...

Android Studio编写xml布局不提示控件的部分属性问题的解决

最近突然发现Android Studio编写xml&#xff0c;发现有一部分控件的属性没有了代码提示&#xff0c;主要体现为id,margin等属性不再有代码提示&#xff0c;如下图。 但是手动输入仍然有效。然后删掉Android Sdk重新回来还是发现有问题&#xff0c;导一个之前的旧项目进来&#…...

BUGKU-simple_SSTI_1漏洞注入

SSTI漏洞注入 SSTI全称Server side template injection.服务端模板注入这节课主要讲flask的模板注入.flask会把类似于 的变量当做参数来渲染并填充到web页面,如果该参数可控并被后台解析则有可能被注入恶意代码导致注入漏洞请注意 模板注入只会存在于二次渲染中,无二次渲染不会…...

Python:dict

一些关于dict的奇妙观察 实验一 首先&#xff0c;创建两个一模一样的字典&#xff1a; dict1 {a: 1} dict2 {a: 1}然后&#xff0c;进行各种各样的相等判断&#xff1a; print(dict1 dict2) print(dict1.keys() dict2.keys()) print(dict1.values() dict2.values()) p…...

git和svn 的国内的下载地址

CNPM Binaries Mirror 下面是svn的地址 TortoiseSVN 64位下载-TortoiseSVN客户端官方版下载-华军软件园...

matplotlib制图进阶版

需求&#xff1a;两个产品销量的可视化折线图 1、使用pandas读取数据 2、生成销售数量的折线图...

【Java 进阶篇】HTML介绍与软件架构相关知识详解

HTML&#xff08;Hypertext Markup Language&#xff09;是一种用于创建网页的标记语言。它是互联网上信息传递和展示的基础&#xff0c;无论是在浏览器中查看网页还是在移动设备上浏览应用程序&#xff0c;HTML都扮演着关键角色。本文将向您介绍HTML的基础知识&#xff0c;并探…...

Python数据攻略-Pandas与机器学习数据准备

在机器学习项目中,大部分时间都花在了数据准备上。你可能听说过“数据是机器学习的燃料”的说法,这是因为高质量的数据是构建出色模型的关键。 在这篇文章中将使用Pandas库来进行数据准备。为了让内容更贴近实际将使用《三国志》游戏中的角色数据作为样本。 文章目录 数据编…...

阿里云/亚马逊云代理:aws账号购买:aws亚马逊云账号的优势

AWS 可以用多少付多少&#xff0c;无预付费用&#xff0c;无需签订长期使用合约。我们能够构建和管理大规模的全球基础设施&#xff0c;aws账号购买并以降低价格的形式将节约成本的优势传递给您。借助我们在规模和专业知识方面的效益&#xff0c;过去四年来&#xff0c;我们已在…...

JSON的MIME媒体类型是application/json

JSON&#xff08;全称 JavaScript Object Notation&#xff09;即JavaScript对象表示法&#xff0c;通知使用application/json媒体类型。 目录 1、JSON介绍 2、JSON语法 3、实践总结 运行环境&#xff1a; Windows-7-Ultimate-x64、Windows-10-BusinessEditions-21h2-x64 1…...

C++ 之如何将数组传递给函数?

在本文中&#xff0c;您将学习将数组传递给C 中的函数。您将学习如何传递一维和多维数组。 数组可以作为参数传递给函数。也可以从函数返回数组。考虑以下示例&#xff0c;将一维数组传递给函数&#xff1a; 示例1&#xff1a;将一维数组传递给函数 C 程序通过将一维数组传递…...

1.7 计算机网络体系结构

思维导图&#xff1a; 1.7.1 计算机网络的体系结构的形成 **1.7 计算机网络体系结构** 计算机网络体系结构中&#xff0c;分层的思想为核心。该方法使得复杂的网络设计变得更为简单和可管理。 **1.7.1 计算机网络体系结构的形成** - **计算机网络的复杂性**: 即使是简单的文…...

boost在不同平台下的编译(win、arm)

首先下载boost源码 下载完成之后解压 前提需要自行安装gcc等工具 window ./bootstrap.sh ./b2 ./b2 installarm &#xff08;linux&#xff09; sudo ./bootstrap.sh sudo ./b2 cxxflags-fPIC cflags-fPIC linkstatic -a threadingmulti sudo ./b2 installx86 (linux) su…...

计算机网络(第8版)第一章概述笔记

6 性能指标 带宽&#xff1a; 在单位时间内从网络中的某一点到另一点所能通过的“最高数据率”。 7 分层结构、协议、接口、服务 1、实体&#xff1a;第n层的活动元素称为n层实体。同一层的实体叫对等实体。 2、协议&#xff1a;为进行网络中的对等实体数据交换而建立的规则、…...

Linux 部署项目

部署 Linux 部署项目1. 宝塔部署1.1 前端部署1.2 后端部署 2. docker 部署2.1 后端部署2.2 前端部署 3. 跨域问题3.1 Nginx 代理&#xff08;推荐&#xff09;3.2 修改后端服务3.3 添加 web 全局请求拦截器 4. 域名解析DNSPod添加域名 Linux 部署项目 1. 宝塔部署 准备工作&am…...

MySQL 基础

MySQL 基础 顾名思义&#xff0c;关系型数据库&#xff08;RDB&#xff0c;Relational Database&#xff09;就是一种建立在关系模型的基础上的数据库。关系模型表明了数据库中所存储的数据之间的联系&#xff08;一对一、一对多、多对多&#xff09;。 关系型数据库中&#…...

VR模拟鸡胚培养接种实验,打造沉浸式的学习环境

在医学教育领域&#xff0c;传统的鸡胚接种实验一直是教学的重要组成部分。然而&#xff0c;这种实验方法存在一定的局限性&#xff0c;如操作难度大、成本高、安全隐患等。为了解决这些问题&#xff0c;越来越多的教育机构开始尝试引入虚拟现实(VR)技术&#xff0c;以模拟鸡胚…...

基于ModbusTCP与西门子PLC通讯项目案例

目录 一、西门子PLC仿真环境搭建 【1.1】创建PLC项目 【1.2】编写PLC程序 二、C#代码编写 【2.1】窗口制作 【2.2】效果演示 【2.3】读取源码 【2.4】FrmSiemensSet源码 【2.5】Variable源码 一、西门子PLC仿真环境搭建 【1.1】创建PLC项目 搭建PLCSIM-Advacend模拟仿…...

Oralce数据库管理 -操作系统cpu 内存 io指标分析查询

1 前35个cpu消耗较大的进程 ps aux|head -1;ps aux|grep -v PID|sort -rn -k 3|head -35 1 前35个内存消耗较大的进程 ps aux|head -1;ps aux|grep -v PID|sort -rn -k 4|head -35...

my_print_defaults 及perror

参考文档&#xff1a; https://mysql.net.cn/doc/refman/8.0/en/my-print-defaults.html https://mysql.net.cn/doc/refman/8.0/en/perror.html -- my.cnf的内容 [rootredhat762100 mysql3306]# more my.cnf [mysqld] datadir/mysql/mysql3306/data #socket/tmp/mysql3306.so…...

视频转GIF:快速生成有趣的动态图片

随着社交媒体的快速发展&#xff0c;GIF动态图片已经成为了人们表达情感、分享生活片段的重要方式。将视频片段转换成GIF动态图片&#xff0c;可以让人们更好地分享和表达自己的情感&#xff0c;也可以让一些有趣的瞬间变得更加生动有趣。本文将介绍如何将视频快速转换成GIF动态…...

vue3 vscode no tsconfig与找不到名称“ref”。ts(2304)

如题&#xff0c;这两个问题都与tsconfig的配置有关&#xff0c;先看下问题表现&#xff1a; 解决方法&#xff0c;应当正确配置如下&#xff0c;之后保存或重启vscode&#xff1a;...

如何做网站在售产品分析/地推是什么

原文地址&#xff1a;https://oracle-base.com/articles/21c/attention-log-oracle-database-21c 原文作者&#xff1a;Tim Hall 多年来&#xff0c;数据库的告警日志变得非常庞大&#xff0c;很难从海量的告警信息中找到重要的日志内容。Attention 日志是 Oracle 21c 中引入的…...

中国建设信用卡积分兑换网站/站长查询域名

最近做图像分类&#xff0c;数据集的整理真的好费时间&#xff0c;找到一个代码&#xff0c;非常好使&#xff0c;推荐给大家。实现的功能是&#xff0c;将一个文件夹下的每个子文件夹的一半数据分割出来并保存&#xff0c;生成相应的train.txt,test.txt。自己弄数据集&#xf…...

阜宁网站制作收费标准/排行榜123网

python实现删除列表中某个元素的3种方法 python中关于删除list中的某个元素&#xff0c;一般有三种方法:remove、pop、del&#xff1a; 1.remove: 删除单个元素&#xff0c;删除首个符合条件的元素&#xff0c;按值删除 举例说明: >>> str[1,2,3,4,5,2,6] >>>…...

网站建设哪个品牌好/2023最新15件重大新闻

Python 中 Eval 函数的用法 eval(str)函数很强大&#xff0c;官方解释为&#xff1a;将字符串str当成有效的表达式来求值并返回计算结果。所以&#xff0c;结合math当成一个计算器很好用。 eval()函数常见作用有&#xff1a; 1、计算字符串中有效的表达式&#xff0c;并返回结果…...

重庆智慧团建网站登录平台/苏州seo关键词优化软件

标签&#xff1a; 转自&#xff1a;http://blog.csdn.net/lh9529/article/details/3946567 概念 Selenium 通过命令进行驱动。Selenium 可归纳为三种“风格”&#xff1a;动作、辅助和断言。每一个命令调用就是下表中的一行。 命令 目标 值 动作(Actions)命令一般用于操作应用…...

wordpress 微信登录插件下载失败/品牌营销策略有哪些

像碰到form表单中既有文件上传&#xff0c;又有接收的字段的时候&#xff0c;字段想用 request.getParameter 来得到&#xff0c;往往是null <form action"FileUpload" method"post" enctype"multipart/form-data" name"form1">…...