电商防止超卖终极方案:让库存管理滴水不漏![特殊字符]

标题:超卖?不存在的!五大方案让你高枕无忧
副标题:从数据库锁到Redis原子操作,防超卖全攻略


🎬 开篇:一个惨痛的案例

makefile

体验AI代码助手

代码解读

复制代码

双11零点,某电商平台: 00:00:00 - 秒杀活动开始! 商品库存:100件 00:00:05 - 系统显示:已售罄! 数据库库存:-23件 💀 实际订单:123个 00:01:00 - 客服电话被打爆: 客户A:我买到了,为什么取消我订单?😠 客户B:明明还有库存,为什么买不了?😤 损失: - 赔偿金:10万+ - 用户流失:1000+ - 品牌损失:无法估量 CEO:这个锅,谁来背?💀

🤔 超卖问题的本质

想象10个人同时抢1件商品:

  • 没有库存控制:10个人都看到"有货",都下单成功(超卖9件!)
  • 有库存控制:只有1个人抢到,其他9个人提示"已售罄"(完美!)

核心问题:并发场景下的库存扣减不是原子操作!


📚 知识地图

体验AI代码助手

代码解读

复制代码

防止超卖的五大方案 ├── 🔐 方案1:悲观锁(数据库锁) ├── 🎯 方案2:乐观锁(版本号) ├── ⚡ 方案3:Redis原子操作(推荐!) ├── 📦 方案4:消息队列削峰 └── 🎪 方案5:分布式锁+预扣库存


🔐 方案1:悲观锁 - "数据库行锁"

🌰 生活中的例子

银行取款机:

  • 没有锁:两个人同时取钱,余额可能出错
  • 有锁:第一个人操作时,第二个人只能等待

💻 技术实现

实现1:SELECT ... FOR UPDATE

java

体验AI代码助手

代码解读

复制代码

/** * 悲观锁方案:使用SELECT FOR UPDATE */ @Service public class PessimisticLockStockService { @Autowired private ProductMapper productMapper; @Autowired private OrderService orderService; /** * 购买商品(悲观锁) */ @Transactional(rollbackFor = Exception.class) public boolean buyProduct(Long productId, Integer quantity) { // 1. 🔒 查询并锁定商品(行锁) Product product = productMapper.selectForUpdate(productId); // 2. 检查库存 if (product.getStock() < quantity) { log.warn("库存不足:商品ID={}, 剩余库存={}, 购买数量={}", productId, product.getStock(), quantity); return false; } // 3. 扣减库存 int updated = productMapper.updateStock(productId, quantity); if (updated == 0) { log.error("扣减库存失败:商品ID={}", productId); return false; } // 4. 创建订单 orderService.createOrder(productId, quantity); log.info("购买成功:商品ID={}, 数量={}", productId, quantity); return true; } } /** * MyBatis Mapper */ @Mapper public interface ProductMapper { /** * 查询并锁定(关键!) */ @Select("SELECT * FROM product WHERE id = #{id} FOR UPDATE") Product selectForUpdate(@Param("id") Long id); /** * 扣减库存 */ @Update("UPDATE product SET stock = stock - #{quantity} " + "WHERE id = #{id}") int updateStock(@Param("id") Long id, @Param("quantity") Integer quantity); } /** * 原理说明: * * SELECT ... FOR UPDATE 会对查询到的行加排他锁(X锁) * * 事务A:SELECT ... FOR UPDATE ✅ 获取锁 * 事务B:SELECT ... FOR UPDATE ⏳ 等待... * 事务C:SELECT ... FOR UPDATE ⏳ 等待... * * 事务A:扣减库存 -> COMMIT 🔓 释放锁 * 事务B: ✅ 获取锁 * 事务C: ⏳ 等待... * * 优点: * ✅ 强一致性,绝不超卖 * ✅ 实现简单 * * 缺点: * ❌ 性能差(串行执行) * ❌ 容易死锁 * ❌ 不适合高并发场景 */

实现2:UPDATE直接加锁

java

体验AI代码助手

代码解读

复制代码

/** * 更简洁的悲观锁方案 */ @Service public class SimplePessimisticLockService { @Autowired private ProductMapper productMapper; @Transactional(rollbackFor = Exception.class) public boolean buyProduct(Long productId, Integer quantity) { // ⚡ 直接扣减库存(MySQL会自动加行锁) int updated = productMapper.decreaseStock(productId, quantity); if (updated == 0) { log.warn("扣减库存失败,可能库存不足"); return false; } // 创建订单 orderService.createOrder(productId, quantity); return true; } } @Mapper public interface ProductMapper { /** * 扣减库存(带库存检查) */ @Update("UPDATE product " + "SET stock = stock - #{quantity} " + "WHERE id = #{id} " + "AND stock >= #{quantity}") // ⚡ 关键:检查库存是否足够 int decreaseStock(@Param("id") Long id, @Param("quantity") Integer quantity); } /** * SQL执行流程: * * UPDATE product * SET stock = stock - 10 * WHERE id = 1 * AND stock >= 10 -- 如果不满足,updated = 0 * * 这个SQL会: * 1. 自动对id=1的行加X锁 * 2. 检查库存是否>=10 * 3. 如果满足,扣减库存;否则不更新 * 4. 返回影响行数(0或1) * * 完美解决超卖问题!✅ */

性能测试

java

体验AI代码助手

代码解读

复制代码

/** * 悲观锁性能测试 */ public class PessimisticLockTest { public static void main(String[] args) throws Exception { // 初始库存:100件 // 并发数:100个线程 // 每个线程购买:1件 int concurrency = 100; CountDownLatch latch = new CountDownLatch(concurrency); for (int i = 0; i < concurrency; i++) { new Thread(() -> { try { stockService.buyProduct(1L, 1); } finally { latch.countDown(); } }).start(); } latch.await(); /** * 测试结果: * - 最终库存:0件 ✅ 正确 * - 成功订单:100个 ✅ 正确 * - 平均耗时:1500ms 💀 太慢了! * - TPS:67 💀 低! */ } }


🎯 方案2:乐观锁 - "版本号机制"

🌰 生活中的例子

编辑Word文档:

  • 悲观锁:我编辑时,锁定文档,你不能看
  • 乐观锁:我们都可以编辑,提交时检查版本,冲突了就重试

💻 技术实现

sql

体验AI代码助手

代码解读

复制代码

-- 数据库表结构 CREATE TABLE product ( id BIGINT PRIMARY KEY, name VARCHAR(100), stock INT, version INT DEFAULT 0, -- ⚡ 版本号字段(关键!) INDEX idx_version (version) );

java

体验AI代码助手

代码解读

复制代码

/** * 乐观锁方案:使用版本号 */ @Service public class OptimisticLockStockService { @Autowired private ProductMapper productMapper; /** * 购买商品(乐观锁 + 重试) */ public boolean buyProduct(Long productId, Integer quantity) { int maxRetry = 3; // 最多重试3次 for (int i = 0; i < maxRetry; i++) { try { // 1. 查询商品(不加锁!) Product product = productMapper.selectById(productId); // 2. 检查库存 if (product.getStock() < quantity) { log.warn("库存不足"); return false; } // 3. ⚡ 乐观锁扣减库存(基于版本号) int updated = productMapper.decreaseStockWithVersion( productId, quantity, product.getVersion() // 传入旧版本号 ); if (updated == 0) { // 版本号不匹配,说明被其他线程修改了,重试! log.warn("版本冲突,重试第{}次", i + 1); Thread.sleep(10); // 短暂休眠后重试 continue; } // 4. 创建订单 orderService.createOrder(productId, quantity); log.info("购买成功:商品ID={}, 数量={}", productId, quantity); return true; } catch (Exception e) { log.error("购买失败", e); if (i == maxRetry - 1) { return false; } } } log.error("重试{}次后仍然失败", maxRetry); return false; } } @Mapper public interface ProductMapper { /** * 基于版本号扣减库存(乐观锁) */ @Update("UPDATE product " + "SET stock = stock - #{quantity}, " + " version = version + 1 " + // 版本号+1 "WHERE id = #{id} " + "AND stock >= #{quantity} " + "AND version = #{version}") // ⚡ 检查版本号(关键!) int decreaseStockWithVersion(@Param("id") Long id, @Param("quantity") Integer quantity, @Param("version") Integer version); } /** * 原理说明: * * 初始状态:stock=10, version=0 * * 线程A查询:stock=10, version=0 * 线程B查询:stock=10, version=0 * * 线程A更新:UPDATE ... WHERE version=0 ✅ 成功,version变为1 * 线程B更新:UPDATE ... WHERE version=0 ❌ 失败,version已经是1了! * * 线程B重试: * - 重新查询:stock=9, version=1 * - 再次更新:UPDATE ... WHERE version=1 ✅ 成功 * * 优点: * ✅ 性能比悲观锁好 * ✅ 不会死锁 * ✅ 并发度高 * * 缺点: * ⚠️ 高并发下重试次数多 * ⚠️ 可能导致活锁 * ⚠️ 需要业务层重试逻辑 */

改进版:ABA问题处理

java

体验AI代码助手

代码解读

复制代码

/** * 使用时间戳替代版本号(防止ABA问题) */ @Service public class TimestampOptimisticLockService { @Transactional(rollbackFor = Exception.class) public boolean buyProduct(Long productId, Integer quantity) { // 1. 查询商品 Product product = productMapper.selectById(productId); // 2. 检查库存 if (product.getStock() < quantity) { return false; } // 3. ⚡ 使用update_time作为乐观锁 int updated = productMapper.decreaseStockWithTimestamp( productId, quantity, product.getUpdateTime() // 传入旧的更新时间 ); if (updated == 0) { throw new OptimisticLockException("库存更新冲突"); } // 4. 创建订单 orderService.createOrder(productId, quantity); return true; } } @Mapper public interface ProductMapper { /** * 基于时间戳的乐观锁 */ @Update("UPDATE product " + "SET stock = stock - #{quantity}, " + " update_time = NOW() " + // 更新时间戳 "WHERE id = #{id} " + "AND stock >= #{quantity} " + "AND update_time = #{oldUpdateTime}") // 检查旧时间戳 int decreaseStockWithTimestamp(@Param("id") Long id, @Param("quantity") Integer quantity, @Param("oldUpdateTime") Date oldUpdateTime); }


⚡ 方案3:Redis原子操作 - "高性能之王"(推荐!)

🌰 生活中的例子

抢红包:

  • 数据库方案:每个人都要去银行排队(慢)
  • Redis方案:微信服务器直接扣减,瞬间完成(快!)

💻 技术实现

实现1:Redis DECR原子操作

java

体验AI代码助手

代码解读

复制代码

/** * Redis方案:使用DECR原子操作 */ @Service public class RedisStockService { @Autowired private StringRedisTemplate redisTemplate; @Autowired private OrderService orderService; /** * 初始化库存到Redis */ public void initStock(Long productId, Integer stock) { String key = "product:stock:" + productId; redisTemplate.opsForValue().set(key, String.valueOf(stock)); } /** * 购买商品(Redis原子操作) */ public boolean buyProduct(Long productId, Integer quantity) { String stockKey = "product:stock:" + productId; // ⚡ Redis原子操作扣减库存 Long remainStock = redisTemplate.opsForValue() .decrement(stockKey, quantity); if (remainStock == null || remainStock < 0) { // 库存不足,回滚 if (remainStock != null && remainStock < 0) { redisTemplate.opsForValue().increment(stockKey, quantity); } log.warn("库存不足:商品ID={}, 剩余库存={}", productId, remainStock); return false; } try { // 异步创建订单(不阻塞扣减库存) orderService.createOrderAsync(productId, quantity); log.info("购买成功:商品ID={}, 数量={}, 剩余库存={}", productId, quantity, remainStock); return true; } catch (Exception e) { // 订单创建失败,回滚库存 redisTemplate.opsForValue().increment(stockKey, quantity); log.error("创建订单失败,已回滚库存", e); return false; } } /** * 查询剩余库存 */ public Integer getStock(Long productId) { String stockKey = "product:stock:" + productId; String stock = redisTemplate.opsForValue().get(stockKey); return stock != null ? Integer.parseInt(stock) : 0; } } /** * 性能对比: * * 数据库悲观锁:TPS = 67 💀 * 数据库乐观锁:TPS = 500 ✅ * Redis原子操作:TPS = 10000 🚀 快150倍! */

实现2:Lua脚本(更强大)

java

体验AI代码助手

代码解读

复制代码

/** * Redis Lua脚本方案(原子性更强) */ @Service public class RedisLuaStockService { @Autowired private StringRedisTemplate redisTemplate; /** * Lua脚本:扣减库存 */ private static final String LUA_SCRIPT = "local stock_key = KEYS[1] " + "local quantity = tonumber(ARGV[1]) " + "local stock = tonumber(redis.call('get', stock_key) or '0') " + "" + "if stock >= quantity then " + " redis.call('decrby', stock_key, quantity) " + " return stock - quantity " + // 返回剩余库存 "else " + " return -1 " + // 库存不足 "end"; /** * 购买商品(Lua脚本) */ public boolean buyProduct(Long productId, Integer quantity) { String stockKey = "product:stock:" + productId; // ⚡ 执行Lua脚本(原子操作) Long remainStock = redisTemplate.execute( RedisScript.of(LUA_SCRIPT, Long.class), Collections.singletonList(stockKey), quantity.toString() ); if (remainStock == null || remainStock < 0) { log.warn("库存不足:商品ID={}", productId); return false; } // 异步创建订单 orderService.createOrderAsync(productId, quantity); log.info("购买成功:剩余库存={}", remainStock); return true; } } /** * Lua脚本的优势: * * ✅ 原子性:整个脚本作为一个原子操作 * ✅ 减少网络往返:一次请求完成多个操作 * ✅ 性能极高:TPS可达10万+ * ✅ 逻辑灵活:可以实现复杂的业务逻辑 */

实现3:Redis + 数据库最终一致性

java

体验AI代码助手

代码解读

复制代码

/** * 完整的Redis+数据库方案 * Redis:扣减库存(快) * DB:订单数据(持久化) * 异步:同步库存到DB(最终一致性) */ @Service public class RedisDbStockService { @Autowired private StringRedisTemplate redisTemplate; @Autowired private ProductMapper productMapper; @Autowired private OrderService orderService; @Autowired private RabbitTemplate rabbitTemplate; /** * 购买商品(完整流程) */ public boolean buyProduct(Long productId, Integer quantity) { // 1. ⚡ Redis扣减库存(快速响应) String stockKey = "product:stock:" + productId; Long remainStock = redisTemplate.opsForValue() .decrement(stockKey, quantity); if (remainStock == null || remainStock < 0) { // 库存不足 if (remainStock != null && remainStock < 0) { redisTemplate.opsForValue().increment(stockKey, quantity); } return false; } // 2. 发送MQ消息(异步处理订单) OrderMessage message = OrderMessage.builder() .productId(productId) .quantity(quantity) .userId(getCurrentUserId()) .build(); rabbitTemplate.convertAndSend( "order.exchange", "order.create", message ); log.info("扣减Redis库存成功,已发送MQ消息"); return true; } /** * MQ消费者:创建订单并同步库存到DB */ @RabbitListener(queues = "order.create.queue") public void handleOrderCreate(OrderMessage message) { try { // 1. 创建订单 Order order = orderService.createOrder( message.getProductId(), message.getQuantity(), message.getUserId() ); // 2. 扣减数据库库存(最终一致性) int updated = productMapper.decreaseStock( message.getProductId(), message.getQuantity() ); if (updated == 0) { // DB库存不足(理论上不应该出现) log.error("DB库存不足,需要回滚"); // 回滚Redis库存 String stockKey = "product:stock:" + message.getProductId(); redisTemplate.opsForValue().increment( stockKey, message.getQuantity()); // 取消订单 orderService.cancelOrder(order.getId()); } log.info("订单创建完成,库存已同步到DB"); } catch (Exception e) { log.error("处理订单失败", e); // 重试或人工介入 } } /** * 定时任务:Redis库存同步到DB */ @Scheduled(cron = "0 */5 * * * ?") // 每5分钟 public void syncStockToDb() { // 扫描所有商品,同步库存 List<Product> products = productMapper.selectAll(); for (Product product : products) { String stockKey = "product:stock:" + product.getId(); String redisStock = redisTemplate.opsForValue().get(stockKey); if (redisStock != null) { int stock = Integer.parseInt(redisStock); // 对比DB库存,不一致则更新 if (stock != product.getStock()) { productMapper.updateStockDirectly(product.getId(), stock); log.info("同步库存:商品ID={}, Redis={}, DB={}->{}", product.getId(), stock, product.getStock(), stock); } } } } }


📦 方案4:消息队列削峰 - "流量控制"

🌰 生活中的例子

排队买奶茶:

  • 没有队列:所有人挤在柜台前(混乱)
  • 有队列:排队等候,一个个处理(有序)

💻 技术实现

java

体验AI代码助手

代码解读

复制代码

/** * MQ削峰方案 * * 流程: * 1. 用户下单 -> 发送MQ消息 * 2. MQ消费者 -> 串行处理订单 * 3. 扣减库存 -> 创建订单 */ @Service public class MqStockService { @Autowired private RabbitTemplate rabbitTemplate; /** * 提交购买请求(快速返回) */ public String submitBuyRequest(Long productId, Integer quantity) { // 生成订单ID String orderId = generateOrderId(); // 发送MQ消息 OrderMessage message = OrderMessage.builder() .orderId(orderId) .productId(productId) .quantity(quantity) .userId(getCurrentUserId()) .createTime(System.currentTimeMillis()) .build(); rabbitTemplate.convertAndSend( "order.exchange", "order.submit", message ); log.info("订单提交成功:orderId={}", orderId); // ⚡ 立即返回订单ID(用户可以轮询查询结果) return orderId; } /** * MQ消费者:处理订单(串行) */ @RabbitListener(queues = "order.submit.queue", concurrency = "1") // 单线程消费 public void handleOrderSubmit(OrderMessage message) { try { // 1. 检查库存 Product product = productMapper.selectById(message.getProductId()); if (product.getStock() < message.getQuantity()) { // 库存不足,更新订单状态 orderService.updateOrderStatus( message.getOrderId(), OrderStatus.STOCK_INSUFFICIENT ); // 发送通知 notifyService.notifyStockInsufficient(message); return; } // 2. 扣减库存(串行处理,不会超卖!) int updated = productMapper.decreaseStock( message.getProductId(), message.getQuantity() ); if (updated == 0) { // 扣减失败 orderService.updateOrderStatus( message.getOrderId(), OrderStatus.FAILED ); return; } // 3. 创建订单 orderService.createOrder(message); // 4. 更新订单状态 orderService.updateOrderStatus( message.getOrderId(), OrderStatus.SUCCESS ); // 5. 发送成功通知 notifyService.notifyOrderSuccess(message); log.info("订单处理成功:orderId={}", message.getOrderId()); } catch (Exception e) { log.error("订单处理失败", e); // 更新订单状态 orderService.updateOrderStatus( message.getOrderId(), OrderStatus.FAILED ); } } /** * 查询订单状态 */ public OrderStatus queryOrderStatus(String orderId) { return orderService.getOrderStatus(orderId); } } /** * 优点: * ✅ 削峰填谷:控制处理速度,保护系统 * ✅ 异步处理:用户体验好 * ✅ 解耦:订单和库存系统解耦 * * 缺点: * ⚠️ 延迟:用户需要等待处理结果 * ⚠️ 复杂度:需要状态查询接口 * ⚠️ 消息可能丢失:需要持久化 */


🎪 方案5:分布式锁 + 预扣库存

💻 技术实现

java

体验AI代码助手

代码解读

复制代码

/** * 分布式锁 + 预扣库存方案 * * 适用场景:秒杀活动 * * 流程: * 1. 活动开始前:预扣库存到Redis * 2. 用户抢购:扣减Redis库存(加分布式锁) * 3. 支付成功:扣减真实库存 * 4. 支付超时:回滚Redis库存 */ @Service public class DistributedLockStockService { @Autowired private RedissonClient redissonClient; @Autowired private StringRedisTemplate redisTemplate; @Autowired private ProductMapper productMapper; /** * 预扣库存(活动开始前) */ public void preOccupyStock(Long productId, Integer stock) { // 1. 将库存加载到Redis String stockKey = "seckill:stock:" + productId; redisTemplate.opsForValue().set(stockKey, String.valueOf(stock)); // 2. 将真实库存记录下来 String realStockKey = "seckill:real_stock:" + productId; redisTemplate.opsForValue().set(realStockKey, String.valueOf(stock)); log.info("预扣库存完成:商品ID={}, 库存={}", productId, stock); } /** * 抢购商品(分布式锁) */ public String rushToBuy(Long productId, Integer quantity) { String lockKey = "seckill:lock:" + productId; RLock lock = redissonClient.getLock(lockKey); try { // ⚡ 获取分布式锁(最多等待3秒,锁自动释放10秒) boolean isLocked = lock.tryLock(3, 10, TimeUnit.SECONDS); if (!isLocked) { log.warn("获取锁失败:商品ID={}", productId); return null; } // 1. 检查Redis库存 String stockKey = "seckill:stock:" + productId; Long remainStock = redisTemplate.opsForValue() .decrement(stockKey, quantity); if (remainStock == null || remainStock < 0) { // 库存不足,回滚 if (remainStock != null && remainStock < 0) { redisTemplate.opsForValue().increment(stockKey, quantity); } log.warn("库存不足"); return null; } // 2. 创建预订单(待支付) String orderId = orderService.createPreOrder(productId, quantity); // 3. 设置订单超时(15分钟未支付自动取消) String orderKey = "seckill:order:" + orderId; redisTemplate.opsForValue().set( orderKey, orderId, Duration.ofMinutes(15) ); log.info("抢购成功:orderId={}, 剩余库存={}", orderId, remainStock); return orderId; } catch (InterruptedException e) { log.error("获取锁被中断", e); return null; } finally { if (lock.isHeldByCurrentThread()) { lock.unlock(); } } } /** * 支付成功:扣减真实库存 */ @Transactional(rollbackFor = Exception.class) public boolean paySuccess(String orderId) { Order order = orderService.getById(orderId); // 1. 扣减数据库真实库存 int updated = productMapper.decreaseStock( order.getProductId(), order.getQuantity() ); if (updated == 0) { log.error("扣减真实库存失败"); return false; } // 2. 更新订单状态 orderService.updateOrderStatus(orderId, OrderStatus.PAID); // 3. 删除订单超时key String orderKey = "seckill:order:" + orderId; redisTemplate.delete(orderKey); log.info("支付成功,真实库存已扣减"); return true; } /** * 支付超时:回滚Redis库存 */ @Scheduled(fixedRate = 60000) // 每分钟执行一次 public void handleExpiredOrders() { // 扫描过期订单 Set<String> keys = redisTemplate.keys("seckill:order:*"); if (keys == null || keys.isEmpty()) { return; } for (String key : keys) { String orderId = redisTemplate.opsForValue().get(key); if (orderId != null) { continue; // 订单未过期 } // 订单已过期,回滚库存 Order order = orderService.getById(extractOrderId(key)); if (order != null && order.getStatus() == OrderStatus.PENDING) { // 回滚Redis库存 String stockKey = "seckill:stock:" + order.getProductId(); redisTemplate.opsForValue().increment( stockKey, order.getQuantity()); // 取消订单 orderService.cancelOrder(order.getId()); log.info("订单超时,已回滚库存:orderId={}", order.getId()); } } } } /** * 优点: * ✅ 高性能:Redis操作快 * ✅ 支持预扣:适合秒杀场景 * ✅ 自动回滚:超时自动释放库存 * * 缺点: * ⚠️ 复杂度高:需要处理超时、回滚 * ⚠️ 数据一致性:Redis和DB可能不一致 */


📊 方案对比总结

方案性能(TPS)并发度一致性复杂度适用场景
悲观锁(DB)67 💀强一致简单低并发
乐观锁(DB)500 ✅强一致中等中并发
Redis原子操作10000 🚀最终一致中等高并发(推荐)
MQ削峰5000 ✅最终一致超高并发
分布式锁+预扣8000 🚀最终一致秒杀活动

✅ 最佳实践

markdown

体验AI代码助手

代码解读

复制代码

生产环境推荐方案:Redis + MQ + 数据库 架构设计: □ L1:Redis扣减库存(快速响应,TPS=1万+) □ L2:MQ异步处理订单(削峰填谷) □ L3:数据库持久化(最终一致性) 关键要点: □ 库存预热:提前加载到Redis □ 原子操作:使用Lua脚本 □ 异步处理:MQ削峰 □ 降级策略:限流、熔断 □ 监控告警:库存、延迟、失败率 极端场景处理: □ Redis宕机 -> 降级到数据库 □ MQ堵塞 -> 限流保护 □ 数据不一致 -> 定时对账 □ 恶意刷单 -> 黑名单、验证码


🎉 总结

核心要点

体验AI代码助手

代码解读

复制代码

防止超卖的本质:保证库存扣减的原子性! 五大方案: 1️⃣ 悲观锁:简单但性能差 2️⃣ 乐观锁:性能中等,有重试 3️⃣ Redis原子操作:高性能,推荐!⭐⭐⭐⭐⭐ 4️⃣ MQ削峰:异步处理,削峰填谷 5️⃣ 分布式锁+预扣:适合秒杀 推荐方案:Redis + MQ + 数据库


记住:防超卖的核心是"原子操作+异步处理+最终一致性"!🎯

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1183197.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2026采购景津装备推荐哪个经理 专业选购指南 - 资讯焦点

2026景津装备推荐哪个经理 专业选购指南 引言:过滤装备采购的核心痛点与推荐逻辑 据《2025-2030年中国过滤装备行业发展白皮书》数据显示,2025年中国过滤装备市场规模突破380亿元,年复合增长率达12.7%,其中压滤机细…

AI优化搜索:从关键词匹配到深度理解用户意图的变革

在如今的数字信息环境里&#xff0c;用户获取信息的首要入口仍然是搜索引擎&#xff0c;随着人工智能技术大力地深度融合&#xff0c;传统的搜索引擎优化也就是SEO正经历着一场变革&#xff0c;这场变革是从由算法来驱动朝着智能理解进行跃迁的&#xff0c;于是AI搜索优化就产生…

2026必备!9个AI论文工具,助继续教育学生轻松写论文!

2026必备&#xff01;9个AI论文工具&#xff0c;助继续教育学生轻松写论文&#xff01; AI 工具助力学术写作&#xff0c;轻松应对论文挑战 随着人工智能技术的不断进步&#xff0c;AI 工具在学术写作中的应用越来越广泛。对于继续教育的学生而言&#xff0c;撰写高质量的论文不…

探索Labodorf光学相干断层扫描仪:供应商、代理商与性价比全解析 - 品牌推荐大师1

01 行业现状:光学相干断层扫描技术市场现状与增长趋势光学相干断层扫描(OCT)作为一项革命性的非侵入式成像技术,已在眼科、皮肤科、心血管科等多个医学领域得到广泛应用。根据世界卫生组织2024年发布的全球视觉健康…

项目简介

1.基于物联网设计的蜂箱智能监测系统设计 https://mp.weixin.qq.com/s/V9XWJSpsMgMslvGHqHA7UQ

我们的经常遇到FM20.DLL丢失找不到问题 免费下载方法分享

在使用电脑系统时经常会出现丢失找不到某些文件的情况&#xff0c;由于很多常用软件都是采用 Microsoft Visual Studio 编写的&#xff0c;所以这类软件的运行需要依赖微软Visual C运行库&#xff0c;比如像 QQ、迅雷、Adobe 软件等等&#xff0c;如果没有安装VC运行库或者安装…

罗技Zone Vibe系列商务耳机推荐:混合办公场景的专业之选 - 资讯焦点

罗技Zone Vibe系列商务耳机推荐:混合办公场景的专业之选在混合办公成为主流的今天,一款能兼顾长时间佩戴舒适、高清通话、多设备兼容的商务耳机,已经成为职场人的“生产力工具”。罗技作为全球知名的外设品牌,针对…

2026年医美信息系统高口碑榜单,Top5软件帮助医美机构实现良性自增长体系 - 速递信息

在医疗美容行业数字化转型的浪潮下,高效的信息管理系统已成为机构提升运营效能的核心竞争力。通过对2026年市场主流医美HIS系统的调研以及市场公开资料,我们从功能创新性、用户体验、数据安全及行业适配度等维度筛选…

我们的系统遇到framedyn.dll丢失损坏问题 免费下载方法分享

在使用电脑系统时经常会出现丢失找不到某些文件的情况&#xff0c;由于很多常用软件都是采用 Microsoft Visual Studio 编写的&#xff0c;所以这类软件的运行需要依赖微软Visual C运行库&#xff0c;比如像 QQ、迅雷、Adobe 软件等等&#xff0c;如果没有安装VC运行库或者安装…

强烈安利自考必看TOP10 AI论文网站测评

强烈安利自考必看TOP10 AI论文网站测评 2026年自考AI论文写作工具测评&#xff1a;为何值得一看 随着人工智能技术的不断进步&#xff0c;AI写作工具在学术领域的应用日益广泛&#xff0c;尤其对于自考学生而言&#xff0c;如何高效完成论文写作成为关键课题。然而&#xff0c;…

什么身体乳有效?2026秋冬缓解皮肤干燥瘙痒止痒润肤身体乳推荐,干燥肌续命清单! - 资讯焦点

对于干燥肌来说,秋冬最离不开的就是一瓶能“打”的身体乳——既要对抗低温干燥带来的水分快速流失,又要缓解起皮干痒的尴尬,还要兼顾肤感不黏腻、适配日常场景。踩过无数雷后,我汇总了7款实测好用的深层保湿身体乳…

Locust百万并发容器化部署实战指南

容器化部署的价值与挑战‌ 在云原生时代&#xff0c;性能测试面临高并发、弹性的新需求。Locust作为开源工具&#xff0c;支持分布式测试&#xff0c;但传统部署难以突破单机瓶颈。容器化&#xff08;如Docker和Kubernetes&#xff09;通过资源隔离和弹性伸缩&#xff0c;成为…

玩转TI的ADC12D1600:高速并行AD转换器的Verilog控制之旅

ADC12D1600是TI旗下的一款高速并行AD转换器。 其有四种工作模式。 在双沿其最大采样率为可达2.8GHz。 本程序为verilog编写的控制程序&#xff0c;并通过串口将数据输出至上位机。 本程序设计到 DDR数据采样 数据速率的降速采样等实际应用中需要用到的技巧。 本程序使用ADC12D…

OpenAI芯片自研与开发者大会技术动态

OpenAI与某中心达成协议&#xff0c;为其人工智能设计自研芯片 相关报道&#xff1a;受此消息影响&#xff0c;某中心股价上涨9%… OpenAI在开发者大会上宣布的所有内容 在年度开发者大会上&#xff0c;OpenAI发布了一系列产品更新和模型增强&#xff0c;主要包括&#xff1a; …

【复现】考虑泊位优化和多能协同的港口综合能源系统运行优化(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

金山平台打造黄金资产增值标杆 - 速递信息

在全球黄金市场迎来历史性发展机遇的背景下,金山——黄金资产增值综合服务平台应运而生。作为紫金矿业集团股份有限公司全资子公司,金山(香港)国际矿业有限公司依托母公司强大的产业实力和香港国际化金融优势,致力…

企业标书“智审”时代已全面开启,火眼审阅标书查重—您值得信任的伙伴 - 资讯焦点

企业标书“智审”时代已全面开启,火眼审阅标书查重—您值得信任的伙伴 2025年末的中央经济工作会议,为来年的招投标市场释放了一个前所未有的清晰信号:破除壁垒、整治乱象已成为与经济复苏同等重要的核心任务。会议…

工业级固态硬盘推荐:天硕 G40 M.2 NVMe 2280 工业级 SSD - 资讯焦点

<span microsoft="" yahei";="" color:="" rgb(12,="" 12,="" 12);"="">如果您正在为工业控制、嵌入式系统、边缘计算或国产化主机平台…

多跳收集-传输无线传感器网络(WSNs)中的性能增强:在窃听者和硬件噪声存在的情况下采用路径选择方法(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1…

不花冤枉钱!2026儿童洗发水性价比榜单:按年龄段匹配需求,热门品牌解析推荐 - 资讯焦点

儿童头皮与成人存在显著生理差异:角质层厚度仅为成人的1/3,屏障功能尚未成熟,皮脂分泌随年龄呈现阶段性变化——婴幼儿分泌稀薄、青少年分泌旺盛,这决定了儿童洗发水的选购不能仅停留在“温和”层面,而需遵循“分…