The flash sales strategy is commonly used for promotional events and brand marketing in the e-commerce industry. This strategy can help you increase the number of unique visitors and customer loyalty to your platform. An excellent business system can improve the stability of your platform and ensure the fairness of flash sales. This improves user experience and the reputation of your platform and maximizes the benefits of flash sales. This topic describes how to use the caching feature of ApsaraDB for Redis to build a highly concurrent business system for handling flash sales.

Characteristics of flash sales

A flash sales activity is used to sell scarce or special commodities for specified quantities in a limited period of time. This attracts a large number of buyers. However, only a few buyers can place orders during the promotional event. A flash sales activity increases the number of unique visitors and order requests by dozens or hundreds of times that in regular sales activities on your platform within a short period of time.

A flash sales activity is divided into three phases:

  • Before the promotional event: Buyers continuously refresh the commodity details page. As a result, the number of requests for this page spikes.
  • During the promotional event: Buyers place orders. The number of order requests reaches a peak.
  • After the promotional event: Specific buyers that have placed orders continue to query the status of orders or cancel orders. Most buyers continue to refresh the commodity details page and wait for opportunities to place orders after other buyers cancel their orders.

In most cases, a database uses row-level locking to handle requests submitted by buyers. The database allows only the requests that hold the lock to query inventory data and place orders. However, in these cases, the database cannot handle high concurrency. This may cause services to be blocked by a large number of requests and cause the server to stop responding to the buyers.

Business system for handling flash sales

During a flash sales activity, the business system may receive a large amount of user traffic. However, only a few of the requests are valid. You can identify and block invalid requests in each phase in advance by using the hierarchy of the system architecture.

Use the browser cache and Content Delivery Network (CDN) to process user traffic that requests static content

Before a flash sales activity, buyers continue to refresh the commodity details page. As a result, the number of requests for this page spikes. To resolve this issue, you must present details of commodities for flash sales and details of regular commodities on different web pages. Use static elements to present details of commodities for flash sales. Static data is cached in the browser and on CDN nodes, except for the place-order feature that requires interaction between the browser and server. This way, only a small fraction of the traffic that is caused by page refreshes before the promotion is redirected to the server.

Use a read/write splitting instance of ApsaraDB for Redis to cache content and block invalid requests

CDN is used to filter and block user traffic in Phase 1. In Phase 2, you can use a read/write splitting instance of ApsaraDB for Redis to block invalid requests. In Phase 2, the business system retrieves data. The read/write splitting instance can handle more than 600,000 queries per second (QPS), which can meet the business demands.

Use the data control module to cache the data of commodities for flash sales to the read/write splitting instance, and specify the tag that indicates whether the flash sales activity begins:

"goodsId_count": 100 // The total number of commodities.
"goodsId_start": 0 // The tag that indicates whether the flash sales activity begins.
"goodsId_access": 0 // The number of order requests that are accepted.
  1. Before the flash sales activity begins, the value of the goodsId_start parameter retrieved by the server cluster is 0. A value of 0 indicates that the flash sales activity has not begun.
  2. After the data control module changes the value of the goodsId_start parameter to 1, the flash sales activity begins.
  3. Then, the server cluster caches the goodsId_start tag and accepts order requests. The cluster updates the number of accepted order requests in goodsId_access. The number of remaining commodities is calculated in the following method: goodsId_count - goodsId_access.
  4. After the number of placed orders reaches the value of goodsId_count, the business system blocks subsequent order requests. The number of remaining commodities is set to 0.

As a result, the business system accepts only a small fraction of the order requests. For high concurrency scenarios, a large amount of traffic is directed to the system. In this case, you can control the percentage of order requests that the system accepts.

Use a master-replica instance of ApsaraDB for Redis to cache inventory data and speed up the removal of the item from the inventory

After the business system receives an order request, the system checks the order information and removes the item from the inventory. To prevent retrieving data directly from the backend database, you can use a master-replica instance of ApsaraDB for Redis to remove the item from the inventory. The master-replica instance supports more than 100,000 QPS. ApsaraDB for Redis can help you optimize inventory queries, block invalid order requests, and increase the overall throughput of the business system to handle flash sales.

You can use the data control module to cache the inventory data to the ApsaraDB for Redis instance in advance. The instance stores the commodity data for promotion in a hash table.

"goodsId" : {
    "Total": 100
    "Booked": 0
}
Note The goodsId field indicates the commodity ID. The Total field indicates the number of the commodities in the inventory. The Booked field indicates the number of ordered commodities.

To remove the item from the inventory, the flash sales promotion server runs the following Lua script and connects to the ApsaraDB for Redis instance to obtain the order permission. The Lua script ensures the atomicity of multiple commands based on the Redis single-thread model.

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

Run the SCRIPT LOAD command to cache the Lua script to the ApsaraDB for Redis instance in advance. Then, run the EVALSHA command to execute the script. This method requires less network bandwidth than directly running the EVAL command.

  1. Cache the Lua script to the ApsaraDB for Redis instance.
    SCRIPT LOAD "lua code"
    The following result is returned:
    "438dd755f3fe0d32771753eb57f075b18fed7716"
  2. Run the Lua script.
    EVALSHA 438dd755f3fe0d32771753eb57f075b18fed7716 1 goodsId 1 
    The following result is returned. The result indicates that an item is removed from the inventory.
    (integer) 1
    Note In this case, if you run the HGET goodsId Booked command, the return value is "1". The return value indicates that a commodity is ordered.

If the ApsaraDB for Redis instance returns the value n as the number of commodities that buyers ordered, the items are successfully removed from the inventory.

Use a master-replica instance of ApsaraDB for Redis to asynchronously write order data to the database based on message queues

After the items are removed from the inventory, the flash sales business system writes order data to the database. The system can directly perform operations in the database for a few commodities. If the number of commodities for promotion is more than 10,000 or 100,000, lock conflicts may occur and can cause performance bottlenecks in the database. Therefore, to prevent directly writing data to the database, the flash sales system writes order data to message queues. Orders that are written to message queues are considered successfully placed orders.

  1. The ApsaraDB for Redis instance provides message queues in a list structure.
     orderList {
         [0] = {Order content} 
         [1] = {Order content}
         [2] = {Order content}
         ...
     }
  2. The flash sales business system writes order content to the ApsaraDB for Redis instance.
    LPUSH orderList {Order content}
  3. The asynchronous order module sequentially retrieves order data from the ApsaraDB for Redis instance and writes order data to the database.
     BRPOP orderList 0

The ApsaraDB for Redis instance provides message queues and asynchronously writes order data to the database to speed up the order process.

Use the data control module to manage the synchronization of promotion data

At the start of the promotion, the flash sales business system uses the read/write splitting instance of ApsaraDB for Redis to block invalid traffic and allows a fraction of valid traffic to continue the order process. After the promotion, the flash sales business system must process more traffic caused by order authentication failures and refund requests. Therefore, the data control module regularly computes data in the database, and synchronizes the data to the master-replica instance and then to the read/write splitting instance.