需求是要支持春节百万并发高并发抢购红包商品。
架构师经过多方技术调研,整理开发以下几个核心步骤:
1.使用redis缓存icon支持高并发
2.商品数据量先存入缓存icon中
3.抢购商品锁定,并从缓存中读取数量减1
4.释放商品锁
代码
import org.redisson.Redisson; import org.redisson.api.RLock; import org.redisson.api.RAtomicLong; import org.redisson.config.Config; public class RedPacketPurchaseService { private static final Redisson redisson = initRedisson(); private static final String PRODUCT_ID = "product_id"; private static final String STOCK_KEY = "stock:" + PRODUCT_ID; private static final String LOCK_KEY = "lock:" + PRODUCT_ID; private static Redisson initRedisson() { Config config = new Config(); config.useSingleServer().setAddress("redis://localhost:6379"); return Redisson.create(config); } public boolean purchase() { RLock lock = redisson.getLock(LOCK_KEY); try { // 使用公平锁并设置超时时间防止死锁 if (lock.tryLock(10, TimeUnit.SECONDS)) { try { RAtomicLong stock = redisson.getAtomicLong(STOCK_KEY); if (stock.decrementAndGet() > 0) { System.out.println("用户成功抢购一个红包商品,剩余库存: " + stock.get()); // 这里省略了持久化到数据库的操作,实际应用中需要异步保存购买记录 return true; } else { // 库存不足,正常情况下不需要还原库存,这里仅作为演示 stock.incrementAndGet(); } } finally { lock.unlock(); } } else { System.out.println("当前抢购人数过多,请稍后再试"); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); System.out.println("线程中断,抢购失败"); } return false; } // 在服务启动时或者定时任务中预加载商品库存至Redis Atomic Long public void preloadStock(int initialStock) { RAtomicLong stock = redisson.getAtomicLong(STOCK_KEY); stock.set(initialStock); } }
**注意事项**:
- 上述代码使用了Redisson提供的`RLock`实现分布式锁,并结合`RAtomicLong`进行原子性的库存扣减,能在一定程度上保证在高并发下的数据一致性。
- 实际生产环境中还需要考虑更多的因素,如网络延迟、服务器性能、数据库写入瓶颈等,并可能需要引入更复杂的策略,例如队列、延时消息队列(如RabbitMQ或RocketMQ)、降级处理等手段来确保系统的稳定性和可用性。
- 另外,为了应对百万级甚至更高的并发,通常还会对系统进行水平扩展,增加服务器数量并通过负载均衡器分配请求,同时也要注意数据库层面的优化和分库分表等操作。
原文链接:https://blog.csdn.net/a913222/article/details/136118200