[日常] 高并发抢购方案的思考

经常在面试中被问到如何设计一个高并发环境下的抢购方案,虽然网上的资料已经很多了,但是都是很简单的说了一些用队列之类的套话,没有更详细的细节考虑.被问的实在是太多了,不得已我也仔细想想这些该怎么设计.抛开运维阶段的多层负载均衡,直接只说PHP的业务层面的逻辑.

整个流程如下:
web界面
点击抢购==>弹出答题弹窗==>答对判定当前队列长度==>队列未满就进入队列,显示排队中(状态),使用wbsocker实时关注用户状态
            ==>答错再答基本就没戏了返回失败
                           ==>队列满了,返回失败

后端进程
从队列随机取部分用户==>修改他的状态为待支付状态===>用户点击支付进行判定库存量===>支付完成减库存

在整个过程中,用户点击支付的时候也要判定库存,如果没库存就显示失败;用户点击完支付,库存充足,如果隔了很长时间才输入密码支付,这个过程中如果库存没了,要给用户退款;

也就是要么冗余部分商品,要么给用户退款两种方案

商品的详细信息
$redis->hGet(‘product‘, ‘num‘,‘name‘);
商品数量设置的是10,其余字段留着存其他信息

用户的状态
1:答题状态
2:排队状态
3:支付状态
4:抢购成功!
5:抢购失败

抢购接口:panic_buy.php
1.判定当前用户哈希是否存在,如果不存在就设置一下
$redis->hSetNx(‘taoshihan‘, ‘status‘, 1);
2.查看当前商品的库存,如果为0直接返回失败,更改用户状态为:5
$redis->hGet(‘product‘, ‘num‘);
3.查看以下队列长度,如果超过1000,直接更改用户状态为:5
$redis->lLen(‘panic_buying‘);
3.用户进入队列排队,更改用户状态为:2
$redis->rPush(‘panic_buying‘, ‘taoshihan‘);

查询状态:status.php
对于进入队列成功的用户才会调用到这个接口
1.判定当前用户状态
$redis->hGet(‘taoshihan‘, ‘status‘);

支付接口:pay.php
1.判定当前用户状态
$redis->hGet(‘taoshihan‘, ‘status‘);
2.判定当前商品数量,如果已经小于10个更改用户状态为:5
$redis->hGet(‘product‘, ‘num‘);
3.支付完成修改当前商品数量
$redis->hIncrBy(‘product‘, ‘num‘,-1);

后端进程:
获取下商品数量,如果等于0,就把所有除去进入支付集合的队列成员更改用户状态为:5
$redis->hGet(‘product‘, ‘num‘);
$redis->sIsMember(‘pay‘, ‘taoshihan‘);//是否存在于集合中

获取前100个用户,更改状态为:3,把该用户同时进入另一支付集合
$redis->lRange(‘panic_buying‘, 0, 99);//获取前100个
$redis->sAdd(‘pay‘ , ‘taoshihan‘);//插入支付集合

PHP-Redis扩展的哈希结构函数

hDel-删除一个或多个哈希字段
hExists-确定哈希字段是否存在
hGet-获取哈希字段的值
hGetAll-获取哈希中的所有字段和值
hIncrBy-将哈希字段的整数值增加给定数字
hIncrByFloat-将哈希字段的浮点值增加给定数量
hKeys-获取哈希中的所有字段
hLen-获取哈希中的字段数
hMGet-获取所有给定哈希字段的值
hMSet-将多个哈希字段设置为多个值
hSet-设置哈希字段的字符串值
hSetNx-设置哈希字段的值,仅当该字段不存在时
hVals-获取哈希中的所有值
hScan-扫描成员的哈希键
hStrLen-获取与哈希中的字段关联的值的字符串长度

PHP REDIS扩展的列表的函数

blPop,brPop-删除并获取列表中的第一个/最后一个元素
bRPopLPush-从列表中弹出一个值,将其推到另一个列表中并返回
lIndex,lGet-通过列表从其索引中获取元素
lInsert-在列表中的另一个元素之前或之后插入一个元素
lLen,lSize-获取列表的长度/大小
lPop-删除并获取列表中的第一个元素
lPush-在列表前添加一个或多个值
lPushx-仅在列表存在时才在列表前添加值
lRange,lGetRange-从列表中获取一系列元素
lRem,lRemove-从列表中删除元素
lSet-通过其索引设置列表中元素的值
lTrim,listTrim-将列表修剪到指定范围
rPop-删除并获取列表中的最后一个元素
rPopLPush-删除列表中的最后一个元素,将其附加到另一个列表中并返回(redis> = 1.1)
rPush-将一个或多个值添加到列表
rPushX-仅在列表存在时将值附加到列表

PHP-Redis扩展集合的操作方法

sADD 添加一个或多个成员到集合里面
sCard, sSize 获取一下集合中成员的个数
sDiff 在N个集合中比较出差集
sDiffStore 和sDiff差不多,但是把差集结果存储在第一个key里面
sInter 返回多个集合的交集
sInterStore 和sInter类似,把结果存储在第一个key里面
sIsMember, sContains检查参数中的成员是否是集合中的一员
sMembers, sGetMembers 获得集合中的所有成员
sMove 把集合中的成员从一个集合移动到另一个集合
sPop 在集合中随机删除一个并获取到这个成员
sRandMember 在集合中随机获取一个成员,并不删除它
sRem, sRemove 在集合中删除指定成员
sUnion 返回多个集合的并集
sUnionStore 把多个集合的并集存储在第一个参数key里面

原文地址:https://www.cnblogs.com/taoshihan/p/11754633.html

时间: 2024-11-04 00:19:45

[日常] 高并发抢购方案的思考的相关文章

通过请求队列的方式来缓解高并发抢购(初探)

通过请求队列的方式来缓解高并发抢购(初探) 一.背景 在移动互联网高速发展的时代,各种电商平台的抢购业务变得越来越火爆,抢购业务所带来的高并发问题值得我们去探索,主要涉及的方面包括处理和响应速度.数据的一致性等.抢购开放的一瞬间,可能有成千上万的下订单请求发送到服务器去处理,如果只是简单的请求处理响应方式,不做任何处理,导致的结果很可能是很多客户很长时间得不到响应,根本不知道自己是否下订单成功,或者下订单的数量已经超过了商品的数量,这就导致了超发的问题. 二.设计思路 1.用户在下订单之前当然是

关于PHP高并发抢购系统设计

内容并发抢购系统注意事项高并发架构设计描述程序端核心代码实现订单流程mysql 端并发解决方案 注意事项(1)高并发环境下,对于服务器cup.内存.网络宽带使用率会瞬间暴涨,需要注意对同服务器上其他应用的影响.(项目解耦,高并发应用独立部署)(2)服务器高负载运行,容易出现死机,重启服务器场景,要提前考虑内存(redis)数据备份与恢复,防止用户抢购数据丢失.(3)高并发应用首先要注重稳定性,其次是性能上优化. (4) 一台服务器能够支持多少并发量nginx服务为例:worker_process

asp.net解决高并发的方案.[转]

最近几天一直在读代震军的博客,他是Discuz!NT的设计者,读了他的一系列关于Discuz!NT的架构设计文章,大呼过瘾,特别是Discuz!NT在解决高访问高并发时所设计的一系列方案,本人尤其感兴趣.写这篇文章的目的,算是对初次阅读之后的总结备忘吧,以便以后有时间亲自测试,如果能在生产环境中得到应用,那就更有参考价值了. 测试方法:本地模拟测试网站高访问高并发采用的测试工具是大名鼎鼎的Loadrunner,这个工具做测试的一般都知道.在代震军的博客中,有以下几篇介绍了通过Loadrunner

asp.net解决高并发的方案

那啥,最近见了一人叨叨叨的神侃如何处理高并发.居然聊到服务器矩阵.我当时还没回过神,过后细想,服务器矩阵我也知道口里说说,但是中小企业能玩得起?作为一个程序员很多时候只能用手头资源来制定优化方案.(人生哲理:要警惕夸夸其谈者) 我收集了下网上提供的处理方式列在这里.虽然我不会无聊到背下来去唬新人,但加深下映象,有个纲目还是好的. 两大点: 通过服务器处理高并发  调整服务器应用程序池中的最大连接数. 1. 调整IIS 7应用程序池队列长度 由原来的默认1000改为65535. IIS Manag

解决高并发的方案

对于我们开发的网站,如果网站的访问量非常大的话,那么我们就需要考虑相关的并发访问问题了.而并发问题是绝大部分的程序员头疼的问题, 但话又说回来了,既然逃避不掉,那我们就坦然面对吧~今天就让我们一起来研究一下常见的并发和同步吧. 为了更好的理解并发和同步,我们需要先明白两个重要的概念:同步和异步    1.同步和异步的区别和联系 所谓同步,可以理解为在执行完一个函数或方法之后,一直等待系统返回值或消息,这时程序是出于阻塞的,只有接收到 返回的值或消息后才往下执行其它的命令. 异步,执行完函数或方法

asp.net解决高并发的方案. (转自网络)

最近几天一直在读代震军的博客,他是Discuz!NT的设计者,读了他的一系列关于Discuz!NT的架构设计文章,大呼过瘾,特别是Discuz!NT在解决高访问高并发时所设计的一系列方案,本人尤其感兴趣.写这篇文章的目的,算是对初次阅读之后的总结备忘吧,以便以后有时间亲自测试,如果能在生产环境中得到应用,那就更有参考价值了. 测试方法:本地模拟测试网站高访问高并发采用的测试工具是大名鼎鼎的Loadrunner,这个工具做测试的一般都知道.在代震军的博客中,有以下几篇介绍了通过Loadrunner

论答系统万人大课高并发性能测试方案2018.10.30

性能测试目的:通过高并发压力测试找到目前服务器瓶颈在哪. 性能测试范围:(根据业务高峰期的日志分析) 1.socket相关(教师端网络监测.白板.分配解析卡.练习卡,学生端网络监测.学生做题) 2.Http接口(教师端备课添加多个教学点.获取课堂信息接口.定制测评.智能练习卡) 性能测试方案: 1.模拟测试在线10万用户下,系统服务器运行情况. 2.并发量=在线用户/10 3.使用Jmeter 发送每秒1w并发量,检查此时系统是否达到瓶颈 4.瓶颈的判断依据:1.服务器资源超过性能测试指标.2.

海量数据、高并发优化方案

一.应用服务器负载均衡 1.链路负载均衡 通过DNS解析域名时,将客户端的访问解析成不同的IP,分配到不同的入口,同时尽可能保证所访问的入口是所有入口中可能较快的一个. 2.软件负载均衡 访问时生成页面的任务会被分配给其中一台服务器完成,这个过程要保证公正.公平.平均. 3.硬件负载均衡 二.页面优化 1.减少请求次数 通过合并CSS和Javascript文件来减少请求次数或是将资源文件分布在多个域名下来绕过浏览器并发加载的限制. 2.压缩CSS和Javascript代码. 通过对文件代码内容删

对于高并发的一些思考

夜宵时的思考 刚刚排错了一个小时,终于搞定了,奖励自己一碗泡面,在等微波炉前等待的时候想了挺多事的. 并发似乎是所有程序员的噩梦,也是所有程序员的"粮食",如果计算机不支持并发,世界上的Error Log应该能少一半,同时程序员的"魔力"也少了三分. 所谓的秒杀系统,其实是一种泛指,代表着多并发,高可用系统.为什么说至今没有一个类似Spring一样的框架,能在并发领域脱颖而出呢,因为每个领域,各个场景的情况不一样,每个解决并发的方案,脱离了实际,就没了价值. 面熟了