How to Implement High‑Performance Stock Deduction with Redis Lua and Spring Boot

This article compares three stock‑deduction strategies—single‑field MySQL, sharded MySQL rows, and Redis incrby with Lua scripts—analyzes their concurrency issues, and provides a complete Spring Boot implementation using a distributed lock, Lua script, and callback for initializing stock.

Java High-Performance Architecture
Java High-Performance Architecture
Java High-Performance Architecture
How to Implement High‑Performance Stock Deduction with Redis Lua and Spring Boot

In daily development, stock deduction appears in e‑commerce, lottery systems, and similar scenarios.

Solution

Use MySQL with a single field to store stock and update it on each deduction.

Store stock in multiple rows (sharding) to increase concurrency, but still heavy DB load.

Put stock in Redis and use Redis incrby to deduct.

Analysis

Both database‑based methods rely on data updates. The single‑field approach blocks all requests under high concurrency, causing timeouts and heavy DB load. The sharded approach improves concurrency slightly but still generates many DB updates.

Database deduction must be performed in a single statement to avoid over‑deduction, e.g.: update number set x=x-1 where x > 0 MySQL performance degrades sharply under high thread counts, and row‑level locking can cause deadlocks.

Redis based solution

Using Redis with Lua scripts avoids over‑deduction and improves performance. However, cache loss requires a recovery strategy, especially when initializing stock after asynchronous reward distribution.

Redis implementation details

Use a Redis Lua script to deduct stock.

Employ a distributed lock for initializing stock in a distributed environment.

Provide a callback to obtain initial stock.

Stock initialization callback (IStockCallback)

/**
 * Get stock callback
 * @author yuhao.wang
 */
public interface IStockCallback {
    /**
     * Get stock
     * @return
     */
    int getStock();
}

StockService

/**
 * Stock deduction service
 * @author yuhao.wang
 */
@Service
public class StockService {
    Logger logger = LoggerFactory.getLogger(StockService.class);
    public static final long UNINITIALIZED_STOCK = -3L;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    public static final String STOCK_LUA;
    static {
        StringBuilder sb = new StringBuilder();
        sb.append("if (redis.call('exists', KEYS[1]) == 1) then");
        sb.append("    local stock = tonumber(redis.call('get', KEYS[1]));");
        sb.append("    local num = tonumber(ARGV[1]);");
        sb.append("    if (stock == -1) then");
        sb.append("        return -1;");
        sb.append("    end;");
        sb.append("    if (stock >= num) then");
        sb.append("        return redis.call('incrby', KEYS[1], 0 - num);");
        sb.append("    end;");
        sb.append("    return -2;");
        sb.append("end;");
        sb.append("return -3;");
        STOCK_LUA = sb.toString();
    }
    // other methods omitted for brevity
}

Controller usage

@RestController
public class StockController {
    @Autowired
    private StockService stockService;
    @RequestMapping(value = "stock", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Object stock() {
        long commodityId = 1;
        String redisKey = "redis_key:stock:" + commodityId;
        long stock = stockService.stock(redisKey, 60 * 60, 2, () -> initStock(commodityId));
        return stock >= 0;
    }
    private int initStock(long commodityId) {
        return 1000; // initialize stock
    }
    // other endpoints omitted
}
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

redisSpring BootmysqlLua Scriptstock deduction
Java High-Performance Architecture
Written by

Java High-Performance Architecture

Sharing Java development articles and resources, including SSM architecture and the Spring ecosystem (Spring Boot, Spring Cloud, MyBatis, Dubbo, Docker), Zookeeper, Redis, architecture design, microservices, message queues, Git, etc.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.