根据雪花算法生成交易订单的id
下面是一个用Java实现的生成雪花算法id的示例代码:
import java.util.concurrent.atomic.AtomicLong;
public class SnowflakeIdGenerator {
private static final long START_TIMESTAMP = 1600000000000L;
private static final long WORKER_ID_BITS = 5L;
private static final long DATACENTER_ID_BITS = 5L;
private static final long SEQUENCE_BITS = 12L;
private static final long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS);
private static final long MAX_DATACENTER_ID = ~(-1L << DATACENTER_ID_BITS);
private static final long WORKER_ID_SHIFT = SEQUENCE_BITS;
private static final long DATACENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;
private static final long TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATACENTER_ID_BITS;
private static final long SEQUENCE_MASK = ~(-1L << SEQUENCE_BITS);
private final long workerId;
private final long datacenterId;
private final AtomicLong sequence;
private long lastTimestamp;
public SnowflakeIdGenerator(long workerId, long datacenterId) {
if (workerId > MAX_WORKER_ID || workerId < 0) {
throw new IllegalArgumentException("Worker ID can't be greater than " + MAX_WORKER_ID + " or less than 0");
}
if (datacenterId > MAX_DATACENTER_ID || datacenterId < 0) {
throw new IllegalArgumentException("Datacenter ID can't be greater than " + MAX_DATACENTER_ID + " or less than 0");
}
this.workerId = workerId;
this.datacenterId = datacenterId;
this.sequence = new AtomicLong(0);
this.lastTimestamp = -1;
}
public synchronized long getNextId() {
long timestamp = System.currentTimeMillis();
if (timestamp < lastTimestamp) {
throw new RuntimeException("Clock moved backwards. Refusing to generate id");
}
if (timestamp == lastTimestamp) {
long sequence = this.sequence.incrementAndGet() & SEQUENCE_MASK;
if (sequence == 0) {
timestamp = waitNextMillis(lastTimestamp);
}
} else {
this.sequence.set(0);
}
lastTimestamp = timestamp;
return ((timestamp - START_TIMESTAMP) << TIMESTAMP_LEFT_SHIFT) |
(datacenterId << DATACENTER_ID_SHIFT) |
(workerId << WORKER_ID_SHIFT) |
sequence;
}
private long waitNextMillis(long lastTimestamp) {
long currentTimestamp = System.currentTimeMillis();
while (currentTimestamp <= lastTimestamp) {
currentTimestamp = System.currentTimeMillis();
}
return currentTimestamp;
}
}
使用示例:
public class Main {
public static void main(String[] args) {
SnowflakeIdGenerator idGenerator = new SnowflakeIdGenerator(1, 1);
long orderId = idGenerator.getNextId();
System.out.println("Generated Order ID: " + orderId);
}
}
这段代码创建了一个SnowflakeIdGenerator实例,并使用workerId和datacenterId作为参数进行初始化。然后调用getNextId()方法生成下一个id。每个id由timestamp、datacenterId、workerId和sequence组成,可以根据需要进行灵活调整。下面是一个用Java实现的生成雪花算法id的示例代码:
import java.util.concurrent.atomic.AtomicLong;
public class SnowflakeIdGenerator {
private static final long START_TIMESTAMP = 1600000000000L;
private static final long WORKER_ID_BITS = 5L;
private static final long DATACENTER_ID_BITS = 5L;
private static final long SEQUENCE_BITS = 12L;
private static final long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS);
private static final long MAX_DATACENTER_ID = ~(-1L << DATACENTER_ID_BITS);
private static final long WORKER_ID_SHIFT = SEQUENCE_BITS;
private static final long DATACENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;
private static final long TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATACENTER_ID_BITS;
private static final long SEQUENCE_MASK = ~(-1L << SEQUENCE_BITS);
private final long workerId;
private final long datacenterId;
private final AtomicLong sequence;
private long lastTimestamp;
public SnowflakeIdGenerator(long workerId, long datacenterId) {
if (workerId > MAX_WORKER_ID || workerId < 0) {
throw new IllegalArgumentException("Worker ID can't be greater than " + MAX_WORKER_ID + " or less than 0");
}
if (datacenterId > MAX_DATACENTER_ID || datacenterId < 0) {
throw new IllegalArgumentException("Datacenter ID can't be greater than " + MAX_DATACENTER_ID + " or less than 0");
}
this.workerId = workerId;
this.datacenterId = datacenterId;
this.sequence = new AtomicLong(0);
this.lastTimestamp = -1;
}
public synchronized long getNextId() {
long timestamp = System.currentTimeMillis();
if (timestamp < lastTimestamp) {
throw new RuntimeException("Clock moved backwards. Refusing to generate id");
}
if (timestamp == lastTimestamp) {
long sequence = this.sequence.incrementAndGet() & SEQUENCE_MASK;
if (sequence == 0) {
timestamp = waitNextMillis(lastTimestamp);
}
} else {
this.sequence.set(0);
}
lastTimestamp = timestamp;
return ((timestamp - START_TIMESTAMP) << TIMESTAMP_LEFT_SHIFT) |
(datacenterId << DATACENTER_ID_SHIFT) |
(workerId << WORKER_ID_SHIFT) |
sequence;
}
private long waitNextMillis(long lastTimestamp) {
long currentTimestamp = System.currentTimeMillis();
while (currentTimestamp <= lastTimestamp) {
currentTimestamp = System.currentTimeMillis();
}
return currentTimestamp;
}
}
使用示例:
public class Main {
public static void main(String[] args) {
SnowflakeIdGenerator idGenerator = new SnowflakeIdGenerator(1, 1);
long orderId = idGenerator.getNextId();
System.out.println("Generated Order ID: " + orderId);
}
}
这段代码创建了一个SnowflakeIdGenerator实例,并使用workerId和datacenterId作为参数进行初始化。然后调用getNextId()方法生成下一个id。每个id由timestamp、datacenterId、workerId和sequence组成,可以根据需要进行灵活调整。
以下Java代码实现检查库存、生成订单并存入MySQL数据库的示例:
import redis.clients.jedis.Jedis;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.UUID;
public class InventoryManager {
private static final String REDIS_HOST = "localhost";
private static final int REDIS_PORT = 6379;
private static final String REDIS_PASSWORD = "your_redis_password";
private static final String MYSQL_HOST = "localhost";
private static final int MYSQL_PORT = 3306;
private static final String MYSQL_DATABASE = "your_mysql_database";
private static final String MYSQL_USER = "your_mysql_username";
private static final String MYSQL_PASSWORD = "your_mysql_password";
public static void main(String[] args) {
// 模拟商品ID和数量
String productId = "product1";
int quantity = 1;
// 连接Redis
Jedis jedis = new Jedis(REDIS_HOST, REDIS_PORT);
jedis.auth(REDIS_PASSWORD);
// 检查库存
int stock = Integer.parseInt(jedis.get(productId));
if (stock >= quantity) {
// 生成订单ID
String orderId = UUID.randomUUID().toString();
// 存储订单到MySQL数据库
saveOrderToMySQL(orderId, productId, quantity);
// 更新库存
jedis.decrBy(productId, quantity);
System.out.println("订单生成成功,订单ID:" + orderId);
} else {
System.out.println("库存不足,无法生成订单");
}
}
private static void saveOrderToMySQL(String orderId, String productId, int quantity) {
try {
// 连接MySQL数据库
Connection conn = DriverManager.getConnection("jdbc:mysql://" + MYSQL_HOST + ":" + MYSQL_PORT + "/" + MYSQL_DATABASE, MYSQL_USER, MYSQL_PASSWORD);
// 插入订单数据
String sql = "INSERT INTO orders (order_id, product_id, quantity) VALUES (?, ?, ?)";
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setString(1, orderId);
stmt.setString(2, productId);
stmt.setInt(3, quantity);
stmt.executeUpdate();
// 关闭数据库连接
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
请根据实际情况修改REDIS_HOST
、REDIS_PORT
、REDIS_PASSWORD
、MYSQL_HOST
、MYSQL_PORT
、MYSQL_DATABASE
、MYSQL_USER
和MYSQL_PASSWORD
的值,以确保与您的实际环境匹配。
这段代码假设您已经在Redis中存储了商品的库存信息,以及在MySQL中创建了名为orders
的表,包含order_id
、product_id
和quantity
字段。
在代码执行过程中,它会先连接到Redis,检查商品的库存。如果库存足够,则生成一个随机的订单ID,并将订单存储到MySQL数据库中,同时更新Redis中的库存信息。