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

微信红包设计流程讲解与实战分析

#1024程序员节 | 征文#

前言

微信红包作为大家耳熟能详的一种互动方式,其背后的技术支持包含多个方面。从用户发出红包到红包被抢完,涉及到的流程包括发红包、红包存储、红包拆分以及抢红包等。本文将详细介绍这一系列流程,并通过代码案例来实践讲解,特别重点分析红包的拆分算法。

微信红包设计流程

整个红包流程按照发红包、红包拆分、抢红包的顺序来设计。在数据结构的选择上,考虑到抢红包的高并发特性和即时响应要求,采用Redis非关系数据库进行设计是优于MySQL的。Redis的每个命令都是单线程执行,保证原子性操作,无需额外的锁机制。

1. 发红包

一个红包通常会被拆分成多个小红包,例如100元可以拆分为20元、20元、20元、30元和10元。这种情况下,可以使用Redis的list结构来存储这些拆分后的小红包。

2. 抢红包

在高并发环境下,如何保证多线程抢红包时不加锁且保持原子性是关键。Redis的特性使得每个命令都是单线程且原子性的,因此使用LPOP命令即可实现。

3. 记红包

为了确保同一个用户不能抢夺同一个红包两次,需要记录哪些红包被哪些用户抢过。这里可以使用Redis的hash结构来进行存储。

拆红包算法

在拆红包算法中,较为合理的是采用“二倍均值算法”。该算法的核心思想是每次拆分红包时,取一个随机区间,其最大值为剩余红包金额的两倍与未被抢的剩余红包个数的乘积。这样可以保证拆分的随机性和公平性。

代码实现

二倍均值算法的具体代码实现如下:

private Integer[] splitRedPackageAlgorithm(int totalMoney, int redPackageNumber){Integer[] splitRedPackageNumbers = new Integer[redPackageNumber];int useMoney = 0;for (int i = 0; i < redPackageNumber; i++) {if(i == redPackageNumber - 1){splitRedPackageNumbers[i] = totalMoney - useMoney;}else {int avgMoney = ((totalMoney - useMoney) / (redPackageNumber - i)) \* 2;splitRedPackageNumbers[i] = 1 + new Random().nextInt(avgMoney - 1);}useMoney += splitRedPackageNumbers[i];}return splitRedPackageNumbers;}

为什么生成每个小红包金额使用如下代码随机生成?

splitRedPackageNumbers[i] = 1 + new Random().nextInt(avgMoney - 1);

首先,前面加1的原因是new Random().nextInt(avgMoney -1)会生成0到avgMoney - 1之间的随机数,但不能为0。为了保证第一个红包不为0元,所以需要+1。其次,avgMoney - 1是为了控制随机数的最大值接近于avgMoney但不等于它。这样可以确保最后一个红包也不会为0元。如果不这样做,有可能每次随机数都取最大值,导致最后剩余的红包金额只能为0。

后面avgMoney -1,如果不-1,结果是怎样呢?接下来模拟不-1的情况下,假设100块分5个红包,每次随机数都取最大值,那么有如下情况:

红包useMoneyavgMoney每次随机数最大本次红包金额
1020 * 2new Random().nextInt(avgMoney) == 3940
24015*2new Random().nextInt(avgMoney) == 2930
37010*2new Random().nextInt(avgMoney) == 1920
4905*2new Random().nextInt(avgMoney) == 910
500

发红包

发红包的主要步骤是将拆分后的小红包保存到Redis的list结构中,并设置过期时间。具体代码如下:

@RequestMapping(value = "/send")public String sendRedPackage(int totalMoney, int redPackageNumber){Integer[] splitRedPackages = splitRedPackageAlgorithm(totalMoney,redPackageNumber);String key = RED\_PACKAGE\_KRY + IdUtil.simpleUUID();redisTemplate.opsForList().leftPushAll(key,splitRedPackages);redisTemplate.expire(key,1, TimeUnit.DAYS);return key+"\t" + Ints.asList(Arrays.stream(splitRedPackages).mapToInt(Integer::valueOf).toArray());}

调用发红包接口,比如20块钱分成5个红包,查看redis。

抢红包

抢红包的逻辑是先验证用户是否已经抢过该红包,如果没有则允许其抢红包并记录到Redis中。具体代码如下:

@RequestMapping(value = "/rob")public String robRedPackage(String redPackageKey,String userId){Object redPackage = redisTemplate.opsForHash().get(RED\_PACKAGE\_CONSUME\_KRY + redPackageKey, userId);if (redPackage == null){Object partRedPackage = redisTemplate.opsForList().leftPop(RED\_PACKAGE\_KRY + redPackageKey);if (partRedPackage != null){redisTemplate.opsForHash().put(RED\_PACKAGE\_CONSUME\_KRY+redPackageKey,userId,partRedPackage);System.out.println("用户"+userId+" 抢到红包了 " + partRedPackage);return String.valueOf(partRedPackage);}return "errorCode : -1 ,红包抢完了";}return "errorCode : -2 ," + userId + " 你已经抢过红包了";}

调用抢红包接口后,用户可以返回抢到的红包金额,并且在Redis中也能查看到相应的红包记录。

总结

本文主要介绍了微信红包的拆分、发放和抢红包的流程,并重点讲解了二倍均值法在拆红包算法中的应用。通过随机生成红包金额的方式,实现了公平且随机的抢红包效果。整个过程中涉及到了Redis数据库的高效利用以及高并发环境下的数据处理问题。

相关文章:

微信红包设计流程讲解与实战分析

#1024程序员节 | 征文# 前言 微信红包作为大家耳熟能详的一种互动方式&#xff0c;其背后的技术支持包含多个方面。从用户发出红包到红包被抢完&#xff0c;涉及到的流程包括发红包、红包存储、红包拆分以及抢红包等。本文将详细介绍这一系列流程&#xff0c;并通过代码案例来…...

AI智能体:AI智能体(Agent)是什么?为什么要学?99%的人不知道!

为什么要学&#xff1f; 我们先搞清楚为什么&#xff1f; 最近看到 AI 创新力五问&#xff0c;我们日常生活中有使用 AI 来融入到我们的学习工作流嘛&#xff1f; 值得我们日常反省。 未来企业人才招聘测试AI创新力的五问&#xff1a; 您是否处于每天习惯使用 AI 的状态&am…...

NVR小程序接入平台/设备EasyNVR多个NVR同时管理的高效解决方案

在当今的数字化安防时代&#xff0c;视频监控系统的需求日益复杂和多样化。为了满足不同场景下的监控需求&#xff0c;一种高效、灵活且兼容性强的安防视频监控平台——NVR批量管理软件/平台EasyNVR应运而生。本篇探讨这一融合所带来的创新与发展。 一、NVR监测软件/设备EasyNV…...

APS开源源码解读: 排程工具 optaplanner II

上篇 排产&#xff0c;原则上也就是分配时间&#xff0c;分配资源&#xff1b;保证资源日历约束&#xff0c;保证工艺路线约束。我们看一下如何实现optaplanner 优化的 定义一个move, 一个move可能改变了分配到的资源&#xff0c;也可能改变了一个资源上的顺序。改变即意味着优…...

科技是把双刃剑,巧用技术改变财务预测

数字化和全球化的双向驱动&#xff0c;引领我国各行各业在技术革新的浪潮中不断扬帆。这一趋势不仅带来了前所未有的突破与创新&#xff0c;推进企业迈向数据驱动决策的新未来&#xff0c;同时也伴随着一些潜在的问题和挑战。科技的普及就像是一场革命&#xff0c;在财务管理领…...

vscode默认添加python项目的源目录路径到执行环境(解决ModuleNotFoundError: No module named问题)

0. 问题描述 vscode中编写python脚本&#xff0c;导入工程目录下的其他模块&#xff0c;出现ModuleNotFoundError: No module named 错误 在test2的ccc.py文件中执行print(sys.path) 查看路径 返回结果发现并无’/home/xxx/first_demo’的路径&#xff0c;所以test2下面的文…...

【每日刷题】Day143

【每日刷题】Day143 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 200. 岛屿数量 - 力扣&#xff08;LeetCode&#xff09; 2. LCR 105. 岛屿的最大面积 - 力扣&…...

基于Springboot智能学习平台的设计与实现

基于Springboot智能学习平台的设计与实现 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;idea 源码获取&#xff1a;https://download.csdn.net/downlo…...

黑马javaWeb笔记重点备份11:Web请求与响应

请求 SpringBoot内置Servlet 在Tomcat这类Web服务器中&#xff0c;是不识别我们自己定义的Controller的&#xff0c;但在tomcat中是可以识别 Servlet程序的。在SpringBoot进行web程序开发时&#xff0c;它内置了一个核心的Servlet程序 DispatcherServlet&#xff0c;称之为 核…...

H5对接海康硬盘录像机视频简单说明

开发过程中使用HTML5(通常是通过Web技术栈,如HTML、CSS、JavaScript)与海康威视(Hikvision)的硬盘录像机(DVR)进行视频对接,通常涉及以下步骤: 获取DVR的RTSP流地址:海康威视DVR支持RTSP协议,你可以通过DVR的管理界面获取每个摄像头的RTSP流地址。 使用视频播放器库…...

测试人必备的Linux常用命令大全...【全网最全面整理】

Linux常用命令大全&#xff08;非常全&#xff01;&#xff01;&#xff01;&#xff09; 最近都在和Linux打交道&#xff0c;感觉还不错。我觉得Linux相比windows比较麻烦的就是很多东西都要用命令来控制&#xff0c;当然&#xff0c;这也是很多人喜欢linux的原因&#xff0c…...

苹果AI落后两年?——深度解析苹果在AI领域的挑战与前景

# 苹果AI落后两年&#xff1f;——深度解析苹果在AI领域的挑战与前景 近年来&#xff0c;人工智能&#xff08;AI&#xff09;领域的技术竞争日益激烈&#xff0c;各大科技巨头纷纷推出突破性的AI产品。然而&#xff0c;关于苹果公司在AI领域的表现&#xff0c;最近传出一些内…...

三菱PLC伺服-停止位置不正确故障排查

停止位置不正确时&#xff0c;请确认以下项目。 1)请确认伺服放大器(驱动单元)的电子齿轮的设定是否正确。 2&#xff09;请确认原点位置是否偏移。 1、设计近点信号(DOG)时&#xff0c;请考虑有足够为0N的时间能充分减速到爬行速度。该指令在DOG的前端开始减速到爬行速度&…...

Mybatis 批量操作存在则更新或者忽略,不存在则插入

Mybatis 批量操作新增&#xff0c;如果存在重复有下列2种处理方式&#xff1a; 1、存在则忽略代码示例&#xff1a; <insert id"insertDuplicateKeyIgnoreList">INSERT IGNORE INTO specs(status,type,code,name,create_time,create_by)VALUES<foreach col…...

「C/C++」C++ STL容器库 之 std::deque 双端队列容器

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「C/C」C/C程序设计&#x1f4da;全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasoli…...

一招教你解决Facebook广告账号问题

这段时间&#xff0c;我们写了很多文章来探讨Facebook的广告账户问题&#xff1a;《Facebook被封号该怎么办》《Facebook二不限、三不限账号是什么》《Facebook海外户&#xff08;三不限&#xff09;和账单户该如何选择》《如何区分真假Facebook三不限海外户》相信看过这些文章…...

MySQL启动报错:InnoDB: Unable to lock ./ibdata1 error

MySQL启动报错&#xff1a;InnoDB: Unable to lock ./ibdata1 error 在OS X环境下MySQL启动时报错&#xff1a; 016-03-03T00:02:30.483037Z 0 [ERROR] InnoDB: Unable to lock ./ibdata1 error: 35 2016-03-03T00:02:30.483100Z 0 [Note] InnoDB: Check that you do not alr…...

Linux终端之旅: 打包和压缩

在 Linux 世界中&#xff0c;打包和压缩文件是管理系统资源、传输数据和备份的重要技能。通过命令行工具如 tar、gzip、zip 等&#xff0c;我们可以高效地将多个文件或目录打包为一个文件&#xff0c;并通过压缩减少其体积。接下来&#xff0c;我将记录学习如何利用这些工具&am…...

PDA手持机提升管理效率和准确性

在当今快节奏的商业世界中&#xff0c;管理效率和准确性是企业成功的关键因素。而 PDA 手持机的出现&#xff0c;为企业管理带来了革命性的变革&#xff0c;成为提升管理效率和准确性的有力武器。 PDA 手持机&#xff0c;即个人数字助理手持设备&#xff0c;集数据采集、存储、…...

C++ [项目] 愤怒的小鸟

现在才发现C游戏的支持率这么高&#xff0c;那就发几篇吧 零、前情提要 此篇为 制作,由于他没有CSDN,于是由我代发 一、基本介绍 支持Dev-C5.11版本(务必调为英文输入法),基本操作看游戏里的介绍,怎么做的……懒得说,能看懂就看注释,没有的自己猜,如果你很固执……私我吧 …...

vscode里如何用git

打开vs终端执行如下&#xff1a; 1 初始化 Git 仓库&#xff08;如果尚未初始化&#xff09; git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

Python:操作 Excel 折叠

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

2025盘古石杯决赛【手机取证】

前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来&#xff0c;实在找不到&#xff0c;希望有大佬教一下我。 还有就会议时间&#xff0c;我感觉不是图片时间&#xff0c;因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

.Net Framework 4/C# 关键字(非常用,持续更新...)

一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

Python ROS2【机器人中间件框架】 简介

销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…...