经常在面试中被问到如何设计一个高并发环境下的抢购方案,虽然网上的资料已经很多了,但是都是很简单的说了一些用队列之类的套话,没有更详细的细节考虑.被问的实在是太多了,不得已我也仔细想想这些该怎么设计.抛开运维阶段的多层负载均衡,直接只说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里面 (编辑:北几岛)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|