1、基于時間戳生成流水號
利用當前時間戳生成流水號,可以確保唯一性。通過格式化時間戳,可以生成固定位數的流水號。
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
String serialNumber = sdf.format(new Date());
特點:時間戳生成的流水號具有唯一性和順序性,適合高并發場景。
優點:無需額外存儲狀態,實現簡單。
缺點:流水號長度可能不固定,需要根據需求調整格式。
2、使用數據庫自增ID
通過數據庫的自增主鍵生成流水號,可以保證唯一性和連續性。
// 假設使用JPA
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
特點:依賴數據庫的自增機制,適合有數據庫支持的場景。
優點:實現簡單,保證唯一性和連續性。
缺點:需要數據庫支持,性能可能受數據庫限制。
3、基于Redis生成流水號
利用Redis的原子性操作生成自增流水號,適合分布式系統。
// 使用RedisTemplate
Long serialNumber = redisTemplate.opsForValue().increment("serial_key");
特點:Redis的INCR命令是原子性的,適合高并發場景。
優點:性能高,支持分布式系統。
缺點:需要引入Redis,增加系統復雜性。
4、UUID生成流水號
使用UUID生成唯一標識符,可以保證全局唯一性。
String serialNumber = UUID.randomUUID().toString().replace("-", "");
特點:UUID生成的流水號長度固定,但無序。
優點:無需中央協調器,適合分布式系統。
缺點:流水號較長且無序,不適合需要順序的場景。
5、雪花算法生成流水號
雪花算法(Snowflake)生成的ID具有時間有序性,適合分布式系統。
// 使用Hutool工具類
long serialNumber = IdUtil.getSnowflake(1, 1).nextId();
特點:結合時間戳、機器ID和序列號生成ID,保證唯一性和順序性。
優點:性能高,適合分布式系統。
缺點:依賴系統時鐘,時鐘回撥可能導致ID重復。
6、自定義計數器生成流水號
通過內存中的計數器生成流水號,適合單機或低并發場景。
private static AtomicLong counter = new AtomicLong(0);
String serialNumber = String.format("%010d", counter.incrementAndGet());
特點:實現簡單,適合單機或低并發場景。
優點:無需外部依賴,性能高。
缺點:重啟后計數器會重置,不適合分布式系統。
7、結合日期和序列號生成流水號
將當前日期與序列號結合生成流水號,適合需要日期前綴的場景。
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
String dateStr = sdf.format(new Date());
String serialNumber = dateStr + String.format("%04d", sequence.incrementAndGet());
特點:流水號包含日期信息,便于分類和查詢。
優點:實現簡單,適合需要日期前綴的場景。
缺點:序列號每日重置,可能重復。
8、使用ZooKeeper生成流水號
利用ZooKeeper的順序節點生成唯一且有序的流水號。
// 使用CuratorFramework
String path = curatorFramework.create().withMode(CreateMode.PERSISTENT_SEQUENTIAL).forPath("/serial/");
String serialNumber = path.substring(path.lastIndexOf('/') + 1);
特點:ZooKeeper的順序節點保證唯一性和順序性。
優點:適合分布式系統,保證高可用性。
缺點:依賴ZooKeeper,性能較低。