php(TP 5)+redisによる秒殺買い占め(ユーザ購入回数制限とユーザ購入回数制限なし)(付ソースコード)
56924 ワード
ユーザーの購入回数を制限しない
https://www.cnblogs.com/qqlong/p/9327844.html 参考住所
説明:今回の環境テストはLinuxで実行する
使用する環境、バージョン、ツール
ThinkPHP 5をインストールする.0の最新バージョンインストールRedisキャッシュLNMP Yumインストールmysql 5.8 Yum abテストツールをインストールnginx仮想ドメイン名を構成
ユーザーの購入回数を制限しない
主なコードは次のとおりです.
テスト:
Webページまたはコマンドラインで、次のコードを順番に実行します.
テストアドレス:
コマンドラインに次のように入力します.
エラーを解決するアドレス
実行結果:
データベースのデータが正しいかどうか:
オーダー表ih_order:
これで,ユーザの購入回数を制限しないコードが完了する.
パケットアドレス
データベース:
https://www.cnblogs.com/qqlong/p/9327844.html 参考住所
説明:今回の環境テストはLinuxで実行する
使用する環境、バージョン、ツール
:lnmp + redis 。
:Centos 7、nginx 1.7.4、mysql 5.8、 php 7.3nts、 redis 5.0.6
:ab
ThinkPHP 5をインストールする.0の最新バージョンインストールRedisキャッシュLNMP Yumインストールmysql 5.8 Yum abテストツールをインストールnginx仮想ドメイン名を構成
ユーザーの購入回数を制限しない
主なコードは次のとおりです.
#!/bin/bash
/**
* User: hzbskak
* Date: 2019/12/25 - 16:23
*/
namespace app\index\controller;
use think\Db;
use think\Exception;
class Seckill
{
public $price = 10;
public $user_id = 1;
public $goods_id = 1;
public $sku_id = 11;
public $number = 1;
private $redis = null;
public function __construct()
{
//
// redis
$this->redis=new \Redis();
$this->redis->connect('127.0.0.1',6379);
}
//
public function go()
{
//
if( !$this->userPop())
{
$this->insertLog('no users buy');
return;
}
//
$count=$this->redis->lpop('goods_store');
if(!$count){
$this->insertLog($this->user_id .' error:no store redis');
return;
}
//
$order_sn=$this->build_order_no();
$order_rs = Db::name( 'order')
->insert([
'order_sn' => $order_sn,
'user_id' => $this->user_id,
'goods_id' => $this->goods_id,
'sku_id' => $this->sku_id,
'price' => $this->price
]);
//
$store_rs = Db::name( 'store')
->where( 'sku_id', $this->sku_id)
->setDec( 'number', $this->number);
if($store_rs){
$this->insertLog($this->user_id .' ');
return;
}else{
$this->insertLog($this->user_id .' ');
return;
}
}
//
// id
public function userPop()
{
return $this->user_id = $this->redis->rpoplpush( 'user_line_up', 'user_pop_queue');
}
public function user()
{
dump( $this->redis->lRange( 'user_line_up', 0, -1));
}
public function clear()
{
dump( $this->redis->flushDB());
}
public function make()
{
echo $this->goodsStockAddQueue();
echo $this->userLineUp();
}
public function test()
{
dump( $this->redis->keys( '*'));
dump( $this->redis->lLen( 'user_line_up'));
dump( $this->redis->lLen( 'goods_store'));
}
// $i user_id
public function userLineUp()
{
//
$num = [];
for ( $a=0;$a<2;$a++)
{
for ( $i=1;$i<1001;$i++)
{
array_push( $num, $i);
}
//
shuffle( $num);
}
for ( $i=0; $i< count( $num); $i++)
{
$this->redis->lPush( 'user_line_up', $num[$i]);
}
echo ' :'.$this->redis->lLen( 'user_line_up');
}
//
public function goodsStockAddQueue()
{
$store=500;
$res=$this->redis->llen('goods_store');
$count=$store-$res;
for($i=0;$i<$count;$i++){
$this->redis->lpush('goods_store',1);
}
echo ' :'.$this->redis->llen('goods_store');
}
//
function build_order_no(){
return date('ymd').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
}
//
function insertLog($event,$type=0){
Db::name( 'log')
->insert( [
'event' => $event,
'type' => $type
]);
}
}
テスト:
Webページまたはコマンドラインで、次のコードを順番に実行します.
( )
http://seckill.ln//index/seckill/clear
true
http://seckill.ln//index/seckill/make
:500 :2000
http://seckill.ln/index/seckill/test
array(2) {
[0] => string(11) "goods_store"
[1] => string(12) "user_line_up"
}
int(2000)
int(500)
int(0)
テストアドレス:
http://seckill.ln/index/seckill/go
コマンドラインに次のように入力します.
[root@localhost ~]# ab -r -n 6000 -c 5000 http://seckill.ln/index/seckill/go
# -n ,-c -r ,
, ab :
socket: Too many open files (24)
エラーを解決するアドレス
実行結果:
Failed Requests 5256, , , 。
, return。
:
Time taken for tests: 15.576 seconds
Requests per second: 385.20 [#/sec] (mean)
[root@localhost ~]# ab -r -n 6000 -c 5000 http://seckill.ln/index/seckill/go
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking seckill.ln (be patient)
Completed 600 requests
Completed 1200 requests
Completed 1800 requests
Completed 2400 requests
Completed 3000 requests
Completed 3600 requests
Completed 4200 requests
Completed 4800 requests
Completed 5400 requests
Completed 6000 requests
Finished 6000 requests
Server Software: nginx
Server Hostname: seckill.ln
Server Port: 80
Document Path: /index/seckill/go
Document Length: 0 bytes
Concurrency Level: 5000
Time taken for tests: 15.576 seconds
Complete requests: 6000
Failed requests: 5087
(Connect: 0, Receive: 0, Length: 5087, Exceptions: 0)
Write errors: 0
Non-2xx responses: 5087
Total transferred: 1771965 bytes
HTML transferred: 864790 bytes
Requests per second: 385.20 [#/sec] (mean)
Time per request: 12980.180 [ms] (mean)
Time per request: 2.596 [ms] (mean, across all concurrent requests)
Transfer rate: 111.09 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 168 575.7 0 3011
Processing: 1 725 2051.4 13 15316
Waiting: 1 725 2051.5 13 15316
Total: 5 893 2186.6 13 15447
Percentage of the requests served within a certain time (ms)
50% 13
66% 191
75% 501
80% 865
90% 3504
95% 5808
98% 8273
99% 10239
100% 15447 (longest request)
データベースのデータが正しいかどうか:
在庫表ih_store: mysql> select * from ih_store;
+----+----------+--------+--------+-------+
| id | goods_id | sku_id | number | freez |
+----+----------+--------+--------+-------+
| 1 | 1 | 11 | 0 | 0 |
+----+----------+--------+--------+-------+
1 row in set (0.02 sec)
number 0,
: number UNSIGNED ,
オーダー表ih_order:
mysql> select COUNT(*) from ih_order;
+----------+
| COUNT(*) |
+----------+
| 500 |
+----------+
1 row in set (0.02 sec)
これで,ユーザの購入回数を制限しないコードが完了する.
パケットアドレス
データベース:
test.sql
/*
Navicat Premium Data Transfer
Source Server : ln
Source Server Type : MySQL
Source Server Version : 50728
Source Host : 192.168.238.129:3306
Source Schema : test
Target Server Type : MySQL
Target Server Version : 50728
File Encoding : 65001
Date: 26/12/2019 11:59:26
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for ih_goods
-- ----------------------------
DROP TABLE IF EXISTS `ih_goods`;
CREATE TABLE `ih_goods` (
`goods_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`cat_id` int(11) NOT NULL,
`goods_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
PRIMARY KEY (`goods_id`) USING BTREE
) ENGINE = MyISAM AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of ih_goods
-- ----------------------------
INSERT INTO `ih_goods` VALUES (1, 0, ' ');
-- ----------------------------
-- Table structure for ih_log
-- ----------------------------
DROP TABLE IF EXISTS `ih_log`;
CREATE TABLE `ih_log` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`event` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`type` tinyint(4) NOT NULL DEFAULT 0,
`addtime` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
PRIMARY KEY (`id`) USING BTREE
) ENGINE = MyISAM AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Table structure for ih_order
-- ----------------------------
DROP TABLE IF EXISTS `ih_order`;
CREATE TABLE `ih_order` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`order_sn` char(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`user_id` int(11) NOT NULL,
`status` int(11) NOT NULL DEFAULT 0,
`goods_id` int(11) NOT NULL DEFAULT 0,
`sku_id` int(11) NOT NULL DEFAULT 0,
`price` float NOT NULL,
`addtime` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = ' ' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Table structure for ih_store
-- ----------------------------
DROP TABLE IF EXISTS `ih_store`;
CREATE TABLE `ih_store` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`goods_id` int(11) NOT NULL,
`sku_id` int(10) UNSIGNED NOT NULL DEFAULT 0,
`number` int(10) NOT NULL DEFAULT 0,
`freez` int(11) NOT NULL DEFAULT 0 COMMENT ' ',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = ' ' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of ih_store
-- ----------------------------
INSERT INTO `ih_store` VALUES (1, 1, 11, 500, 0);
SET FOREIGN_KEY_CHECKS = 1;