Summary of ID generation scheme

Distributed ID generation scheme

  • UUID
  • database self-increment
  • number segment mode
  • Redis implementation
  • Snowflake algorithm (SnowFlake)
  • Baidu Uidgenerator
  • Meituan Leaf
  • Didi TinyID

This article focuses on Leaf and TinyID that can auto-increment ID

number segment mode

This mode is also a method for generating distributed IDs. The idea is to obtain a range of numbers from the database, such as [1,1000], generate auto-increment IDs from 1 to 1000, and load them into memory. The table structure is as follows :

CREATE TABLE id_generator (
  id int(10) NOT NULL,
  max_id bigint(20) NOT NULL COMMENT '当前最大id',
  step int(20) NOT NULL COMMENT '号段的布长',
  biz_type int(20) NOT NULL COMMENT '业务类型',
  version int(20) NOT NULL COMMENT '版本号',
  PRIMARY KEY (`id`)
) 


biz_type: different business types
max_id: the current largest id
step: the step size of the representative number segment
version: the version number, just like MVCC, can be understood as an optimistic lock
, wait for the ID to be used, then go to the database to get it, and then change the maximum value

update id_generator set max_id = #{max_id+step}, version = version + 1 where version = # {version} and biz_type = XXX

Advantages: There are relatively mature solutions, such as Baidu Uidgenerator, Meituan Leaf
Disadvantages: Depends on database implementation

Meituan Leaf

Leaf provides two ways to generate IDs: number segment mode (Leaf-segment) and snowflake mode (Leaf-snowflake). You can enable both methods at the same time, or you can specify a method to enable. The default is to disable the two methods.

git location

GitHub - Meituan-Dianping/Leaf: Distributed ID Generate Service

Introduction document

https://github.com/Meituan-Dianping/Leaf/blob/master/README_CN.md

Create data table

CREATE DATABASE leaf
CREATE TABLE `leaf_alloc` (
  `biz_tag` varchar(128)  NOT NULL DEFAULT '',
  `max_id` bigint(20) NOT NULL DEFAULT '1',
  `step` int(11) NOT NULL,
  `description` varchar(256)  DEFAULT NULL,
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`biz_tag`)
) ENGINE=InnoDB;

insert into leaf_alloc(biz_tag, max_id, step, description) values('leaf-segment-test', 1, 2000, 'Test leaf Segment Mode Get Id')

get item

git clone [email protected]:Meituan-Dianping/Leaf.git

Upgrade mysql driver

If the connection is above mysql1.8, you need to upgrade the mysql driver, respectively

Leaf/poe.xml and leaf_core/poe.xml

# Leaf/poe.xml
<mybatis-spring.version>1.2.5</mybatis-spring.version>

#leaf_core/poe.xml
 <dependency>
     <groupId>mysql</groupId>
     <artifactId>mysql-connector-java</artifactId>
      <version>8.0.25</version>
 </dependency>

Change setting

The following is the configuration of the number segment mode

leaf_server/resouces/leaf.properties

leaf.name=com.sankuai.leaf.opensource.test
leaf.segment.enable=true
leaf.jdbc.url=jdbc:mysql://127.0.0.1:3306/leaf?useSSL=false
leaf.jdbc.username=root
leaf.jdbc.password=123456

leaf.snowflake.enable=false
#leaf.snowflake.zk.address=
#leaf.snowflake.port=

Pack

cd leaf
mvn clean install -DskipTests

run

cd leaf-server
#mvn method
mvn spring-boot:run
#script method
sh deploy/run.sh 

test

#segment
curl http://localhost:8080/api/segment/get/leaf-segment-test
#snowflake
curl http://localhost:8080/api/snowflake/get/test
Monitoring page
number segment mode: http:// localhost:8080/cache

#Note that after adding a biz_type, it will take effect after 10s .

Didi TinyID

github location

GitHub - request/request: ID Generator identification

 Introduction document

Home · Wikipedia · GitHub

get item

git clone https://github.com/didi/tinyid.git

Create data table

tinyid-server/db.sql

CREATE TABLE `tiny_id_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
  `biz_type` varchar(63) NOT NULL DEFAULT '' COMMENT '业务类型,唯一',
  `begin_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '开始id,仅记录初始值,无其他含义。初始化时begin_id和max_id应相同',
  `max_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '当前最大id',
  `step` int(11) DEFAULT '0' COMMENT '步长',
  `delta` int(11) NOT NULL DEFAULT '1' COMMENT '每次id增量',
  `remainder` int(11) NOT NULL DEFAULT '0' COMMENT '余数',
  `create_time` timestamp NOT NULL DEFAULT '2010-01-01 00:00:00' COMMENT '创建时间',
  `update_time` timestamp NOT NULL DEFAULT '2010-01-01 00:00:00' COMMENT '更新时间',
  `version` bigint(20) NOT NULL DEFAULT '0' COMMENT '版本号',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uniq_biz_type` (`biz_type`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT 'id信息表';

CREATE TABLE `tiny_id_token` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',
  `token` varchar(255) NOT NULL DEFAULT '' COMMENT 'token',
  `biz_type` varchar(63) NOT NULL DEFAULT '' COMMENT '此token可访问的业务类型标识',
  `remark` varchar(255) NOT NULL DEFAULT '' COMMENT '备注',
  `create_time` timestamp NOT NULL DEFAULT '2010-01-01 00:00:00' COMMENT '创建时间',
  `update_time` timestamp NOT NULL DEFAULT '2010-01-01 00:00:00' COMMENT '更新时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT 'token信息表';

INSERT INTO `tiny_id_info` (`id`, `biz_type`, `begin_id`, `max_id`, `step`, `delta`, `remainder`, `create_time`, `update_time`, `version`)
VALUES
	(1, 'test', 1, 1, 100000, 1, 0, '2018-07-21 23:52:58', '2018-07-22 23:19:27', 1);

INSERT INTO `tiny_id_info` (`id`, `biz_type`, `begin_id`, `max_id`, `step`, `delta`, `remainder`, `create_time`, `update_time`, `version`)
VALUES
	(2, 'test_odd', 1, 1, 100000, 2, 1, '2018-07-21 23:52:58', '2018-07-23 00:39:24', 3);


INSERT INTO `tiny_id_token` (`id`, `token`, `biz_type`, `remark`, `create_time`, `update_time`)
VALUES
	(1, '0f673adf80504e2eaa552f5d791b644c', 'test', '1', '2017-12-14 16:36:46', '2017-12-14 16:36:48');

INSERT INTO `tiny_id_token` (`id`, `token`, `biz_type`, `remark`, `create_time`, `update_time`)
VALUES
	(2, '0f673adf80504e2eaa552f5d791b644c', 'test_odd', '1', '2017-12-14 16:36:46', '2017-12-14 16:36:48');

Change setting

cd tinyid-server/src/main/resources/offline
vi application.properties

server.port=9999
server.context-path=/tinyid

batch.size.max=100000

#datasource.tinyid.names=primary
#如果希望数据库能够高可用,可以设置多个不同节点,两个节点上的数据保持一致。
#注意添加配置的时候,多个节点都要添加
datasource.tinyid.names=primary,secondary
datasource.tinyid.type=org.apache.tomcat.jdbc.pool.DataSource

datasource.tinyid.primary.driver-class-name=com.mysql.jdbc.Driver
datasource.tinyid.primary.url=jdbc:mysql://localhost:3306/db1?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8
datasource.tinyid.primary.username=root
datasource.tinyid.primary.password=123456
#datasource.tinyid.primary.testOnBorrow=false
#datasource.tinyid.primary.maxActive=10

datasource.tinyid.secondary.driver-class-name=com.mysql.jdbc.Driver
datasource.tinyid.secondary.url=jdbc:mysql://localhost:3306/db2?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8
datasource.tinyid.secondary.username=root
datasource.tinyid.secondary.password=123456
datasource.tinyid.secondary.testOnBorrow=false
datasource.tinyid.secondary.maxActive=10


Pack

cd tinyid

mvn clean install -DskipTests

#or

cd tinyid-server/
sh build.sh offline

run

cd tinyid-server/
#sh build.sh offline
java -jar output/tinyid-server-xxx.jar

test

nextId:
curl 'http://localhost:9999/tinyid/id/nextId?bizType=test&token=0f673adf80504e2eaa552f5d791b644c'
response:{"data":[2],"code":200,"message":""}

nextId Simple:
curl 'http://localhost:9999/tinyid/id/nextIdSimple?bizType=test&token=0f673adf80504e2eaa552f5d791b644c'
response: 3

with batchSize:
curl 'http://localhost:9999/tinyid/id/nextIdSimple?bizType=test&token=0f673adf80504e2eaa552f5d791b644c&batchSize=10'
response: 4,5,6,7,8,9,10,11,12,13

Get nextId like 1,3,5,7,9...
bizType=test_odd : delta is 2 and remainder is 1
curl 'http://localhost:9999/tinyid/id/nextIdSimple?bizType=test_odd&batchSize=10&token=0f673adf80504e2eaa552f5d791b644c'
response: 3,5,7,9,11,13,15,17,19,21

 

client use

client packaging

cd tinyid

mvn clean install -DskipTests

#tinyid-client\target\ tinyid-client-0.1.0-SNAPSHOT.jar is the client that can be used

client profile

tinyid_client.properties

Put tinyid_client.properties under resources

tinyid.server=localhost:9999
tinyid.token=0f673adf80504e2eaa552f5d791b644c

use

public class ClientTest {
    @Test
    public void testNextId() {
        for (int i = 0; i < 100000; i++) {
            Long id = TinyId.nextId("test_odd");
            System.out.println("current id is: " + id);
        }
    }
}

Note: Every time you restart the program, the id will add a step forward, no matter whether you have used it up or not, if the program restarts frequently, the step should not be set too large. But the step should not be set too small, otherwise the interaction with the database will be too frequent.

source:

Summary of 8 distributed ID generation schemes 

Guess you like

Origin blog.csdn.net/csdncjh/article/details/132112737