Have help please point a concern, support about writing ~

Seckill activity is the way most e-commerce companies choose to promote their brands at low prices. It can not only bring users to the platform, but also improve the visibility of the platform. A good seckill system can improve the stability and fairness of the platform system, obtain better user experience, enhance the reputation of the platform, and thus enhance the maximum value of seckill activities.

The characteristics of a second kill

Seckill activities sell scarce or special goods at a fixed time and at a fixed quantity, attracting a large number of consumers to snap up, but only a small number of consumers can place orders successfully. Therefore, seckill activities will generate tens of times and hundreds of times more page traffic and single request traffic than usual in a short period of time.

Seckill activities can be divided into three stages:

  • Before the second kill: the user continuously refreshes the product details page, and the page request reaches the instantaneous peak.
  • Seckill start: the user clicks the seckill button, and the single request reaches the instantaneous peak value.
  • After the second kill: some users who placed a successful order continuously refresh the order or return the order, while most users continue to refresh the product details page and wait for the return opportunity.

Consumers submit orders, the general practice is to use the database row-level lock, only grab the lock request can be inventory query and order operations. However, in the case of high concurrency, the database cannot handle such a large request, and the entire service is often blocked, which means the server goes down in the eyes of consumers.

Second kill system

The traffic of seckill system is very high, but the actual effective traffic is very limited. Using the hierarchical structure of the system, checking in advance at each stage and intercepting invalid traffic can reduce the amount of invalid traffic flooding into the database.

2.1 Use browser cache and CDN to resist static page traffic

Before the seconds kill, users constantly refresh the product details page, resulting in a large number of page requests. Therefore, we need to separate the kill product details page from the regular product details page. As far as possible, the static elements of the seconds kill product details page will be processed statically. Except for the seconds kill button, the server needs to make dynamic judgment, and other static data can be cached in the browser and CDN. In this way, only a small fraction of the traffic to the server resulting from page refreshes before seckilling.

2.2 Redis cache intercepts traffic using read/write separation

CDN is the first level of traffic interception. For the second level of traffic interception, we use Redis which supports read/write separation. In this stage, we mainly read data. Redis can support more than 600,000 QPS, which can fully support the demand.

First, through the data control module, the second kill product is cached to Redis in advance, and the second kill start mark is set as follows:

"goodsId_count": 100 / / the total number of
"goodsId_start": 0   // Start the tag
"goodsId_access": 0  // Accept singular
Copy the code
  1. Before the slaughtering starts, the service cluster reads goodsId_Start as 0 and returns that the slaughtering does not start.
  2. The data control module changes goodsId_start to 1, indicating the start of seckilling.
  3. The service cluster caches the start flag bit and starts accepting requests, and records the goodsId_access in Redis with (goodsId_count – goodsId_access).
  4. After goodsId_count is reached, all requests continue to be intercepted, and the number of goods left is 0.

Question & Thinking

Question: In the read-write separation architecture, I understand that the update status is a write request from Redis, which will be forwarded to the master node. The slave node is supposed to host the inventory query, but the inventory state is synchronized by the master. There is a delay in the inventory state, which seems to be difficult to handle the instantaneous second kill scenario.

Answer: I can see from the back that this step will exceed some traffic, but the main purpose is to intercept traffic that fails to kill. For example, in this step, the second kill traffic is 2000w, only 5 million shipments, due to the read-write separation architecture master/slave synchronous inventory state is delayed, maybe 8 million traffic to the next phase, another 12 million traffic is blocked. Although the flow of 8 million exceeds the inventory of 5 million, it does not mean that the order is successfully placed. In the next stage, redis master-slave architecture is used to ensure the consistency of the inventory data by reading and writing from the master node. Finally, only 5 million flows pass the inventory verification and enter the order warehousing process of the next stage. The other 3 million traffic will be returned with a seconds kill failure.

It can be seen that only a small part of the successful participation in the final order can be accepted. In the case of high concurrency, slightly more traffic is allowed in. Therefore, it is possible to control the proportion of singular numbers accepted.

2.3 Use Redis cache of master and slave versions to accelerate inventory deduction

After successfully placing an order, enter the lower level service, start to check the order information and deduct the inventory. To avoid direct access to the database, we use master/slave Redis for inventory deduction. Master/slave Redis provides QPS of 100,000 level. Using Redis to optimize inventory queries and intercept failed seckill requests in advance will greatly improve the overall throughput of the system. Through the data control module, the inventory is stored in Redis in advance, and each second kill product is represented in Redis with a hash structure.

"goodsId" : {
    "Total": 100
    "Booked": 100
}
Copy the code

The server requests Redis to obtain the order qualification through the following Lua script. Because Redis is a single-threaded model, Lua can ensure the atomicity of multiple commands.

local n = tonumber(ARGV[1])
if not n  or n == 0 then
    return 0       
end                
local vals = redis.call("HMGET", KEYS[1]."Total"."Booked");
local total = tonumber(vals[1])
local blocked = tonumber(vals[2])
if not total or not blocked then
    return 0       
end                
if blocked + n <= total then
    redis.call("HINCRBY", KEYS[1]."Booked", n)                                   
    return n;   
end                
return 0
Copy the code

Use SCRIPT LOAD to cache the lua SCRIPT in Redis, and then call EVALSHA to call the SCRIPT. This saves network bandwidth compared to EVAL directly.

//1. Cache lua scripts to Redis. SCRIPT LOAD "lua code" / / return the result as follows: "438 dd755f3fe0d32771753eb57f075b18fed7716" / / 2. Call the Lua script. EVALSHA 438dd755f3fe0d32771753eb57f075b18fed7716 1 goodsId 1Copy the code

The second kill service can know whether the request is successful by judging whether Redis returns the number n.

2.4 Use the master and slave Redis to realize the simple message queue asynchronous ordering and warehousing

After the amount of deduction is completed, the order shall be put into storage. If the number of goods is small, direct operation of the database can be. Database lock conflicts can be a significant performance bottleneck if the second kill item is 10,000 or even 100,000. Therefore, with the message queue component, when the seckill service writes the order information to the message queue, the order can be considered complete, avoiding direct operation of the database.

1. Message queue components can still be implemented using Redis, represented by the List data structure in R2.

 orderList {
     [0] = {order content} [1] = {order content} [2] = {order content}... }Copy the code

2. Write the order content into Redis:

LPUSH orderList {order contents}Copy the code

3. The asynchronous ordering module obtains order information sequentially from Redis and writes the order to the database.

 BRPOP orderList 0
Copy the code

By using Redis as a message queue, order entry is processed asynchronously, which effectively improves the order completion speed of users.

2.5 summarize

Initially, Redis was used to limit traffic, allowing only part of the traffic to enter the order. More traffic needs to be brought in for failed inspections and refunded orders. Therefore, the data control module needs to regularly calculate the data in the database, synchronize it to the master and slave version Redis, and then synchronize it to the read-write separation Redis to let more traffic in.

Have help please point a concern, support about writing ~