景区抢票系统

/ 2025-11-29

操作在数据库,使用MQ异步落库
@Autowired
private TicketService ticketService;
@PostMapping(“/grab”)
public ResponseEntity grabTicket(
@RequestParam Long scenicId,
@RequestParam Long userId) {
boolean success = ticketService.grab(scenicId, userId);
return success ?
ResponseEntity.ok(“抢票成功”) :
ResponseEntity.badRequest().body(“抢票失败”);
}










@Service
public class TicketService {
@Autowired
private StringRedisTemplate redisTemplate;


// @Autowired
// private RocketMQTemplate rocketMQTemplate;
private static final DefaultRedisScript SCRIPT;

static {
SCRIPT = new DefaultRedisScript<>();
SCRIPT.setResultType(Long.class);
SCRIPT.setScriptText(
“if redis.call(‘SISMEMBER’, KEYS[2], ARGV[1]) == 1 then return -1 end “ +
“local stock = tonumber(redis.call(‘GET’, KEYS[1])) “ +
“if stock <= 0 then return 0 end “ +
“redis.call(‘DECR’, KEYS[1]) “ +
“redis.call(‘SADD’, KEYS[2], ARGV[1]) “ +
“return 1”
);
}










public boolean grab(Long scenicId, Long userId) {
// 抢票前先预热库存
//redisTemplate.opsForValue().set(“ticket:stock:” + scenicId, “100”);
//redisTemplate.delete(“ticket:user:” + scenicId);


  1. String stockKey = "ticket:stock:" + scenicId;
  2. String userKey = "ticket:user:" + scenicId;
  3. Long result = redisTemplate.execute(
  4. SCRIPT,
  5. Arrays.asList(stockKey, userKey),
  6. userId.toString()
  7. );
  8. if (result == null || result != 1) {
  9. return false;
  10. }
  11. // 异步下单

// rocketMQTemplate.convertAndSend(
// “ticket-order-topic”,
// new TicketOrderMsg(scenicId, userId)
// );
return true;
}




}


转载请注明作者和出处,并添加本页链接。
原文链接: //pongpongkai.top/150

皖ICP备2025092356号-1 | 沪公网安备31011202021249号