您好,登录后才能下订单哦!
在分布式系统中,生成全局唯一ID是一个常见的需求。全局唯一ID通常用于标识系统中的各种资源,如订单、用户、消息等。本文将介绍如何使用Java基于数据库实现全局唯一ID的几种常见方法。
最简单的方法是使用数据库的自增主键功能。大多数关系型数据库(如MySQL、PostgreSQL)都支持自增主键。每次插入一条新记录时,数据库会自动为该记录生成一个唯一的ID。
CREATE TABLE orders (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
order_data VARCHAR(255)
);
public class Order {
private Long id;
private String orderData;
// Getters and setters
}
public class OrderDAO {
public void saveOrder(Order order) {
String sql = "INSERT INTO orders (order_data) VALUES (?)";
try (Connection conn = getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
pstmt.setString(1, order.getOrderData());
pstmt.executeUpdate();
try (ResultSet rs = pstmt.getGeneratedKeys()) {
if (rs.next()) {
order.setId(rs.getLong(1));
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
某些数据库(如Oracle、PostgreSQL)支持序列(Sequence),可以生成唯一的数字序列。通过使用序列,可以在多个数据库实例之间生成唯一的ID。
CREATE SEQUENCE order_id_seq START WITH 1 INCREMENT BY 1;
public class OrderDAO {
public Long generateOrderId() {
String sql = "SELECT nextval('order_id_seq')";
try (Connection conn = getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery()) {
if (rs.next()) {
return rs.getLong(1);
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
UUID(Universally Unique Identifier)是一种128位的全局唯一标识符。Java提供了java.util.UUID
类来生成UUID。
UUID.randomUUID()
生成UUID。public class Order {
private String id;
private String orderData;
public Order() {
this.id = UUID.randomUUID().toString();
}
// Getters and setters
}
CREATE TABLE orders (
id VARCHAR(36) PRIMARY KEY,
order_data VARCHAR(255)
);
在分布式系统中,可以使用分布式ID生成器来生成全局唯一ID。常见的分布式ID生成算法有Snowflake算法、Twitter的Snowflake、百度的UidGenerator等。
public class SnowflakeIdGenerator {
private final long twepoch = 1288834974657L;
private final long workerIdBits = 5L;
private final long datacenterIdBits = 5L;
private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
private final long sequenceBits = 12L;
private final long workerIdShift = sequenceBits;
private final long datacenterIdShift = sequenceBits + workerIdBits;
private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
private final long sequenceMask = -1L ^ (-1L << sequenceBits);
private long workerId;
private long datacenterId;
private long sequence = 0L;
private long lastTimestamp = -1L;
public SnowflakeIdGenerator(long workerId, long datacenterId) {
if (workerId > maxWorkerId || workerId < 0) {
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
}
if (datacenterId > maxDatacenterId || datacenterId < 0) {
throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
}
this.workerId = workerId;
this.datacenterId = datacenterId;
}
public synchronized long nextId() {
long timestamp = timeGen();
if (timestamp < lastTimestamp) {
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
}
if (lastTimestamp == timestamp) {
sequence = (sequence + 1) & sequenceMask;
if (sequence == 0) {
timestamp = tilNextMillis(lastTimestamp);
}
} else {
sequence = 0L;
}
lastTimestamp = timestamp;
return ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence;
}
protected long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
}
protected long timeGen() {
return System.currentTimeMillis();
}
}
在Java中基于数据库实现全局唯一ID有多种方法,每种方法都有其优缺点。选择哪种方法取决于具体的应用场景和需求。对于简单的单机应用,自增主键或UUID可能是最简单的选择;而对于分布式系统,可能需要使用分布式ID生成器来确保全局唯一性。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。