加入收藏 | 设为首页 | 会员中心 | 我要投稿 北几岛 (https://www.beijidao.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

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

发布时间:2021-05-21 06:52:34 所属栏目:大数据 来源: https://www.jb51.cc
导读:经常在面试中被问到如何设计一个高并发环境下的抢购方案,虽然网上的资料已经很多了,但是都是很简单的说了一些用队列之类的套话,没有更详细的细节考虑.被问的实在是太多了,不得已我也仔细想想这些该怎么设计.抛开运维阶段的多层负载均衡,直接只说PHP的业务层

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


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

获取前100个用户,更改状态为:3,把该用户同时进入另一支付集合
$redis->lRange('panic_buying',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里面

(编辑:北几岛)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读