当前位置:网站首页>Distributed cluster architecture scenario optimization solution: distributed ID solution
Distributed cluster architecture scenario optimization solution: distributed ID solution
2022-07-28 06:03:00 【Brother Tao】
Distributed cluster architecture scenario optimization solution : Distributed ID Solution
Distributed ID Solution
Why do you need distributed ID( Global uniqueness in distributed cluster environment ID)

1、UUID( It can be used )
UUID Refer to Universally Unique Identifier, Translated into Chinese is Universal unique identification code
Produce repetition UUID Very low error rate , Therefore, there is no need to consider this problem .
import java.util.UUID;
public class UuidTest {
public static void main(String[] args) {
String uuid = UUID.randomUUID().toString();
System.out.println(uuid);
}
}

2、 Self augmentation of independent database ID
such as A The table is divided into A1 Table and A2 surface , Then we must not let A1 Table and A2 Tabular ID Self increasing , that ID How to get it ?
We can Create a separate Mysql database , Create a table in this database , This watch is ID Set to auto increment , other place It needs to be global and unique ID When , Just simulate this Mysql Simulate inserting a record into this table of the database , here ID Will be from increase , And then we can go through Mysql Of select last_insert_id() Get the self incrementing generated in the table just now ID.
such as , We created a database instance global_id_generator, A data table is created in it , Table structure is as follows Next :
-- ----------------------------
-- Table structure for DISTRIBUTE_ID
-- ----------------------------
DROP TABLE IF EXISTS `DISTRIBUTE_ID`;
CREATE TABLE `DISTRIBUTE_ID` (
`id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT ' Primary key ',
`createtime` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
In a distributed cluster environment, which application needs to obtain a globally unique distributed server ID When , You can use code to connect to this database instance , The implementation is as follows sql Sentence can be used .
insert into DISTRIBUTE_ID(createtime) values(NOW());
select LAST_INSERT_ID();
Be careful :
1) there createtime Field has no practical meaning , Is to insert a piece of data so that it can increase itself id.
2) Use independent Mysql Instance generation is distributed id, It's possible , But the performance and reliability are not good enough , Because you need code to connect to the database to get id, Performance cannot be guaranteed , in addition mysql The database instance is down , Then you can't get points type id 了 .
3) Some developers will use it to generate distributed id Of mysql The database is designed as a cluster architecture , In fact, this way now Basically not , Because it's too much trouble .
3、SnowFlake Snowflake algorithm ( It can be used , recommend )
The snowflake algorithm is Twitter A for generating distributed data is introduced ID The strategy of .
Snowflake algorithm is an algorithm , Based on this algorithm, we can generate ID, Generated ID It's a long type , So in Java In a long The type is 8 Bytes , Count it down 64bit, The following is a... Generated using the snowflake algorithm ID Binary form of :

in addition , All Internet companies have also encapsulated some distributed based on the above scheme ID generator , For example, Didi tinyid( Based on numbers Database implementation )、 Baidu uidgenerator( be based on SnowFlake) With meituan leaf( Based on database and SnowFlake) etc. .
Algorithm code :
/** * Official launch ,Scala Programming language to achieve * Java The elder used Java Language implements the snowflake algorithm */
public class IdWorker{
// Each of the following two 5 position , Add up to 10 Bit working machine id
private long workerId; // Work id
private long datacenterId; // data id
//12 Bit's serial number
private long sequence;
public IdWorker(long workerId, long datacenterId, long sequence){
// sanity check for workerId
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));
}
System.out.printf("worker starting. timestamp left shift %d, datacenter id bits %d, worker id bits %d, sequence bits %d, workerid %d",
timestampLeftShift, datacenterIdBits, workerIdBits, sequenceBits, workerId);
this.workerId = workerId;
this.datacenterId = datacenterId;
this.sequence = sequence;
}
// Initial timestamp
private long twepoch = 1288834974657L;
// The length is 5 position
private long workerIdBits = 5L;
private long datacenterIdBits = 5L;
// Maximum
private long maxWorkerId = -1L ^ (-1L << workerIdBits);
private long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
// Serial number id length
private long sequenceBits = 12L;
// Maximum serial number
private long sequenceMask = -1L ^ (-1L << sequenceBits);
// Work id The number of digits that need to be shifted left ,12 position
private long workerIdShift = sequenceBits;
// data id You need to shift the number of digits to the left 12+5=17 position
private long datacenterIdShift = sequenceBits + workerIdBits;
// Timestamps need to be shifted to the left 12+5+5=22 position
private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
// Last time stamp , The initial value is negative
private long lastTimestamp = -1L;
public long getWorkerId(){
return workerId;
}
public long getDatacenterId(){
return datacenterId;
}
public long getTimestamp(){
return System.currentTimeMillis();
}
// next ID generating algorithm
public synchronized long nextId() {
long timestamp = timeGen();
// Get the current time stamp. If it is less than the last time stamp , Indicates that there is an exception in timestamp acquisition
if (timestamp < lastTimestamp) {
System.err.printf("clock is moving backwards. Rejecting requests until %d.", lastTimestamp);
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds",
lastTimestamp - timestamp));
}
// Get the current time stamp if it is equal to the last time stamp
// explain : Still in the same millisecond , Add... To the serial number 1; Otherwise, the serial number is assigned to 0, from 0 Start .
if (lastTimestamp == timestamp) {
// 0 - 4095
sequence = (sequence + 1) & sequenceMask;
if (sequence == 0) {
timestamp = tilNextMillis(lastTimestamp);
}
} else {
sequence = 0;
}
// Refresh last timestamp value
lastTimestamp = timestamp;
/** * Return results : * (timestamp - twepoch) << timestampLeftShift) Indicates that the initial timestamp is subtracted from the timestamp , Move the corresponding digit to the left * (datacenterId << datacenterIdShift) It means that the data will be id Move the corresponding digit to the left * (workerId << workerIdShift) I'm going to work id Move the corresponding digit to the left * | It's a bitwise OR operator , for example :x | y, Only when x,y All for 0 It turns out to be 0, In other cases, the result is 1. * Because only the values in the corresponding bits are meaningful , All the others are 0, So the values of each part are calculated | You can get the final stitched id */
return ((timestamp - twepoch) << timestampLeftShift) |
(datacenterId << datacenterIdShift) |
(workerId << workerIdShift) |
sequence;
}
// Get the timestamp , And compare with the last timestamp
private long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
}
// Get the system timestamp
private long timeGen(){
return System.currentTimeMillis();
}
public static void main(String[] args) {
IdWorker worker = new IdWorker(21,10,0);
for (int i = 0; i < 100; i++) {
System.out.println(worker.nextId());
}
}
}
4、 With the help of Redis Of Incr Command to get globally unique ID( recommend )
Redis Incr The order will key The value of the number stored in is increased by one . If key non-existent , that key The value of is initialized to 0 , And then execute INCR operation .
<key,value>
<id,>
.incr(id) 1 2 3 4

Redis install :
Download from the official website redis-3.2.10.tar.gz
Upload to linux The server unzips tar -zxvf redis-3.2.10.tar.gz
cd Unzip the file directory , For decompressed redis Compile
make
then cd Get into src Catalog , perform make install
Modify the configuration file in the decompression directory redis.conf, Turn off protection mode

- stay src Execute under directory ./redis-server …/redis.conf start-up redis service
Java The code uses Jedis Client calls Reids Of incr Command to get a global id
- introduce jedis client jar
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
- Java Code ( Here we are connecting single nodes , Also do not use connection pooling )
import redis.clients.jedis.Jedis;
public class RedisGenerator {
public static void main(String[] args) {
Jedis jedis = new Jedis("192.168.2.3",6379);
Long id = jedis.incr("id");//<id,0>
System.out.println(id);
}
}
边栏推荐
猜你喜欢
随机推荐
Flex elastic box
(php毕业设计)基于php在线旅游网站管理系统获取
撞脸ins? Mars数字藏品平台探索数字藏品轻社交
【五】redis主从同步与Redis Sentinel(哨兵)
Flume安装及使用
单行函数,聚合函数课后练习
浅谈数字藏品与实体如何相互赋能
mysql5.6(根据.ibd,.frm文件)恢复单表数据
分布式锁-数据库实现
Assembly打包
反弹shell的N种姿势
MySQL view, stored procedure and stored function
7月7日国风廿四节气《小暑》来袭!!附..合..成..预..告..
On July 7, the national wind 24 solar terms "Xiaoshu" came!! Attachment.. cooperation.. completion.. advance.. report
CTF常见加密方式JS
Mysql的两种覆盖表中重复记录的方法
Installation and use of sqoop
内网信息收集总结
ES6 new data types -- > symbol, map, set
第七章 单行函数









