Implementation of the seckill system

Time:2021-7-14

How to achieve high availability in high concurrency system

principle

CDN; CDN; Nginx current limiting, asynchronous queue (high concurrent traffic becomes shared traffic)
Divide and rule: LVS + nginx load balancing

features

Write strong consistency (not oversold)
Read weak consistency (read may be in stock, but cannot place an order)

Core implementation

Implementation of reading service
Write service implementation
Implementation of queuing progress query
How to optimize the link traffic (LVS layer, sever layer, reduce the influx of traffic)

Flow funnel

In the request link, peak clipping, current limiting, automatic degradation and fusing are performed for each layer

Implementation of seckill system [an example of didi instructor]

The maximum QPS that ab pressure measurement interface can bear

-N access 1000 times, - C concurrent 100

Implementation of the seckill system

Implementation of the seckill system

Requests per second is the throughput in seconds, so this value is OK; End QPS.

Current limiting

Tengine version adopts http_ limit_ req_ Module

Please refer to   http://tengine.taobao.org/doc…

Similar to the official nginx, it supports multiple variables and multiple limits_ req_ The setting of zone. For example:

limit_req_zone $binary_remote_addr zone=one:3m rate=1r/s;
limit_ req_ zone $binary_ remote_ addr $uri zone=two:3m rate=1r/s;               # $ Uri: without client request parameters
limit_ req_ zone $binary_ remote_ addr $request_ uri zone=thre:3m rate=1r/s;      # $ request_ Uri: with client request parameters

The second instruction above indicates that when the same IP address and access to the same URI, it will result in the limit req (1 request per second).

The official version of nginx restricts IP connection and concurrency. There are two modules respectively

  • limit_ req_ zone   It is used to limit the number of requests per unit time, that is, speed limitLeaky bucket algorithm
  • limit_ req_ conn   It is used to limit the number of connections at the same time

Where limit_ req_ The conn module can limit the number of concurrent access connections of a single user or the total number of concurrent connections to the service according to the source IP.

The biggest difference between the two algorithms: token bucket algorithm can deal with burst traffic, but copper leakage algorithm can’t.

Implementation of the seckill system

Implementation of the seckill system

For reference: https://www.cnblogs.com/bigli…

Leaky bucket algorithm

We assume that the system is a leaky bucket. When the request arrives, it is to add water to the leaky bucket. When the request is processed, it is water leaking from the bottom of the leaky bucket.The speed of water leakage is fixedWhen the water is added too fast, the bucket overflows, which is called “reject request”. So that the volume of water in the bucket can not exceed the capacity of the bucket. The main purpose is to control the rate of data injection into the network and smooth the burst traffic on the network. Leaky bucket algorithm provides a mechanism by which the burst traffic can be shaped to provide a stable traffic for the network.

Examples are as follows:

http {

limit_conn_log_level error;

limit_conn_status 503;

limit_conn_zone **$binary_remote_addr** zone=one:10m;

limit_conn_zone **$server_name** zone=perserver:10m;

limit_ req_ zone **$binary_ remote_ addr** zone=allips:100m     rate=10r/s;    // Of which $binary_ remote_ Sometimes addr needs to use its own * * log\_ Format variable * * is configured to replace

server {

                …………………….

                limit_conn  one  100;                                              

                limit_conn perserver 1000;

                limit_req   zone=allips  burst=5  nodelay;

                ………………….

         }

}

Parameter explanation:

Zone = one or allips indicates that a storage area named “one” or “allips” is set, with a size of 10 megabytes

rate=10r/s   Allow no more than 10 requests per second

Burst = 5 indicates that the maximum number of delayed requests is no more than 5.   If too many requests are limited, the delay is unnecessary  , At this time, you need to use the nodelay parameter, and the server will immediately return the 503 status code.

limit_ conn   one    100 means that the maximum number of concurrent connections per client IP is limited to 100

limit_ Conn perserver 1000 indicates that the total number of connections provided by the service should not exceed 1000. If the number exceeds 1000, it will be rejected

Examples are as follows:

http {

    limit_req_zone $binary_remote_addr zone=one:100m   rate=10r/m;

    server {

              limit_req   zone=one  burst=1  nodelay;

    }

}

Configuration explanation

rate=10r/m 

No more than one request per second is allowed, and the maximum number of delayed requests is no more than 5

If the request does not need to be delayed, add the nodelay parameter, and the server will immediately return 503 status code. Without this field, a large number of TCP connection requests will wait.

http{  
    limit_zone one  $binary_remote_addr  10m;  
    server  
    {  
    ......  
    limit_conn  one  1;  
    ......  
    }  
   }

there   one   Is to declare a limit_ zone   My name is $binary_ remote_ Addr is an alternative  $ remore_ addr   Variable, 10m   Is the space for session state storage.

limit_conn one 1 

Limit the number of concurrent connections to 1,   allow only one connection per an IP addressAt a time.

limit_ req_ The function of zone is to limit the user’s connection frequency through the leaky bucket principle (this module allows you to limit the number of requests for a specific session or special needs at a single address)  ) 。

and   limit_ zone   The function is to limit the number of concurrent connections of a client( This module can limit the number of specified sessions in a single address or the number of concurrent connections in special cases.

One is to limit concurrent connections, and the other is to limit connection frequency. It seems that there is no difference on the surface. Let’s see the actual effect~~~
Add these two parameters to my test machine. Here are some of my configuration files

http{  
    limit_zone one  $binary_remote_addr  10m;  
    #limit_req_zone  $binary_remote_addr  zone=req_one:10m rate=1r/s;  
    server  
    {  
    ......  
    limit_conn   one  1;  
    #limit_req   zone=req_one  burst=120;  
    ......  
    }  
}

Configuration explanation

limit_zone one  $binary_remote_addr  10m;  

there   one   It’s a statement   limit_ zone   My name is $binary_ remote_ Addr is an alternative  $ remore_ addr   Is the storage space of session state

limit_conn one 1 

Limit the number of concurrent connections to 1

limit_ Two working conditions of zone
limit_reqzone=one burst=10;

By default, this is configured so that each request has a delay time,

limit_req_zone$binary_remote_addr zone=one:100m rate=10r/m;

That is, there are 10 tokens for users to use every minute. According to the configuration of a, there will be a delay. Each request time is 60 / 10, and each request time is 6S.

limit_reqzone=one burst=10 nodelay;

Add nodelay configuration, so that you can access according to your network condition. After 10 times of access in one minute, the server will directly return to 503.

limit_req_zone$binary_remote_addr zone=one:100m rate=10r/m;

That is, there are 10 tokens for users to use every minute. According to the configuration of B, the URL will be accessed according to the network situation. If there are more than 10 tokens in one minute, the server will return 503 and wait for the next minute to get the access token.

rate=10r/m 

Each address can only request 10 times per minute, that is to say, according to the leaky bucket principle, burst = 1   There is one token in total, and only 10 new tokens are added every minute,
After one token is sent, the extra requests will return 503.

add   More than after nodelay   The request of burst size will directly return 503. If there is no this field, a large number of TCP connection requests will wait.

http{
    ...
    #Define a limit called allips_ req_ Zone is used to store sessions. The size is 10m memory,
    #With $binary_ remote_ Addr is key, and the average number of requests per second is limited to 20,
    #1m can store 16000 States, and the value of rete must be an integer,
    #If one request is limited to two seconds, it can be set to 30R / m
    limit_req_zone $binary_remote_addr zone=allips:10m rate=20r/s;
    ...
    server{
        ...
        location {
            ...
            #The number of requests per IP per second is limited to no more than 20, and the number of leaky buckets burst is 5
            #Brut means that if there are 19 requests in 1 second, 2 second, 3 second and 4 second,
            #25 requests in the fifth second are allowed.
            #However, if you have 25 requests in the first second and more than 20 requests in the second second, 503 errors will be returned.
            #Nodelay. If this option is not set, the average rate is strictly used to limit the number of requests,
            #When there are 25 requests in the first second, 5 requests will be executed in the second second,
            #Set nodelay, 25 requests will be executed in the first second.
            limit_req zone=allips burst=5 nodelay;
            ...
        }
        ...
    }
    ...
}

cdn

Implementation of the seckill system

Implementation of the seckill system

load balancing

Implementation of the seckill system

A problem of IP hash is that if the total IP of a school is assigned to a certain machine, then the access volume of the machine will be very large.

Message queuing

In a high concurrency environment, due to the lack of time for synchronous processing, requests are often blocked. For example, a large number of requests such as insert and update arrive at the dB at the same time, which directly leads to countless row locks and table locks. Even in the end, the requests will accumulate too many, thus triggering the too many connections error. By using message queuing, we can process requests asynchronously to relieve the pressure of the system.

Flow estimation

Implementation of the seckill system

Characteristics and difficulties of second kill system

Implementation of the seckill system

Implementation of the seckill system

Strategy of seckill system

Implementation of the seckill system
Seckill system is deployed in isolation from other services, so it is also a separate service, seckill service.

Implementation of the seckill system

Implementation requirements

Implementation of the seckill system

The realization of second kill system — the plan of stock deduction

Several ways of deducting inventory

● order deduction inventory

When the buyer places an order, the total inventory of goods minus the buyer’s purchase quantity. Reducing inventory by placing an order is the simplest way to reduce inventory, and it is also the most accurate way to control. When placing an order, the inventory of goods is controlled directly through the transaction mechanism of the database, so that there will be no oversold. But you should know that some people may not pay after placing the order.

Payment deducting inventory

That is, the buyer does not reduce the inventory immediately after placing an order, but does not reduce the inventory until the user pays, otherwise the inventory will be reserved for other buyers. But because the inventory is reduced only when the payment is made, if the concurrency is relatively high, the buyer may not be able to pay after placing the order, because the goods may have been bought by others.

Withholding inventory

This method is relatively complicated. After the buyer places an order, the inventory will be reserved for a certain period of time (such as 10 minutes). After that, the inventory will be released automatically, and other buyers can continue to buy after the release. Before the buyer makes payment, the system will check whether the inventory of the order is still reserved. If not, the system will try to deduct again; If the inventory is insufficient (that is, the withholding fails), the payment is not allowed to continue; If the withholding is successful, the payment is completed and the inventory is actually subtracted.

Problems in several ways of reducing inventory

Because there are two or more steps in the shopping process, there will be some loopholes that may be exploited by malicious buyers by reducing inventory in different operation steps, such as malicious orders.

If we adopt the method of “reducing inventory by placing an order”, that is, the inventory will be reduced after the user places an order. Under normal circumstances, the probability of payment after the buyer places an order will be very high, so there won’t be much problem. However, there is an exception to this scenario, that is, when the seller participates in an activity, the effective time of the activity is the selling time of the goods. If a competitor orders all the goods of the seller in a malicious way, reducing the inventory of the goods to zero, the goods will not be sold normally. You know, these people who maliciously place orders will not really pay, which is the deficiency of the method of “placing orders to reduce inventory”.

Since “reducing inventory by placing an order” may lead to malicious orders, thus affecting the seller’s sales of goods, is there any way to solve it? You may think, is it OK to adopt the method of “payment minus inventory”? Yes, indeed. However, “payment minus inventory” will lead to another problem: inventory oversold.

Since both “order minus inventory” and “payment minus inventory” have shortcomings, can we combine the two and link the two operations before and after. When placing an order, we should first make a deduction, and then release the inventory without payment within the specified time, that is, we should adopt the method of “withholding inventory”?

This kind of plan can really alleviate the above problems to a certain extent. But has it been completely solved? Not really! In this case, although the effective payment time is set to 10 minutes, the malicious buyer can place an order again after 10 minutes, or reduce the inventory by ordering many items at a time. In view of this situation, the solution is to combine security and anti cheating measures to stop.

How to solve the problem of single deduction inventory

Identify and mark the buyers who often place orders but do not pay (the inventory can not be reduced when the marked buyers place orders), set the maximum number of items to be purchased for certain categories (for example, one person can only buy 3 items at most for participating activities), and set the maximum number of items not to be paid for repeated orders
Limit the number of operations.

Server performance optimization (extreme squeezing CPU)

The point is to avoid unnecessary context switching.
Process, switch between threads, system call, CPU all need to consume resource scheduling, these are invalid actions. The effective action is to execute the program,

Threads, the use of coroutines, can avoid both.
So it can be seen that PHP is not a better and more suitable language for inventory deduction.

In order to achieve the ultimate performance, PHP can do is to reduce the blocking IO (disk file read and write, remote call).

Implementation of the seckill system

Redis, stand-alone single service can achieve 10W QPS.

Implementation of the seckill system

Realization of inventory deduction

Go is a single process, PHP is a multi process. Code implementation:

Implementation of the seckill system
Redis + Lua script to prevent oversold. Realization of commodity information and rush purchase schedule

Implementation of the seckill system
Product title picture details, which are not often changed and relatively static information, can be static + CDN

Price, promotion, inventory, these relative dynamic information, can do hot cache.

The data structure difference between array and hash table,
The biggest difference: different ways, array through the key to find value, hash through the function to find.

https://www.cnblogs.com/chenj…

Users who have successfully reduced inventory are saved in array A and stored in sequence. The array is the index array, the key is the index value, and the value is uid.
Hash table, key is uid, and value is the index value of array a.

Every consumption data is consumed from beginning to end. The index value of the latest consumption is recorded as X,

Get the queue progress,
Array and hash are stored in memory. The query complexity of array and hash table is O1, which is very fast.

Implementation of the seckill system
Implementation of the seckill system

Deduction of inventory, put a small part of the flow, to the unified deduction of inventory place, operation.
Write orders, asynchronous consumption.

Request link implementation funnel traffic

Implementation of the seckill system

For example: the verification code of 12306 is to cut the peak, increase the difficulty of user operation, and reduce the number of requests. It can also prevent the robot from cracking and verifying.

For the access inventory, pay attention to the current limit, but not too long. Pay attention to the time interval. It allows users to read data at low frequency,

Read write separation, one master and many slaves, can effectively improve the access ability of read

Implementation of the seckill system
The essence of massive Concurrency: divide and conquer; Effectively squeeze CPU. The key to improve the performance of single service is to squeeze CPU performance. Reduce IO (network access)

Q, disk read / write), reduce CPU context switching, CPU context switching is invalid operation.

Single process and single thread, to ensure that the context will not be switched, but IO may block, asynchronous

Multi core CPU, single deployment of multiple instances (multiple single process, single thread), effective use of multi-core CPU.