Рубрики
Uncategorized

PHP сочетается с redis для реализации примера высокого параллелизма функций покупки flash и seckill

Автор оригинала: David Wong.

В настоящее время Snap up и seckill являются распространенными сценариями приложений. Есть две основные проблемы, которые необходимо решить:

Давление высокого параллелизма на базу данных

2. Как решить проблему “перепроданности” в конкурентном состоянии

Что касается первой проблемы, то легко подумать об использовании кэша для решения проблемы покупки флэш-памяти и избежать прямой работы с базой данных, например, с помощью redis .

Сосредоточьтесь на втором вопросе

Обычное письмо:

Запросите запасы соответствующих товаров, чтобы узнать, больше ли они 0, а затем выполните такие операции, как создание заказа. Однако, если запас больше 0, возникнет проблема, если он высокий и выдан, что приведет к отрицательному запасу

php
$conn=mysql_connect("localhost","big","123456"); 
if(!$conn){ 
	echo "connect failed"; 
	exit; 
} 
mysql_select_db("big",$conn); 
mysql_query("set names utf8");

$price=10;
$user_id=1;
$goods_id=1;
$sku_id=11;
$number=1;

//Generate unique order
function build_order_no(){
  return date('ymd').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
}
//Log
function insertLog($event,$type=0){
	global $conn;
	$sql="insert into ih_log(event,type) 
	values('$event','$type')"; 
	mysql_query($sql,$conn); 
}

//Simulate single order operation
//Whether the inventory is greater than 0
$SQL = "select number from ih_store where goods_id = '$goods_id' and sku_id = '$sku_id'"; // when unlocking, the data of goods_id = '$goods_id' and sku_id = '$SKU ID' in ih_store data is locked (Note 3). Other transactions can only be executed after the transaction submission
$rs=mysql_query($sql,$conn);
$row=mysql_fetch_assoc($rs);
If ($row ['number '] > 0) {// high and sending will lead to oversold
	$order_sn=build_order_no();
	//Generate order 
	$sql="insert into ih_order(order_sn,user_id,goods_id,sku_id,price) 
	values('$order_sn','$user_id','$goods_id','$sku_id','$price')"; 
	$order_rs=mysql_query($sql,$conn); 
	
	//Inventory reduction
	$sql="update ih_store set number=number-{$number} where sku_id='$sku_id'";
	$store_rs=mysql_query($sql,$conn); 
	if(mysql_affected_rows()){ 
		Insertlog ('inventory reduction succeeded ');
	}else{ 
		Insertlog ('inventory decrease failed ');
	} 
}else{
	Insertlog ('out of stock ');
}
?>

Схема оптимизации 1: Установите для поля номер поля инвентаризации значение без знака. Когда запас равен 0, поскольку поле не может быть отрицательным, оно вернет значение false

//Inventory reduction
$sql="update ih_store set number=number-{$number} where sku_id='$sku_id' and number>0";
$store_rs=mysql_query($sql,$conn); 
if(mysql_affected_rows()){ 
	Insertlog ('inventory reduction succeeded ');
}

Схема оптимизации 2: Использование MySQL Транзакция, блокировка операции

0){
	//Generate order 
	$order_sn=build_order_no();	
	$sql="insert into ih_order(order_sn,user_id,goods_id,sku_id,price) 
	values('$order_sn','$user_id','$goods_id','$sku_id','$price')"; 
	$order_rs=mysql_query($sql,$conn); 
	
	//Inventory reduction
	$sql="update ih_store set number=number-{$number} where sku_id='$sku_id'";
	$store_rs=mysql_query($sql,$conn); 
	if(mysql_affected_rows()){ 
		Insertlog ('inventory reduction succeeded ');
		Mysql_query ("commit"); // transaction commit unlocks
	}else{ 
		Insertlog ('inventory decrease failed ');
	}
}else{
	Insertlog ('out of stock ');
	mysql_query("ROLLBACK");
}
?>

Схема оптимизации 3: Используйте неблокирующую эксклюзивную блокировку файлов

 0) {// whether the inventory is greater than 0
	//Simulate single order operation 
	$order_sn=build_order_no();	
	$sql="insert into ih_order(order_sn,user_id,goods_id,sku_id,price) 
	values('$order_sn','$user_id','$goods_id','$sku_id','$price')"; 
	$order_rs=mysql_query($sql,$conn); 
	
	//Inventory reduction
	$sql="update ih_store set number=number-{$number} where sku_id='$sku_id'";
	$store_rs=mysql_query($sql,$conn); 
	if(mysql_affected_rows()){ 
		Insertlog ('inventory reduction succeeded ');
		Float ($FP, lock_un); // release the lock
	}else{ 
		Insertlog ('inventory decrease failed ');
	} 
}else{
	Insertlog ('out of stock ');
}
fclose($fp);

План оптимизации 4: Используйте очередь redis, потому что операция pop атомарна, даже если многие пользователи прибывают одновременно, она выполняется по очереди, рекомендуется использовать (транзакция MySQL находится в высокой параллелизме, и производительность отправки значительно снижается, так же как и способ блокировки файлов)

Сначала проведите инвентаризацию товаров в виде очереди

connect('127.0.0.1',6379);
$res=$redis->llen('goods_store');
echo $res;
$count=$store-$res;
for($i=0;$i<$count;$i++){
	$redis->lpush('goods_store',1);
}
echo $redis->llen('goods_store');
?>

Паническая покупка и логика описания

connect('127.0.0.1',6379);
$count=$redis->lpop('goods_store');
if(!$count){
	insertLog('error:no store redis');
	return;
}

//Generate order 
$order_sn=build_order_no();
$sql="insert into ih_order(order_sn,user_id,goods_id,sku_id,price) 
values('$order_sn','$user_id','$goods_id','$sku_id','$price')"; 
$order_rs=mysql_query($sql,$conn); 

//Inventory reduction
$sql="update ih_store set number=number-{$number} where sku_id='$sku_id'";
$store_rs=mysql_query($sql,$conn); 
if(mysql_affected_rows()){ 
	Insertlog ('inventory reduction succeeded ');
}else{ 
	Insertlog ('inventory decrease failed ');
}

Имитация теста с высоким параллелизмом 5000

верстак -c 5000 -t 60 http://192.168.1.198/big/index.php ab -r -n 6000 -c 5000 http://192.168.1.198/big/index.php

Вышесказанное-всего лишь простая симуляция высокого и выданного порыва к покупке, реальная сцена гораздо сложнее, чем эта, много внимания

Если страница сделана статичной, вызовите интерфейс через Ajax

Другим примером является то, что вышеизложенное приведет к тому, что один пользователь ограбит нескольких пользователей

Требуется очередь в очередь, очередь результатов и очередь инвентаризации. В случае высокого параллелизма сначала поместите пользователя в очередь, выведите пользователя из очереди с помощью обработки цикла потока и определите, находится ли пользователь в очереди результатов срочной покупки. Если это так, это была срочная покупка, в противном случае это не была срочная покупка, инвентарь уменьшается на 1, и напишите база данных , поместите пользователя в очередь результатов.

Технический паспорт испытания

--
--Database: ` big`
--

-- --------------------------------------------------------

--
--Structure of table ` IH ABCD goods`
--


CREATE TABLE IF NOT EXISTS `ih_goods` (
  `goods_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `cat_id` int(11) NOT NULL,
  `goods_name` varchar(255) NOT NULL,
  PRIMARY KEY (`goods_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;


--
--Data in the transfer table ` ih_goods`
--


INSERT INTO `ih_goods` (`goods_id`, `cat_id`, `goods_name`) VALUES
(1, 0, 'Xiaomi mobile phone');

-- --------------------------------------------------------

--
--Table structure ` IH log`
--

CREATE TABLE IF NOT EXISTS `ih_log` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `event` varchar(255) NOT NULL,
 `type` tinyint(4) NOT NULL DEFAULT '0',
 `addtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
 PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

--
--Data in transfer table ` IH \`
--


-- --------------------------------------------------------

--
--Table structure ` IH ABCD order`
--

CREATE TABLE IF NOT EXISTS `ih_order` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `order_sn` char(32) 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 NOT NULL DEFAULT CURRENT_TIMESTAMP,
 PRIMARY KEY (`id`)
)Engine = InnoDB default charset = utf8 comment = order table 'Auto increment = 1;

--
--Data in transfer table ` ih'order`
--


-- --------------------------------------------------------

--
--Table structure ` ih'store`
--

CREATE TABLE IF NOT EXISTS `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',
 `Freeze ` int (11) not null default '0' comment 'virtual inventory',
 PRIMARY KEY (`id`)
)Engine = InnoDB default charset = utf8 comment = inventory 'Auto increment = 2;

--
--Transfer data in the table ` ih'store`
--

INSERT INTO `ih_store` (`id`, `goods_id`, `sku_id`, `number`, `freez`) VALUES
(1, 1, 11, 500, 0);

Выше приведен пример PHP и redis, которые Xiaobian предоставил вам для реализации функций высокоскоростного шоппинга и seckill. Я надеюсь, что вы сможете больше поддерживать developepaer~