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 161 162 163
|
@Service public class OptimizedDistributedLockService { @Autowired private RedisTemplate<String, String> redisTemplate;
public boolean tryLockWithRetry(String lockKey, String lockValue, Duration lockTime, Duration maxWaitTime) { long startTime = System.currentTimeMillis(); long maxWaitMillis = maxWaitTime.toMillis(); while (System.currentTimeMillis() - startTime < maxWaitMillis) { Boolean acquired = redisTemplate.opsForValue() .setIfAbsent(lockKey, lockValue, lockTime); if (Boolean.TRUE.equals(acquired)) { return true; } try { long waitTime = Math.min(100, (System.currentTimeMillis() - startTime) / 10); Thread.sleep(waitTime); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return false; } } return false; }
public boolean releaseLock(String lockKey, String lockValue) { String luaScript = """ if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end """; Long result = redisTemplate.execute( new DefaultRedisScript<>(luaScript, Long.class), Collections.singletonList(lockKey), lockValue ); return result != null && result == 1; }
public boolean renewLock(String lockKey, String lockValue, Duration renewTime) { String luaScript = """ if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('expire', KEYS[1], ARGV[2]) else return 0 end """; Long result = redisTemplate.execute( new DefaultRedisScript<>(luaScript, Long.class), Collections.singletonList(lockKey), lockValue, String.valueOf(renewTime.getSeconds()) ); return result != null && result == 1; } }
@Service public class OptimizedInventoryService { @Autowired private OptimizedDistributedLockService lockService;
public boolean updateInventory(Long productId, int quantity) { String lockKey = "lock:inventory:" + productId; String lockValue = UUID.randomUUID().toString(); boolean lockAcquired = lockService.tryLockWithRetry( lockKey, lockValue, Duration.ofSeconds(5), Duration.ofSeconds(3) ); if (!lockAcquired) { log.warn("获取库存锁超时: {}", productId); return false; } try { boolean result = doInventoryUpdate(productId, quantity); if (result) { CompletableFuture.runAsync(() -> recordInventoryChangeAsync(productId, quantity)); } return result; } finally { lockService.releaseLock(lockKey, lockValue); } }
private boolean doInventoryUpdate(Long productId, int quantity) { try { Inventory inventory = inventoryMapper.selectByProductId(productId); if (inventory.getStock() < quantity) { return false; } inventory.setStock(inventory.getStock() - quantity); int updated = inventoryMapper.updateInventory(inventory); return updated > 0; } catch (Exception e) { log.error("库存更新失败: productId={}", productId, e); return false; } }
@Async("inventoryTaskExecutor") public void recordInventoryChangeAsync(Long productId, int quantity) { try { inventoryChangeLogService.record(productId, quantity); } catch (Exception e) { log.error("记录库存变动失败: productId={}", productId, e); } } }
|