How to Build a High‑Concurrency Flash‑Sale System with Spring Boot, Redis, and Lua

The article analyzes why flash‑sale systems often crash under extreme traffic and presents a step‑by‑step solution using Spring Boot, Redis, and Lua that prevents overselling, pre‑warms stock, applies token‑bucket rate limiting, executes atomic stock deductions, and decouples order creation asynchronously while adding monitoring and safety measures.

LuTiao Programming
LuTiao Programming
LuTiao Programming
How to Build a High‑Concurrency Flash‑Sale System with Spring Boot, Redis, and Lua

Why Flash‑Sale Systems Fail

During major promotions (e.g., Double 11, 618) inventory can disappear before the page loads, requests may produce negative stock, and traffic spikes can overwhelm the database, causing system collapse. The root cause is that traditional e‑commerce architectures cannot sustain instantaneous extreme concurrency.

Flash‑sale essentials: fast (millisecond response), accurate (no oversell), stable (survive any load).

Technical Stack Choice

Why Redis?

In‑memory access speed.

Native support for atomic operations.

Horizontal scalability.

Acts as the first gate before the database.

Why Lua?

Single Redis command atomicity does not guarantee multi‑step business atomicity.

Lua scripts can combine check + decrement + validation into an indivisible operation.

Role of Spring Boot

Quick integration of Redis and message queue.

AOP, annotations, and auto‑configuration reduce complexity.

Facilitates building a standardized, maintainable flash‑sale service.

Overall Architecture

The core flow consists of:

Pre‑heat stock data into Redis before the event.

Apply token‑bucket rate limiting to filter invalid requests.

Execute a Lua script that atomically decrements stock.

On success, asynchronously create the order.

On failure, return quickly without blocking threads.

Compensate failures and trigger monitoring alerts.

Key Implementations

Stock Pre‑heat Service

package com.icoderoad.seckill.stock;</code>
<code>@Service</code>
<code>public class StockPreheatService {</code>
<code>    @Autowired</code>
<code>    private RedisTemplate<String, Object> redisTemplate;</code>
<code>    @Autowired</code>
<code>    private ProductRepository productRepository;</code>
<code>    public void preheatStock(Long productId) {</code>
<code>        Product product = productRepository.findById(productId);</code>
<code>        redisTemplate.opsForValue().set("stock:" + productId, product.getStock(), Duration.ofHours(2));</code>
<code>        redisTemplate.opsForValue().set("product:" + productId, product, Duration.ofHours(2));</code>
<code>        redisTemplate.opsForValue().set("seckill:status:" + productId, "ready", Duration.ofHours(2));</code>
<code>    }</code>
<code>}
Core principle: the database does not participate in the main path before the flash‑sale starts.

Lua Script for Atomic Stock Deduction

package com.icoderoad.seckill.lua;</code>
<code>@Component</code>
<code>public class SeckillLuaScript {</code>
<code>    private static final String SCRIPT =</code>
<code>        "local stock = tonumber(redis.call('GET', KEYS[1]))
" +</code>
<code>        "if not stock or stock <= 0 then return 0 end
" +</code>
<code>        "redis.call('DECR', KEYS[1])
" +</code>
<code>        "return 1";</code>
<code>    @Autowired</code>
<code>    private RedisTemplate<String, Object> redisTemplate;</code>
<code>    public boolean execute(Long productId) {</code>
<code>        RedisScript<Long> script = new DefaultRedisScript<>(SCRIPT, Long.class);</code>
<code>        Long result = redisTemplate.execute(script, List.of("stock:" + productId));</code>
<code>        return result != null && result == 1;</code>
<code>    }</code>
<code>}

Benefits: atomicity, zero lock contention, stability under high concurrency.

Traffic Shaping (Token‑Bucket Rate Limiting)

package com.icoderoad.seckill.limit;</code>
<code>@Component</code>
<code>public class TrafficShapingService {</code>
<code>    private final Map<String, RateLimiter> limiterMap = new ConcurrentHashMap<>();</code>
<code>    public boolean allow(String key) {</code>
<code>        return limiterMap.computeIfAbsent(key, k -> RateLimiter.create(100)).tryAcquire();</code>
<code>    }</code>
<code>}
Rate limiting is not to reject users but to protect the system.

Flash‑Sale Core Service

package com.icoderoad.seckill.core;</code>
<code>@Service</code>
<code>public class SeckillService {</code>
<code>    @Autowired private TrafficShapingService trafficService;</code>
<code>    @Autowired private SeckillLuaScript luaScript;</code>
<code>    @Autowired private OrderProducer orderProducer;</code>
<code>    public SeckillResult seckill(Long productId, Long userId) {</code>
<code>        if (!trafficService.allow("seckill:" + productId)) {</code>
<code>            return SeckillResult.failure("系统繁忙");</code>
<code>        }</code>
<code>        if (!luaScript.execute(productId)) {</code>
<code>            return SeckillResult.failure("库存不足");</code>
<code>        }</code>
<code>        orderProducer.send(productId, userId);
<code>        return SeckillResult.success();</code>
<code>    }</code>
<code>}

Asynchronous Order Creation

package com.icoderoad.seckill.order;</code>
<code>@Component</code>
<code>public class OrderConsumer {</code>
<code>    @RabbitListener(queues = "seckill.order.queue")</code>
<code>    public void consume(OrderMessage msg) {</code>
<code>        // create order</code>
<code>    }</code>
<code>}

Advanced Enhancements

Stock sharding to reduce Redis hotspot.

User‑level rate limiting.

Pre‑sale plus deposit model.

Anti‑scraping, duplicate‑request, and script‑attack protection.

Dynamic multi‑stage rate limiting.

Circuit breaking and degradation.

Metrics monitoring and alerting.

Performance & Security Configuration Example

spring:</code>
<code>  redis:</code>
<code>    lettuce:</code>
<code>      pool:</code>
<code>        max-active: 200</code>
<code>        max-idle: 50</code>
<code>        min-idle: 10</code>
<code>        max-wait: 2000ms</code>
<code>      timeout: 1000ms
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.

RedisHigh concurrencySpring Bootrate limitingLuaFlash SaleAtomic Script
LuTiao Programming
Written by

LuTiao Programming

LuTiao Programming is a friendly community offering free programming lessons. We inspire learners to explore new ideas and technologies and quickly acquire job-ready skills.

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.