PHP combined with Redis for high-concurrency snapping, second-kill function

Source: Internet
Author: User
Tags flock ord

Snapping, second-kill is now a very common application scenario, the main need to solve the problem has two: 1 high concurrency on the database pressure 2 How to solve the correct inventory reduction ("oversold" problem) for the first problem, it is very easy to think of caching to handle snapping, avoid directly manipulating the database, For example, use Redis. The focus is on the second problem. Optimization Scenario 1: Set the Inventory field Number field to unsigned, when inventory is 0 o'clock, because the field cannot be negative, it will return False (slightly) Optimization Scenario 2: Use the transaction, lock the operation of the row

<?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 number 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 whether the order operation//inventory is greater than 0mysql_query ("BEGIN"); Start Transaction $sql= "select number from Ih_store where goods_id= ' $goods _id ' and sku_id= ' $sku _id ' for UPDATE ';//This record is locked, Other transactions must wait for the transaction to be committed before executing $rs=mysql_query ($sql, $conn), $row =mysql_fetch_assoc ($rs), if ($row [' number ']>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 is unlocked}else{insertlog (' Inventory reduction failed ');    }}else{Insertlog (' insufficient inventory '); mysql_query ("ROLLBACK");}? >

  optimization Scenario 3: Use non-blocking file exclusive lock

<?php$conn=mysql_connect ("localhost", "root", "123456"), if (! $conn) {echo "Connect failed"; Exit;} mysql_select_db ("Big-bak", $conn); mysql_query ("Set names UTF8"); $price =10; $user _id=1; $goods _id=1; $sku _id=11;$ number=1;//generates a unique order number 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);} $fp = fopen ("Lock.txt", "w+"); if (!flock ($fp, LOCK_EX |    LOCK_NB) {echo "system busy, please try again later"; return;} Order $sql= "Select number from Ih_store where goods_id= ' $goods _id ' and sku_id= ' $sku _id '"; $rs =mysql_query ($sql, $conn); $    ROW=MYSQL_FETCH_ASSOC ($RS); if ($row [' number ']>0) {///inventory is greater than 0//simulated under single 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 ');    Flock ($FP, lock_un);//Release lock}else{insertlog (' Inventory reduction failed '); }}else{Insertlog (' insufficient inventory ');} Fclose ($FP);

  optimization Scenario 4: Use Redis queues, because the pop operation is atomic, even if there are many users arriving at the same time, it is recommended to use (MySQL transaction under high concurrency performance degradation is very bad, file lock Way is also)
Inventory items first, such as queues

<?php$store=1000; $redis =new redis () $result = $redis->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 ');?    > Snapping, describing logic <?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 number 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 a single operation//pre-order Redis queue Inventory $redis=new redis (); $result = $redis->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 reduction failed ');} The above is just a simple simulation of high-level snapping, the real scene is much more complicated than this, a lot of attention places such as snapping up the page to make static, through the AJAX call interface again as above will cause a user to rob multiple, thinking: Need a queue queue and snapping results and inventory queue. High concurrency, the user first into the queued queue, with a thread loop processing from the queued queue to remove a user, determine whether the user has snapped the results queue, if in, then has snapped, otherwise not snapped, inventory minus 1, write the database, the user into the result queue.

PHP combined with Redis for high-concurrency snapping, second-kill function

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.