关于微信红包的架构思考
关于微信红包的架构思考
微信红包的架构实现是前段时间技术圈里很热门的一个话题,这是一个非常典型的大访问高并发场景。至于如何实现,答案并不是唯一的,对这个问题的思考其实反映了工程师的架构设计功底。所以我也谈一谈我的想法。
首先任何架构设计离不开对业务的理解和认识,架构设计并不是凭空存在的,一定是基于业务场景并且服务业务场景的。所以我先分析一下微信红包的业务场景。
*** 需要特别说一点,本文中的架构设计不一定是官方的实现方式,只是一种分析,是基于我目前的技术能力的一种思考 ***
业务场景分析
根据微信红包的操作,可以把红包的业务场景分为发放红包,抢红包和打开红包三个步骤。
PS:我觉得微信红包的架构讨论之所以非常火爆,一个重要原因就是微信红包的业务场景大家都很熟悉
发放红包:
- 发放者设置红包金额,红包数量等属性
- 从发放者账户扣除红包金额
- 生成红包,并且发送抢红包的链接
抢红包:
- 用户点击红包链接
打开红包:
- 显示用户抢到的红包金额
- 剩余红包数量-1,红包剩余金额改变
- 抢到红包的用户账户金额增加
注意,以上均为原子操作
根据业务场景,可以知道红包的主要属性有:
- 红包金额:始终不变
- 红包总数量:始终不变
- 红包剩余金额:每次有人领取红包,该属性变化
- 红包剩余数量:每次有人领取红包,该属性-1
- 抢到红包的用户以及抢到的金额:用于显示手气排行,并且防止重复抢红包
- 过期时间:如果到过期红包仍未抢完,返回发放者账户
架构分析
单纯实现微信红包的功能并不复杂,其难点在于如何处理高访问和并发,当发出一个红包之后,只有少数人能够抢到,而大部分的请求都属于无效请求,如果让这部分请求落到数据库或者在服务端经过复杂处理,那么以微信的用户体量,后果是灾难性的。
从这个角度来说,微信红包和电商的秒杀业务有几分相似
处理类似业务最常见的手段就是请求过滤和添加缓存(cache),当然,至于服务器集群,负载均衡,读写分离这些基础架构,由于已经成了大型网站的标配,默认已经存在。
其中,请求过滤是只允许少数符合条件的请求走到最后,把大量不符合条件的请求挡在外面,这个非常关键。而采用缓存技术,原因有两个,一是缓存的访问速度快,使用缓存可以有效提高吞吐速度,二是红包发放相对来说是一个临时性的东西,故而可以放在缓存里面。
业务上需要注意的地方
- 防止用户重复抢红包
- 应对redis宕机的风险,目前一般是采用sentinel机制
架构设计
缓存我们默认使用redis,数据库默认使用mysql
新建红包的时候,生成唯一红包id,设置红包属性,在mysql中添加记录,表结构大致如下
|红包id|发放者uid|红包总金额|红包总数量|红包剩余金额|红包剩余数量|抢到红包的用户列表json|过期时间|创建时间|
|---|:----|:---|---|----|---|---|----|---|--|--|:---|:----|:---|---|----|---|---|----|---|--
同时,在redis里添加:
- 抢红包请求队列(队列)
- 打开红包请求队列(队列)
- 红包信息,包含剩余红包数量和剩余金额(键值对)
- 已经抢到红包的用户信息(有序集合)
当抢红包的时候,
做以下判断:
- 剩余红包数量是否大于0
- 该用户是否在已经抢到红包的用户集合里面
通过判断的请求添加进请求队列,否则返回已经抢完的标示,这样下一步用户打开红包的时候,甚至可以不发送请求直接显示红包已经抢完,过滤无效请求
于此同时,另外有进程从请求队列里取出抢红包请求,生成token标示,返回给抢红包者
当用户打开红包的时候,传入该标示,放进打开红包请求队列,后端消费者进程从队列中取出打开红包请求,判断红包数量是否大于0,以及用户传来的打开红包token与红包id是否合法,参数检验之后,生成红包金额,调用余额接口处理,并且更新redis中红包剩余数量,红包剩余金额
最后异步方式更新数据库
红包算法
关于红包算法,网上说的很多了,这里就不啰嗦了,金额是拆的时候实时算出来,不是预先分配的,采用的是纯内存计算,不需要预算空间存储,具体的算法是在在0.01和剩余平均值的2倍之间随机生成一个金额
效果
比如现在发了一个红包,分为5份。有100个人抢。
可能有10个人成功进入请求队列(抢到红包和打开红包之间有一定间隔,所以先抢到的不一定先打开),拿到了打开红包token,其余90个人拿到的是红包已经抢完的token,那么当打开红包的时候,这90个人甚至都不需要发送请求,直接显示红包已抢完
这10个人打开红包的时候,其中5个人抢到,剩下的5个也显示红包已经抢完
本来5个红包100个人抢,会请求201次(生成红包1次+抢红包100次+打开红包100次)
那么这种情况下,只需要111次(生成红包1次+抢红包100次+打开红包10次),并且,其中90次请求很快就返回,大大减轻服务端压力
需要注意的是
- 如何保证原子性操作
- 如何提高可用性,主要是防止redis宕机
总结
衡量一个架构设计的标准主要是性能,扩展性,伸缩性,可用性,安全性等指标,本例中,由于红包业务是一个很具体的业务,并非通用服务,所以不讨论扩展性。
- 性能角度,由于采用了缓存以及请求过滤等手段,性能肯定比常规实现大大提高
- 伸缩性角度,应该采用服务器集群,redis集群,mysql集群的方式部署,注意redis集群中的一致性hash的实现
- 可用性角度,本例中决定可用性的关键还是在于redis集群是否能够保证高可用,所以sentinel机制必不可少,甚至还应该加上其他的各种检测节点,替换节点方案,以保证高可用。而且需要考虑极端情况,例如缓存被击穿导致mysql压力过大的情况下,如何确保服务不宕机。
- 安全性角度,红包涉及资金来往,所以需要格外注意安全性。红包业务中,是通过调用接口来实现资金往来,故账目平衡的风险不是由红包系统来承担而是由红包所调用的接口保证的,但红包系统也可能存在以下几种安全隐患,单一用户重复抢红包,所有用户抢的的红包金额总数大于发放者设置的红包金额等。所以其关键在于确保抢红包,打开红包均为一次原子性操作。如有必要,甚至可以通过加锁等方式实现,但需要考虑加锁对于性能上的影响
作者:cuihang
链接:https://www.jianshu.com/p/63f238b04c59
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
关于微信红包的架构思考相关推荐
- PHP实现微信随机红包算法和微信红包的架构设计简介
微信红包的架构设计简介: 原文:https://www.zybuluo.com/yulin718/note/93148 @来源于QCon某高可用架构群整理,整理朱玉华. 背景:有某个朋友在朋友圈咨询微 ...
- 微信红包系统架构的设计和优化分享
微信红包系统架构的设计和优化分享 编者按:经过2014年一年的酝酿,2015微信红包总量创下历史新高,峰值1400万次/秒,8.1亿次每分钟,微信红包收发达10.1亿次,系统整体运行平稳, 在这里我分 ...
- 微信红包数据架构演变
PPT主题:微信红包数据架构演变 嘉宾:莫晓东有关资金安全,所以需要事务1.继续使用MySQL• MySQL支持事物,满足一致性要求.• 结构化存储,紧凑.连续.• 支持多索引.• 部署简单,工具支持 ...
- 微信红包技术架构,防外挂贼牛逼!(附胶片下载)
公众号后台回复 "微信红包架构" 下载该胶片 参考:https://www.open-open.com/lib/view/open1427943866100.htmlhttp:// ...
- 微信红包的架构设计简介
参考:https://www.zybuluo.com/yulin718/note/93148 http://coderroc.com/article/%E6%95%B0%E5%AD%A6%E5%92% ...
- 高并发资金交易系统设计方案—百亿双十一、微信红包背后的技术架构
21CTO社区导读 : 今天带来的是一个长篇文章.主要讲解高可用的互联网交易系统架构,包括双十一.支付宝&微博红包技术架构,以及微信红包的技术架构,希望能给各位提供价值. 概述 话说每逢双十一 ...
- 微信红包随机数字_微信红包随机算法转载
php固定红包 + 随机红包算法 1 需求 CleverCode最近接到一个需求,需要写一个固定红包 + 随机红包算法. 1 固定红包就是每个红包金额一样,有多少个就发多少个固定红包金额就行. 2 随 ...
- 微信抢红包MATLAB,微信红包怎么抢才是运气王?有人做了实验,看结果!
在抢微信红包的过程中,可能许多人有这样一种感觉,抢红包貌似后抢比先抢能拿到更多的钱?有人就做了一个实验-- 友情提示: 全文约6400字,阅读全文约10分钟.如果觉得时间紧张,可以跳过实验过程直接拉至 ...
- 微信红包随机算法实现
为什么80%的码农都做不了架构师?>>> 看了微信红包的算法实现探讨(基于PHP)一文,我尝试使用C++重现,代码如下: #include <iostream> # ...
最新文章
- 跟着柴毛毛学Spring(3)——简化Bean的配置
- Zabbix添加Ping外网IP监控
- java平衡二叉树,最全Java知识总结
- oracle 取前10条记录
- Linux高性能server编程——高级I/O函数
- 双网卡oracle rac,Linux+Oracle 10g RAC双网卡绑定和解除绑定的实现(2)
- python递归算法案例教案_python教案
- 几种纯css布局的导航栏
- Linux16.04和Windows 10双系统下,解决时间不一致问题
- 5安卓输入法键盘显示 搜索_手机输入法谁更黑科技?讯飞搜狗百度大PK
- java名字转化为拼音_将中文姓名转换为拼音
- 函数对称性常见公式_函数的对称性
- hash碰撞解决方法
- 【愚公系列】2021年12月 攻防世界-简单题-MOBILE-008(Ph0en1x-100)
- 数据库对三大范式简单易懂的理解
- 2020最新手机百度云不限速教程,下载速度10M/S,比会员还快
- Python 从函数 def 到类 Class
- windows端的MarginNote:BookxNote
- Bugku CTF 眼见为实(MISC)
- RHEL 5下iSCSI Initiator软件安装配置指导
热门文章
- shell在指定目录下执行nohup_nohup:关闭shell程序依然执行
- python get argument_Python-Web框架-get_argument方法
- v8声卡怎么录制唱歌_【绝对干货】关于声卡你需要知道的几点知识(上)
- Flume监听文件夹中的文件变化,并把文件下沉到hdfs
- linux 修改IP, DNS 命令
- Spring整合了CXF的一个applicationContext.xml的配置文件
- OA中总结:s:select,关于使用modelDriven,项目分层,@Transactional,jspf,各个层上配置注解交给spring管理的方法,简单的OGNL表达式写法
- 调链接_古筝谱 |踏山河是七叔呢演唱歌曲 双手版 D调 简谱唱谱
- 5页面调用原生相机_React Native与原生通信全梳理(iOS端)
- 批处理中setlocal enabledelayedexpansion的作用详细整理