Cet article présente des implémentations concrètes pour la génération d'identifiants uniques globaux (UID) en Java, en s'appuyant sur des projets open-source de Baidu et Meituan. Les principes théoriques étant largement documentés, nous nous concentrerons ici sur les aspects pratiques du code.
Générateur d'UID Baidu
Dépendance Maven
<dependency>
<groupId>com.baidu.uid</groupId>
<artifactId>uid-generator-sdk</artifactId>
<version>1.0.15</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
Schéma SQL pour le nœud worker
DROP TABLE IF EXISTS `worker_node`;
CREATE TABLE `worker_node` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID du worker',
`host_name` varchar(64) NOT NULL COMMENT 'Nom d''hôte',
`port` varchar(64) NOT NULL COMMENT 'Port',
`type` int NOT NULL COMMENT 'Type de nœud',
`launch_date` DATE NOT NULL COMMENT 'Date de lancement',
`modified` timestamp NOT NULL COMMENT 'Date de modification',
`created` timestamp NOT NULL COMMENT 'Date de création',
PRIMARY KEY (`id`)
) COMMENT='Assigneur d''ID worker pour le générateur d''UID' ENGINE=InnoDB;
Configuration de l'application (application.yml)
spring:
datasource:
url: jdbc:mysql://localhost:3306/your_database
username: your_username
password: your_password
driver-class-name: com.mysql.cj.jdbc.Driver
Configuration des Beans Spring
package com.example.uid.config;
import com.baidu.uid.generator.impl.DefaultUidGenerator;
import com.baidu.uid.worker.DisposableWorkerIdAssigner;
import com.baidu.uid.worker.WorkerIdAssigner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class UidGeneratorConfig {
@Bean
public WorkerIdAssigner workerIdAssigner() {
// Utilisation d'un assigneur basé sur une base de données, ou un autre mécanisme
DisposableWorkerIdAssigner assigner = new DisposableWorkerIdAssigner();
// Configuration de l'assigneur si nécessaire (ex: via JdbcTemplate)
return assigner;
}
@Bean
public DefaultUidGenerator defaultUidGenerator(WorkerIdAssigner workerIdAssigner) {
DefaultUidGenerator uidGenerator = new DefaultUidGenerator();
uidGenerator.setWorkerIdAssigner(workerIdAssigner);
uidGenerator.setEpochStr("2023-01-01"); // Votre date d'époque
uidGenerator.setTimeBits(30);
uidGenerator.setWorkerBits(22);
uidGenerator.setSeqBits(12);
return uidGenerator;
}
}
Exemple de test
package com.example.uid.test;
import com.baidu.uid.generator.impl.DefaultUidGenerator;
import com.baidu.uid.generator.utils.UidUtils;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class UidGeneratorTest {
@Autowired
private DefaultUidGenerator defaultUidGenerator;
@Test
public void testGenerateUID() {
long uniqueId = defaultUidGenerator.getUID();
System.out.println("Generated UID: " + uniqueId);
System.out.println("Parsed UID: " + UidUtils.parseUID(uniqueId));
}
}
Générateur d'UID Meituan (Leaf)
Dépendance Maven
<dependency>
<groupId>com.meituan.leaf</groupId>
<artifactId>leaf-core</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
Schéma SQL pour les segments ID
DROP TABLE IF EXISTS `id_segment`;
CREATE TABLE `id_segment` (
`biz_tag` varchar(50) NOT NULL COMMENT 'Tag métier',
`max_id` bigint(20) NOT NULL COMMENT 'ID maximum alloué',
`step` bigint(20) NOT NULL COMMENT 'Taille du segment',
`last_update_time` datetime DEFAULT NULL,
`current_update_time` datetime DEFAULT NULL,
PRIMARY KEY (`biz_tag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Table de stockage des segments d''ID';
INSERT INTO `id_segment` (`biz_tag`, `max_id`, `step`, `last_update_time`, `current_update_time`) VALUES ('Order', 1000, 100, NOW(), NOW());
Configuration des Beans Spring
package com.example.uid.config;
import com.meituan.leaf.common.Result;
import com.meituan.leaf.common.Status;
import com.meituan.leaf.jdbc.impl.MySqlLeafImpl;
import com.meituan.leaf.segment.SegmentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
@Configuration
public class LeafConfig {
@Autowired
private JdbcTemplate jdbcTemplate;
@Bean
public SegmentService segmentService() {
MySqlLeafImpl mysqlLeaf = new MySqlLeafImpl();
mysqlLeaf.setJdbcTemplate(jdbcTemplate);
mysqlLeaf.setBizTag("Order"); // Le tag métier de votre choix
mysqlLeaf.setCacheEnabled(true); // Activer la mise en cache des segments
return mysqlLeaf;
}
// Méthode utilitaire pour obtenir un ID, encapsulant la logique de Leaf
public long getOrderId() {
SegmentService service = segmentService(); // Note: Ceci devrait être un bean injecté
Result result = service.getId("Order");
if (result.getStatus() == Status.EXCEPTION) {
throw new RuntimeException("Failed to get ID from Leaf: " + result.getMessage());
}
return result.getId();
}
}
Exemple de test
package com.example.uid.test;
import com.example.uid.config.LeafConfig;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class LeafTest {
@Autowired
private LeafConfig leafConfig; // Injecter la configuration qui contient la logique pour obtenir l'ID
@Test
public void testGenerateOrderId() {
long orderId = leafConfig.getOrderId();
System.out.println("Generated Order ID: " + orderId);
}
}
Ces exemples fournissent une base pour implémenter des générateurs d'UID dans vos applications Java. Le projet Baidu est généralement apprécié pour sa simplicité et ses performances, tandis que Leaf de Meituan offre une appproche basée sur des segmetns gérés en base de données.