How to Build a High‑Performance Seckill System with SpringBoot, Redis, and RabbitMQ
This article details the design and implementation of a Java‑based flash‑sale (Seckill) system using SpringBoot, Redis, RabbitMQ, and related technologies, covering architecture, security, caching, asynchronous processing, oversell prevention, and rate‑limiting techniques.
Project Overview
This SeckillProject is a simplified flash‑sale system built with SpringBoot. It provides login, product list, product details, seckill, and order details, and demonstrates techniques such as asynchronous order processing, hotspot data caching, and oversell prevention.
Technology Stack
Backend: SpringBoot, MyBatis, MySQL, RabbitMQ, Redis
Frontend: HTML, jQuery, Thymeleaf
Implementation Details
1. Double MD5 password encryption
First MD5 protects the password in transit; the second MD5 protects stored passwords against database theft.
2. Distributed session with Redis
After successful login, a UUID token is stored in Redis as key and the user object as value, and the token is also placed in a cookie for session maintenance.
3. Unified exception handling
Custom interceptor and @ControllerAdvice + @ExceptionHandler capture all exceptions and return uniform responses.
4. Page and object caching
Rendered HTML pages are cached in Redis; hot objects such as user, product, and order are also cached to reduce database load.
5. Page staticization
Ajax loads data once; subsequent visits use browser cache.
6. Memory flag + Redis pre‑decrement + RabbitMQ async order
A local map marks sold‑out products, Redis pre‑decrements stock, and RabbitMQ queues the order for asynchronous processing, minimizing database hits.
private Map<Long, Boolean> localOverMap = new HashMap<>();
boolean over = localOverMap.get(goodsId);
if (over) {
return Result.error(CodeMsg.MIAO_SHA_OVER);
}
long stock = redisService.decr(GoodsKey.getSeckillGoodsStock, "" + goodsId);
if (stock < 0) {
localOverMap.put(goodsId, true);
return Result.error(CodeMsg.MIAO_SHA_OVER);
}
SeckillOrder order = orderService.getOrderByUserIdGoodsId(user.getId(), goodsId);
if (order != null) {
return Result.error(CodeMsg.REPEATE_MIAOSHA);
}
SeckillMessage sm = new SeckillMessage();
sm.setUser(user);
sm.setGoodsId(goodsId);
sender.sendSeckillMessage(sm);7. Preventing oversell
SQL updates only succeed when stock > 0; a unique index on (user_id, goods_id) prevents duplicate purchases; optimistic locking with a version field adds another safety layer.
8. Interface rate limiting
Custom @AccessLimit annotation limits the number of requests per user within a time window.
@AccessLimit(seconds=5, maxCount=5, needLogin=true)
@RequestMapping(value="/path", method=RequestMethod.GET)
@ResponseBody
public Result<String> getSeckillPath(User user, @RequestParam("goodsId") long goodsId) {
if (user == null) {
return Result.error(CodeMsg.USER_NO_LOGIN);
}
String path = seckillService.createPath(user, goodsId);
return Result.success(path);
}Demo Screenshots
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
