В настоящее время Snap up и seckill являются распространенными сценариями приложений. Есть две основные проблемы, которые необходимо решить:
Давление высокого параллелизма на базу данных
2. Как решить проблему “перепроданности” в конкурентном состоянии
Что касается первой проблемы, то легко подумать об использовании кэша для решения проблемы покупки флэш-памяти и избежать прямой работы с базой данных, например, с помощью redis .
Сосредоточьтесь на втором вопросе
Обычное письмо:
Запросите запасы соответствующих товаров, чтобы узнать, больше ли они 0, а затем выполните такие операции, как создание заказа. Однако, если запас больше 0, возникнет проблема, если он высокий и выдан, что приведет к отрицательному запасу
Схема оптимизации 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~