当前位置:网站首页>Redis queue realizes second kill
Redis queue realizes second kill
2022-07-29 02:43:00 【Chenqing Nuo language】
Features of seckill system
1、 The number of people snapping up is far more than the inventory , Read write concurrency is huge .
2、 The stock is low , Write less effectively .
3、 Writing needs strong consistency , Goods cannot be sold beyond .
4、 Reading consistency is not high .
5、 Stability is difficult : High and low , A small dependency may directly cause an avalanche 、 It is difficult to predict the flow accurately , Too high also causes avalanches . Distributed cluster , There are many machines , The probability of failure is high .
6、 Accuracy is difficult : stock 、 Number of successful rush purchases , Create consistency between the number of orders .
7、 High performance difficult : We need to achieve extreme performance at limited cost .
Seckill system —— Principles of Architecture
1、 stability : Reduce third-party dependence , At the same time, its own service deployment also needs to be isolated . Pressure measurement 、 Downgrade 、 Current limiting scheme 、 Ensure that core services are available . Health detection mechanism is needed , The whole link avoids single point .
2、 High performance : Shorten the single request access path , Reduce IO. Reduce the number of interfaces , Reduce data throughput , Fewer requests .
Seckill service core implementation
1、 How to design seckill service : Meet basic needs , Achieve the ultimate performance of single service . Request link traffic optimization , Optimize every layer from client to server . Stability building .
2、 Basic needs : Inventory deduction 、 Check inventory 、 Queue progress .( Achieve the ultimate performance of single service ). Check the order details 、 Create order , Payment order .( The number of people who rush to buy is far more than inventory , Read write concurrency is high )
Basic needs —— Inventory deduction scheme
1、 Order less stock ?
Concurrent request ——> Create order ——> Inventory deduction ——> payment This process will not oversold , But the problem is that if someone places an order maliciously and doesn't pay , Occupy inventory .
2、 Pay less inventory ?
Concurrent request ——> Create order ——> payment ——> Inventory deduction This process is to pay for one-time deduction of inventory , If the user has finished buying the goods , Other users cannot place orders or orders are oversold .
3、 Withholding stock ?
Concurrent request ——> Inventory deduction ——> Create order ——> payment ——>10 Cancel the order without payment within minutes , Add inventory .
It is better to adopt the withholding inventory scheme .
wxml
<view>
<l-countdown time-type="second" time="{
{expire_time}}" bind:linend="changeBtn"/>
<view><image src="{
{Detail.image}}" bindtap="image"></image></view>
<view>{
{Detail.store_product.store_name}}</view>
<view>{
{Detail.price}}</view>
<view>
<l-button disabled="{
{ disabled }}" bind:lintap="buyGoods" type="error" data-id="{
{Detail.id}}"> Kill immediately </l-button>
</view>
</view>js
// pages/Detail/Detail.js
Page({
/**
* Initial data of the page
*/
data: {
expire_time:0,
disabled:false,
expire_time:'',
},
/**
* Life cycle function -- Monitor page loading
*/
onLoad(options) {
let that = this
let sid = options.id
wx.request({
url: 'http://www.wej.com/index.php/api/seckill/goodsDetail', // Just for the sample , Not a real interface address
data: {
sid
},
header: {
'content-type': 'application/json' // The default value is
},
success (res) {
console.log(res.data)
let newdate = Math.round(new Date().getTime() / 1000).toString()
let expire_time = res.data.data.start_time - newdate
console.log(expire_time)
that.setData({
Detail:res.data.data,
expire_time:expire_time
})
if(expire_time > 0){
that.setData({
disabled:true
})
}else{
that.setData({
disabled:false
})
}
}
})
},
buyGoods(c){
clearTimeout(this.TimeID);
this.TimeID = setTimeout(() => {
let goods_id = c.currentTarget.dataset.id
wx.request({
url: 'http://www.wej.com/index.php/api/seckill/snap_up', // Just for the sample , Not a real interface address
data: {
goods_id
},
header: {
'content-type': 'application/json' // The default value is
},
success (res) {
console.log(res.data)
}
})
}, 1000);
},
changeBtn(){
console.log(' The second kill begins ')
this.setData({
disabled:false
})
},
image(c){
wx.previewImage({
current: this.data.Detail.image, // The http link
urls: [this.data.Detail.image] // Pictures that need to be previewed http Link list
})
},
})json
{
"usingComponents": {
"l-countdown":"/dist/countdown",
"l-button":"/dist/button"
}
}<?php
namespace App\Http\Controllers;
use App\Models\AddressInfo;
use App\Models\StoreOrder;
use App\Server\Snowflake;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;
class Seckill extends Controller
{
/**
* Data preheating
* @return \Illuminate\Http\JsonResponse
*/
public function activity()
{
$result = \App\Models\Seckill::with('StoreProduct')
->get()->toArray();
foreach ($result as $val){
// Generate the corresponding commodity inventory queue
$goods = "activity_goods_".$val['product_id'];
for ($i=0; $i < $val['stock']; $i++) {
Redis::lpush($goods,1);
}
}
return response()->json(['code' => 20000, 'msg' => ' The query is successful ', 'data' => $result]);
}
/**、
* Second kill list
* @return \Illuminate\Http\JsonResponse
*/
public function activityList()
{
$result = \App\Models\Seckill::with('StoreProduct')
->get()->toArray();
return response()->json(['code' => 20000, 'msg' => ' The query is successful ', 'data' => $result]);
}
/**
* Second kill product details
* @return \Illuminate\Http\JsonResponse
*/
public function goodsDetail()
{
$goods_id = request()->get('sid');
$result = \App\Models\Seckill::with(['StoreProduct'])
->where('product_id',$goods_id)
->first();
return response()->json(['code' => 20000, 'data' => $result, 'msg' => ' The query is successful ']);
}
/**
* Verify inventory
* @return \Illuminate\Http\JsonResponse
*/
public function snap_up(){
// user ID
$userID = 1;
// goods ID
$goodsID = request()->get('goods_id');
// Corresponding commodity inventory queue
$goods = "activity_goods_".$goodsID;
// Set of users who have successfully snapped up corresponding products {1,3,4}
$robSuccessUser = "success_user".$goodsID;
// Judge whether the current user is in the queue of successful robbery
$result = Redis::sismember($robSuccessUser,$userID);
// If you're in here , It's over
if ($result) {
// If the rush is successful Return status code , Place an order
return response()->json(['code' => 20000, 'data' => '', 'msg' => ' It has been snapped up ']);
}
// Reduce inventory , Turn the data in the queue from the left head
$count = Redis::lpop($goods);
if (!$count) {
// If the rush is successful Return status code , Place an order
return response()->json(['code' => 20001, 'data' => '', 'msg' => ' It's all gone ']);
}
// Put the current spike uid Store it in the queue of successful rush purchase set
$success = Redis::sadd($robSuccessUser, $userID);
if(!$success){
// Already in the success queue , Add back inventory , To prevent concurrent requests from the same user
Redis::lpush($goods, 1);
// If the rush is successful Return status code , Place an order
return response()->json(['code' => 20002, 'data' => '', 'msg' => ' It has been snapped up ']);
}
// If the rush is successful Return status code , Place an order
return response()->json(['code' => 20000, 'data' => '', 'msg' => ' Seckill success ']);
}
/**
* Generate order
* @return false|\Illuminate\Http\JsonResponse|string
*/
public function createOrder(){
// user ID
$userID = request()->get('userID');
// goods ID
$goodsID = request()->get('goods_id');
// Address ID
$address_id = request()->get('address_id');
// Set of users who have successfully snapped up corresponding products
$robSuccessUser = "success_user".$goodsID;
// Judge whether the current user is in the queue of successful robbery
$result = Redis::sismember($robSuccessUser,$userID);
// If you're in here , It's over
if (!$result) {
// If the rush is successful Return status code , Place an order
return response()->json(['code' => 20003, 'data' => '', 'msg' => ' Hands slow !']);
}
DB::beginTransaction();
try{
// Reduce inventory
$shopData = \App\Models\Seckill::with('StoreProduct')
->where('product_id',$goodsID)
->first()->toArray();
$shopStock = \App\Models\Seckill::where('product_id',$goodsID)->update(['stock' => $shopData['stock'] - 1]);
if (!$shopStock) return json_encode(['code' => 50000,'msg' => ' Order failure ','data' => []]);
// Address
$address_info = AddressInfo::find($address_id)->toArray();
// Generate order
Snowflake::machineId($userID);
$order_id = substr(date('Ymd'),2).'-'.Snowflake::createOnlyId();
$data = [
'order_id' => $order_id,
'uid' => $userID,
'real_name' => $address_info['real_name'],
'user_phone' => $address_info['phone'],
'user_address' => $address_info['detail'],
'pay_price' => $shopData['store_product']['price'],
'pay_time' => time()
];
$orderAdd = StoreOrder::insert($data);
if (!$orderAdd) return json_encode(['code' => 50000,'msg' => ' Order failure ','data' => []]);
DB::commit();
// checkout success , Jump to the payment page
return response()->json(['code' => 20000, 'data' => '', 'msg' => ' checkout success !']);
}catch (\Exception $e){
DB::rollBack();
return response()->json(['code' => 50000, 'data' => '', 'msg' => $e->getMessage()]);
}
}
}
边栏推荐
- Branch management practice of "two pizza" team
- Where, having, group by, order by, is null, not in, subquery, delete, date function
- HTTP缓存
- Explain the four asynchronous solutions of JS in detail: callback function, promise, generator, async/await
- XSS range (II) xss.haozi
- FPGA刷题——存储器(RAM和FIFO的Verilog实现)
- 全新UI四方聚合支付系统源码/新增USDT提现/最新更新安全升级修复XSS漏洞补单漏洞
- K210——声源定位、声音识别
- xxxxx
- qt QStringList用法
猜你喜欢

The outsourcing company "mixed" for two years, and I only did five things seriously. Now I get byte offer smoothly.

详解异步任务:任务的状态及生命周期管理

Explain asynchronous tasks in detail: task status and lifecycle management

Redis主从模式、哨兵集群、分片集群

C language to achieve the three chess game

FFmpeg+SDL+QT实现简单是视频播放器

JMeter's BeanShell generates MD5 encrypted data and writes it to the database

Servlet三种实现方式

CUDA details GPU architecture

OSPF实验
随机推荐
3种过期策略
laravel框架中实现封装公共方法全局调用
Esbuild Bundler HMR
XSS range (II) xss.haozi
The outsourcing company "mixed" for two years, and I only did five things seriously. Now I get byte offer smoothly.
[quality] code quality evaluation standard
How to quickly design a set of cross end components that support rendering rich text content
平凡的快乐
Multimodal Unsupervised Image-to-Image Translation多通道无监督图像翻译
Read the recent trends of okaleido tiger and tap the value and potential behind it
快速掌握Nodejs安装以及入门
Three expiration strategies
FPGA skimming memory (Verilog implementation of ram and FIFO)
深度剖析 —— 预处理
一文理解分布式开发中的服务治理
In depth analysis - Pretreatment
第九天笔记
Stm32f103xx firmware function library-1
新版海螺影视主题模板M3.1全解密版本多功能苹果CMSv10后台自适应主题开源全解密版
3d智能工厂工艺流转可视化交互展示应用优点