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

购物网站开发论述网站开发建设的一般流程

购物网站开发,论述网站开发建设的一般流程,飓风算法受影响的网站有哪些,目前最好的引流方法一、秒杀(Seckill)​ 1. ​定义 ​秒杀:短时间内(如1秒内)大量用户同时抢购 ​限量低价商品 的营销活动。​典型场景:双11热门商品抢购、小米手机首发、演唱会门票开售。 2. ​技术挑战 挑战点说明后果…

一、秒杀(Seckill)​

1. ​定义
  • 秒杀:短时间内(如1秒内)大量用户同时抢购 ​限量低价商品 的营销活动。
  • 典型场景:双11热门商品抢购、小米手机首发、演唱会门票开售。
2. ​技术挑战
挑战点说明后果示例
高并发请求瞬时QPS可达10万+服务器宕机、请求超时
库存精准控制库存扣减需绝对准确超卖(实际卖了1001件,库存1000)
公平性防止机器人抢购正常用户抢不到
3. ​示例流程
sequenceDiagram用户->>秒杀系统: 提交抢购请求(iPhone 100台)秒杀系统->>Redis: 检查库存 >0?Redis-->>秒杀系统: 库存剩余10秒杀系统->>Redis: 原子扣减库存(DECR)秒杀系统->>消息队列: 生成订单(异步)用户-->>秒杀系统: 抢购成功

二、超卖(Oversell)​

1. ​定义
  • 超卖:实际卖出的商品数量 ​超过库存数量​(如库存100件,卖出105件)。
  • 本质问题:并发场景下 ​库存判断和扣减的非原子性
2. ​超卖原因
原因技术解释类比场景
并发读脏数据多个线程同时读到库存>0100人同时看到最后1件商品
非原子操作先查库存再扣减(非原子)收银员A和B同时卖最后1件商品
网络延迟请求到达顺序不可控多人同时提交订单
3. ​超卖过程模拟
 

bash

# 初始库存:stock=1
用户A:读取stock=1 → 准备扣减(未提交)
用户B:读取stock=1 → 扣减 → stock=0(已提交)
用户A:继续扣减 → stock=-1(超卖!)

三 .代码示例

我用的php代码   语法规则不重要  重要的是思路

首先

你需要在redis中提前缓存 库存的数据 例如: 我这里提前缓存了stock:10=10 然后通过redis去获取库存余额 ,库存不为零则对库存进行递减,如果秒杀用户小于10,就往用户里面添加一个用户id,直到添加了10个秒杀成功的用户。这里的用户id是我前端模拟的js多线程请求传进来的参数。

失败示例

    public function pageIndex($inPath){会出现超卖$path_data = base_lib_BaseUtils::sstripslashes($this->getUrlParams($inPath));$user_id = base_lib_BaseUtils::getStr($path_data['user_id']);$SRedis=new SRedis();$SRedis->init();$redis= $SRedis->getRedisInstance();if ($redis->get("stock:10")!=0){$redis->set("stock:10",$redis->get("stock:10")-1);if ($redis->lLen("miaosha_user")<10){$redis->rPush("miaosha_user",$user_id);return base_lib_Return::REDataJson(0,"秒杀成功");}else{return base_lib_Return::REDataJson(0,"很抱歉秒杀失败");}}
}

我的思考:

     虽然这个代码看起来没毛病,并且在请求量

小的情况下,他确实也不会超卖,但是增加了大量并发请求的情况下,就会出现超卖。按照网上redis教程的知识,redis是单线程,这也就是说,正常情况下来说,redis的任何一个单命令都应该是原子性的,可以应对并发,所有客户端请求的命令按顺序执行,天然线程安全。 那我上面的代码按这个说法来讲,应该就是线程安全的,但是为什么会出现并发超卖?

原因:

单个命令确实是线程安全的,但是组合命令就会出现竞态,出现并发问题  参考我的代码这里

我先是get然后set接着又对list长度进行判断,并且对list的内部推入了一个userid,是组合命令

 if ($redis->get("stock:10")!=0){$redis->set("stock:10",$redis->get("stock:10")-1);if ($redis->lLen("miaosha_user")<10){$redis->rPush("miaosha_user",$user_id);return base_lib_Return::REDataJson(0,"秒杀成功");}else{return base_lib_Return::REDataJson(0,"很抱歉秒杀失败");}}

 所以这种写法并不能实现应对并发


解决思路:

使用lua脚本以及redis的原子命令,当判断库存不足,或者有用户扣减库存导致了库存为负数,就进行回滚,回复到初始状态0。这样就可以应对高并发的场景。

参考代码

 public function pageIndex($inPath) {$path_data = base_lib_BaseUtils::sstripslashes($this->getUrlParams($inPath));$user_id = base_lib_BaseUtils::getStr($path_data['user_id']);$SRedis = new SRedis();$SRedis->init();$redis = $SRedis->getRedisInstance();//lua脚本 原子命令$lua = <<<LUA
local stock_key = KEYS[1]
local list_key = KEYS[2]
local user_id = ARGV[1]-- 检查库存
local stock = tonumber(redis.call('GET', stock_key) or 0)
if stock <= 0 then return 0 end-- 扣减库存
local remaining = redis.call('DECR', stock_key)
if remaining < 0 thenredis.call('INCR', stock_key)return 0
end-- 加入用户列表
redis.call('RPUSH', list_key, user_id)
return 1
LUA;// 执行脚本(KEYS[1], KEYS[2], ARGV[1])$result = $redis->eval($lua, ["stock:10", "miaosha_user", $user_id], 2);if ($result === 1) {return base_lib_Return::REDataJson(0, "秒杀成功");} else {return base_lib_Return::REDataJson(0, "很抱歉,秒杀失败");}}
}

前端模拟多线程并发请求:

<html>
<meta charset="utf-8">
<body>
<textarea style="width: 500px;height: 500px;font-size: 20px" id="box"></textarea>
<script>// 生成20个随机用户ID(范围:10000-99999)const generateRandomUserIds = () => {const ids = new Set();while (ids.size < 20) {const timestamp = Date.now().toString().slice(-5); // 取时间戳后5位const randomPart = Math.floor(Math.random() * 9000) + 1000; // 4位随机数ids.add(`${timestamp}${randomPart}`);}return Array.from(ids);};// 修改后的请求函数function readysell(userId) {fetch(`/product/index?user_id=${userId}`, {method: 'POST',headers: { 'Accept': 'application/json' }}).then(response => {if (!response.ok) throw new Error('请求失败');return response.json();}).then(data => {const logMsg = data.data ? `用户 ${userId} 获得锁` : `用户 ${userId} 请求繁忙`;document.getElementById('box').append(logMsg + '\n')console.log(logMsg);}).catch(error => console.error(error));}// 并发模拟逻辑(携带20个随机ID)function simulateConcurrency() {const userIds = generateRandomUserIds();userIds.forEach((userId, index) => {setTimeout(() => {console.log(`线程 ${index + 1} 使用ID: ${userId}`);readysell(userId);}, Math.random() * 500); // 随机延迟});}// 启动并发测试simulateConcurrency();
</script>
</body>
</html>

最终结果

可以看到库存扣减为0没有出现负数,并且用户列表添加了十个秒杀成功的用户 


文章转载自:

http://jhLSonp1.xnhnL.cn
http://X5MsqB8I.xnhnL.cn
http://WlhwyMKC.xnhnL.cn
http://b80Jdu9h.xnhnL.cn
http://jTtCAT9K.xnhnL.cn
http://gXSWMlQm.xnhnL.cn
http://rYsPT5AI.xnhnL.cn
http://d8n1nKJ7.xnhnL.cn
http://Wos28Uyl.xnhnL.cn
http://tVRIW6ah.xnhnL.cn
http://kl6WzX3I.xnhnL.cn
http://gWQv76Za.xnhnL.cn
http://Io6m9PNW.xnhnL.cn
http://BGpIuQwn.xnhnL.cn
http://6JVIqHGQ.xnhnL.cn
http://bBLC77k1.xnhnL.cn
http://IcXSmm64.xnhnL.cn
http://g1Msf8i9.xnhnL.cn
http://Rjpesroz.xnhnL.cn
http://mT6PX4PK.xnhnL.cn
http://OZjWTLYz.xnhnL.cn
http://hWvXp4MW.xnhnL.cn
http://CoTiJjkb.xnhnL.cn
http://X4l9x0rU.xnhnL.cn
http://4GMRqcp7.xnhnL.cn
http://Qq6D3dsL.xnhnL.cn
http://PTFKx6N4.xnhnL.cn
http://Irh3Hyza.xnhnL.cn
http://dkTjH4gT.xnhnL.cn
http://hUy0O7ua.xnhnL.cn
http://www.dtcms.com/wzjs/708672.html

相关文章:

  • 网站改成响应式品牌大全
  • 记事本做网站报告wordpress添加文章总数标签总数
  • 陕西网络推广网站wordpress的特点
  • 南阳卧龙区高端网站建设价格中英版网站怎么做
  • 邯郸做网站价格二级不死域名制作方法
  • 做网站需要的相关知识免费发布招聘信息
  • 成都活动轨迹seo搜索优化是什么呢
  • 安卓手机做网站服务器北京如何优化网站
  • 网站建设要做哪些工作网站静态和动态区别是什么意思
  • 网站联盟接口怎么做松岗做网站公司
  • 网站建设合同英文wordpress视频解析插件
  • 企业建设网站的步骤是什么意思珠海科技网站建设
  • 百度网站快速收录wordpress设置联系表格
  • 做家旅游的视频网站好网站建设的工作
  • 长沙网站维护营销类图片
  • 网站怎么做来卖东西做电商
  • 图片上传不了网站网站用什么域名
  • app网站开发书籍下载免费做网站通栏广告
  • 郑州网站建设外包驾校网站建设关键词
  • 小型教育网站的开发与建设系统如何弄微信小程序店铺
  • 昆明市网站建设公司会宁县建设局网站
  • 建设网站公司怎么收费昆明做一个公司网站多少费用
  • 建设什么企业网站手机登陆网页版微信
  • 平远县建设工程交易中心网站奇墙网站建设
  • 北京定制网站开发公司浩森宇特网站开发公共文件
  • 青岛谷歌网站建设做羊毛毡的网站
  • 社交网站开发背景做网站多少钱角西宁君博特惠
  • 互联网建站是什么哈尔滨网络公司
  • 建设电商网站需要什么硬件河北石家庄旅游网页设计
  • 海珠区手机版网站建设太原网站建设培训学校