1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
@Service public class StockService { private final RedisTemplate<String, Object> redisTemplate; private final SeckillProperties properties; private final RedissonClient redissonClient; public StockService(SeckillProperties properties) { this.properties = properties; this.redisTemplate = new RedisTemplate<>(); this.redissonClient = null; }
public boolean preReduceStock(Long activityId, Long userId) { String lockKey = "stock_lock:" + activityId; RLock lock = redissonClient.getLock(lockKey); try { if (lock.tryLock(3, TimeUnit.SECONDS)) { try { String stockKey = properties.getStockPrefix() + ":" + activityId; String stockStr = (String) redisTemplate.opsForValue().get(stockKey); int stock = stockStr != null ? Integer.parseInt(stockStr) : 0; if (stock <= 0) { return false; } redisTemplate.opsForValue().decrement(stockKey); String userStockKey = "user_stock:" + activityId + ":" + userId; redisTemplate.opsForValue().set(userStockKey, "1", Duration.ofSeconds(properties.getPreReduceTimeout())); log.info("预扣库存成功: activityId={}, userId={}, remainingStock={}", activityId, userId, stock - 1); return true; } finally { lock.unlock(); } } else { log.warn("获取库存锁失败: activityId={}, userId={}", activityId, userId); return false; } } catch (Exception e) { log.error("预扣库存失败: activityId={}, userId={}", activityId, userId, e); return false; } }
public boolean confirmReduceStock(Long activityId, Long userId) { String userStockKey = "user_stock:" + activityId + ":" + userId; try { String userStock = (String) redisTemplate.opsForValue().get(userStockKey); if (userStock == null) { return false; } redisTemplate.delete(userStockKey); log.info("确认扣减库存成功: activityId={}, userId={}", activityId, userId); return true; } catch (Exception e) { log.error("确认扣减库存失败: activityId={}, userId={}", activityId, userId, e); return false; } }
public boolean rollbackStock(Long activityId, Long userId) { if (!properties.isEnableStockRollback()) { return true; } String lockKey = "stock_lock:" + activityId; RLock lock = redissonClient.getLock(lockKey); try { if (lock.tryLock(3, TimeUnit.SECONDS)) { try { String stockKey = properties.getStockPrefix() + ":" + activityId; String userStockKey = "user_stock:" + activityId + ":" + userId; String userStock = (String) redisTemplate.opsForValue().get(userStockKey); if (userStock != null) { redisTemplate.opsForValue().increment(stockKey); redisTemplate.delete(userStockKey); log.info("回滚库存成功: activityId={}, userId={}", activityId, userId); } return true; } finally { lock.unlock(); } } else { log.warn("获取库存锁失败: activityId={}, userId={}", activityId, userId); return false; } } catch (Exception e) { log.error("回滚库存失败: activityId={}, userId={}", activityId, userId, e); return false; } }
public int getStock(Long activityId) { try { String stockKey = properties.getStockPrefix() + ":" + activityId; String stockStr = (String) redisTemplate.opsForValue().get(stockKey); return stockStr != null ? Integer.parseInt(stockStr) : 0; } catch (Exception e) { log.error("获取库存失败: activityId={}", activityId, e); return 0; } } }
|