DCS Redis Help Documentation

Inventory Control for Flash Sales

2024-05-25 01:35:32

Scenario

Selling a certain package or product, and the total quantity of items to be sold needs to be set. Oversold must not occur, that is, the remaining quantity of items sold cannot be below zero.

The process can be divided into the following steps:

1. User requests: When users place orders, the requests enter the load balancing server.

2. Load balancing: The load balancing server distributes requests to multiple backend servers based on certain algorithms.

3. Service processing logic: Backend servers receive requests and verify the requested quantity and user identity.

4. Inventory deduction: If the inventory is robust, the backend server deducts stocks, generates an order, and returns a success message to the user. If the inventory is insufficient, the backend server returns a failure message.

5. Order processing: Backend servers save the order information to the database and perform asynchronous processing such as notifying users of the order status.

6. Cache update: Backend servers update the inventory information in the cache for the next flash sale request.

The database is accessed multiple times during the flash sale process. Row-level locking is usually used to restrict access. The database can be accessed and an order can be placed only after a lock is obtained. However, the database is often blocked by the sheer number of order requests.

Business Requirements

The system has high concurrency, and the snap-up ratio for extremely popular packages is only 1%. For example, 100 items can be sold out in a few seconds. The front end must calculate the remaining inventory quickly to respond to over 100,000 requests.

Products cannot be oversold.

Ensure inventory consistency among multiple dealers.

Analysis

Obtaining the remaining quantity of the product for condition determination and updating the data are two separate operations. There can be conflicts with other applications that modify the data. When a conflict occurs, the user needs to merge the latest data and then perform condition determination and data modification. Encapsulate the two separate operations into an atomic service to ensure that the result (remaining quantity - sales quantity) is not a negative number.

Example Solution: Implementing with Lua Script

Since Redis is single-threaded, no lock is required to modify data. Calling a Lua script can be regarded as an atomic operation and can be executed and calculated efficiently. Example:

 

local n = tonumber(ARGV[1])

if not n  or n == 0 then

    return 0

end

local vals = redis.call(\"HMGET\", KEYS[1], \"total\", \"booked\", \"remain\");

local booked = tonumber(vals[2])

local remain = tonumber(vals[3])

if booked <= remain then

    redis.call(\"HINCRBY\", KEYS[1], \"booked\", n)

    redis.call(\"HINCRBY\", KEYS[1], \"remain\", -n)

    return n;

end

return 0



.eGxpzXRWnVx