java 高并发 订单编号递增(解决方案)

本文讨论了在并发场景下,如何避免订单号重复的问题,并提出了五种解决方案:使用同步锁、Redis自增、乐观锁、数据库行锁及利用唯一性约束。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

业务描述:

  首先从数据中查找最近的一条订单数据,然后将之前的订单号码+1作为新的订单号码,插入到数据库当中。(需求不能改变

  当出现并发操作时,A从数据库中获取最近一条订单的订单号为N,这是A还没有完成新订单的插入操作。B用户进来,也获取最近一条订单的订单号为N,这是A和B 想数据库同事插入的订单就有相同的订单号码。

 

解决方法1:

  程序用同步锁控制(synchronized),性能急剧下降了,本身 java 就是多线程的,你把它单线程使用,不是明智的选择,同时,如果分布式部署的时候,加了 synchronized  也无法控制并发。

 

解决方法2:

  redis 自增。将订单号自增字段,交给redis管理。

 

解决方法3:

  乐观锁:(可能睡涉及到多次提交,用户体验性差)。

 

解决方法4:

  数据库行锁:行锁的同时,可能会影响其他程序对数据库的操作。

 

解决方式5:

  数据库(唯一性约束UNIQUE KEY),由于订单号不能重复,当插入相同的订单号码,就会产生错误。

 

转载于:https://www.cnblogs.com/chihirotan/p/6483890.html

### 资源复用与线程管理 在高并发场景中,资源复用是提升系统性能的关键策略之一。通过线程池和连接池的使用,可以显著减少线程和数据库连接的创建与销毁开销。Java 提供了 `ExecutorService` 接口和 `Executors` 工厂类来创建线程池,例如固定大小的线程池可以有效控制并发线程的数量,避免资源耗尽问题: ```java ExecutorService executor = Executors.newFixedThreadPool(10); executor.submit(() -> { // 执行任务 }); ``` 此外,数据库连接池(如 HikariCP 或 Druid)可以复用数据库连接,避免每次数据库访问都需要建立和关闭连接的开销。 ### 减少锁竞争与并发控制 在并发环境中,锁竞争是影响性能的重要因素之一。为了减少锁的粒度,可以采用无锁结构(如 `AtomicInteger`)或使用 `ReentrantLock` 提供的细粒度锁机制。`AtomicInteger` 利用 CAS(Compare and Swap)操作实现线程安全,避免了传统锁的阻塞开销。此外,分段锁(如 `ConcurrentHashMap` 的实现)将锁的范围进一步细化,允许多个线程同时访问不同的数据段,从而提高并发性能。 ### 异步化与非阻塞IO 异步化是一种有效的性能优化策略,尤其是在处理耗时操作时。Java 提供了 `CompletableFuture` 来支持异步编程,使得任务可以异步执行并减少主线程的阻塞时间。例如: ```java CompletableFuture<Void> future = CompletableFuture.runAsync(() -> { // 异步执行的任务 }); future.join(); // 等待任务完成 ``` 此外,Java NIO(New IO)提供了非阻塞 IO 操作的能力,通过 `Selector`、`Channel` 和 `Buffer` 的组合,能够高效处理大量并发连接,适用于高并发网络编程场景。 ### 数据缓存与读写分离 数据缓存是降低数据库压力的重要手段。通过本地缓存(如 `Caffeine`)或分布式缓存(如 Redis),可以显著减少对数据库的直接访问。例如,使用 Redis 缓存热点数据,可以有效提升读取性能。同时,在数据库层面,可以通过读写分离将读操作和写操作分配到不同的数据库实例上,从而提升并发处理能力。分库分表技术进一步将数据分布到多个物理节点,提高系统的扩展性和性能。 ### 高并发订单号生成方案 在分布式系统中,订单号需要满足全局唯一性、趋势递增高并发支持等要求。基于时间戳和节点 ID 的组合算法是一种常见的订单号生成方案,例如雪花算法(Snowflake)。为了进一步提升性能,可以结合 Redis 预生成订单号池,确保在高并发场景下快速生成订单号。例如: ```java public class OrderIdGenerator { private final long nodeId; private long lastTimestamp = -1L; private long nodeIdBits = 10L; private long maxSequence = ~(-1L << 12); // 4096 private long nodeBits = 12; private long sequence = 0L; public OrderIdGenerator(long nodeId) { this.nodeId = nodeId << nodeBits; } public synchronized long nextId() { long timestamp = System.currentTimeMillis(); if (timestamp < lastTimestamp) { throw new RuntimeException("时钟回拨"); } if (timestamp == lastTimestamp) { sequence = (sequence + 1) & maxSequence; if (sequence == 0) { timestamp = tilNextMillis(lastTimestamp); } } else { sequence = 0; } lastTimestamp = timestamp; return (timestamp << (nodeIdBits + nodeBits)) | nodeId | sequence; } private long tilNextMillis(long lastTimestamp) { long timestamp = System.currentTimeMillis(); while (timestamp <= lastTimestamp) { timestamp = System.currentTimeMillis(); } return timestamp; } } ``` ### 高性能网络编程与 Netty Netty 是一个基于 NIO 的高性能网络框架,广泛应用于构建高并发服务器。它简化了 TCP/UDP 协议栈的处理,并提供了事件驱动的编程模型,使得开发者能够轻松地编写出高性能、可扩展的服务端和客户端程序。Netty 的优势在于其高效的内存管理、灵活的协议支持以及非阻塞 IO 模型,适用于构建大规模分布式系统。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值