java如何减少库存
减少库存的常见方法
在Java中减少库存通常涉及数据库操作和并发控制,以下是几种常见的方法:
使用数据库事务
确保库存更新操作在事务中执行,避免部分操作失败导致数据不一致。例如使用Spring的@Transactional注解:
@Transactional
public void reduceStock(Long productId, int quantity) {
Product product = productRepository.findById(productId);
if (product.getStock() >= quantity) {
product.setStock(product.getStock() - quantity);
productRepository.save(product);
} else {
throw new RuntimeException("库存不足");
}
}
乐观锁控制并发 在库存表中添加版本号字段,更新时检查版本号是否变化:
@Transactional
public void reduceStockWithOptimisticLock(Long productId, int quantity) {
Product product = productRepository.findById(productId);
if (product.getStock() >= quantity) {
int affectedRows = productRepository.reduceStock(productId, quantity, product.getVersion());
if (affectedRows == 0) {
throw new RuntimeException("并发更新失败");
}
} else {
throw new RuntimeException("库存不足");
}
}
悲观锁控制并发 在查询时加锁,防止其他事务同时修改:
@Transactional
public void reduceStockWithPessimisticLock(Long productId, int quantity) {
Product product = productRepository.findByIdWithLock(productId);
if (product.getStock() >= quantity) {
product.setStock(product.getStock() - quantity);
productRepository.save(product);
} else {
throw new RuntimeException("库存不足");
}
}
使用Redis分布式锁 在高并发场景下,可以使用Redis实现分布式锁:
public void reduceStockWithDistributedLock(Long productId, int quantity) {
String lockKey = "product_" + productId;
try {
boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 10, TimeUnit.SECONDS);
if (!locked) {
throw new RuntimeException("获取锁失败");
}
reduceStock(productId, quantity);
} finally {
redisTemplate.delete(lockKey);
}
}
消息队列异步处理 将减库存请求放入消息队列,异步处理避免瞬时高并发:

public void asyncReduceStock(Long productId, int quantity) {
Map<String, Object> message = new HashMap<>();
message.put("productId", productId);
message.put("quantity", quantity);
rabbitTemplate.convertAndSend("stock.reduce.queue", message);
}
注意事项
确保在减库存前检查库存数量,避免出现负库存 高并发场景下优先考虑分布式锁或消息队列方案 对于秒杀等极端场景,可以考虑预减库存或缓存库存方案 记录库存变更日志,便于核对和恢复 根据业务需求选择合适的方案,平衡性能和数据一致性






