Distributed - high concurrent distributed global ID generation strategy

A distributed global ID generation strategy, which has several

1.1, using the globally unique UUID generated order number advantages and disadvantages

Disadvantages:

  •   No sorting, no guarantee that trend increments;
  •   UUID often use strings to store, query efficiency ratio is low;
  • Storage space is relatively large, if it is a massive database, we need to consider storage issues.

1.2, based on the database increment

Case: No. generate orders based on a database increment or sequence

Realization of ideas: use database auto-increment serial numbers or ways to achieve order number.

Disadvantages:

  •  Different different database syntax and implementation;
  • In the case of a single database or a master or a separate multi-read from only one master library may be generated. The risk of single point of failure;
  • Points table and warehouses when there will be trouble.

1.3, consider how the database cluster database increment uniqueness

Queries from the growing step : the LIKE SHOW VARIABLES 'auto_inc %'

Modify step increment of: the SET @@ auto_increment_increment = 10 ;

Start value modification: the SET @@ auto_increment_offset =. 5;

Suppose you have two mysql database server:

① node increment  1357911 ....

From node ② increase  24681012 ....

Note: After initially set up each node spacing increment way to determine the number of clusters mysql Well, we can not extend a new mysql, otherwise step of generating rules may vary.

1.4, based on Redis generate the global id generation Strategies

Because Redis is single-threaded, inherently guarantee atomicity, INCR and atomic operations may be used to achieve INCRBY Redis.

advantage:

  • It does not depend on a database, the database superior performance;
  • Digital ID natural sorting, pagination or the results need to sort helpful.

(1) Note: In the case of Redis cluster also need to set a different incremental steps , while key must be set expiration date.

(2) a cluster: You can use Redis cluster to obtain higher throughput. If the cluster has a 5 sets the Redis . Can initialize each Redis values are 1,2,3,4,5 , then the step is 5 . Each Redis generated ID is:

A:1,6,11,16,21
B:2,7,12,17,22
C:3,8,13,18,23
D:4,9,14,19,24
E:5,10,15,20,25

(3) usage scenarios:

Compare suitable for use Redis to generate daily from 0 serial began. Such as order number = Date + day since growth numbers. Day can Redis generated in a Key , using INCR accumulated. If the generated order number exceeds the growth increment, you can use the prefix + from increased + and set the expiration date.

(4) Integration (example generates order numbers) SpringBoot

.yml 配置:

spring:
  redis:
    database: 1
    host: 111.231.55.110
    port: 6379
    password: 123456
    jedis:
      pool:
        max-active: 8
        max-wait: -1
        max-idle: 8
        min-idle: 0
    timeout: 10000
    

OrderController:

// 基于Redis 实现分布式全局id
@RestController
public class OrderController {
	@Autowired
	private RedisTemplate redisTemplate;

	/**
	 * 15 18位 前缀=当前日期=2018112921303030-5位自增id(高并发请下 先天性安全) 00001<br>
	 * 00010<br>
	 * 00100<br>
	 * 01000<br>
	 * 11000<br>
	 * 在相同毫秒情况下,最多只能生成10万-1=99999订单号<br>
	 * 假设:双11每毫秒99万笔 <br>
	 * 提前生成号订单号码存放在redis中
	 * 
	 * 9.9万*1000=900万<br>
	 * 考虑失效时间问题 24小时
	 * 
	 * 
	 * @return
	 */
	@RequestMapping("/order")
	public String order(String key) {
		RedisAtomicLong redisAtomicLong = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
		for (int i = 0; i < 100; i++) {
			long incrementAndGet = redisAtomicLong.incrementAndGet();
			// 5位
			String orderId = prefix() + "-" + String.format("%1$05d", incrementAndGet);
			String orderSQL = "insert into orderNumber value('" + orderId + "');";
			System.out.println(orderSQL);
		}

		return "success";
	}
    //设置步长
	@RequestMapping("/order1")
	public String order1(String key) {
		RedisAtomicLong redisAtomicLong = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
		// // 起始值
		// redisAtomicLong.set(10);
		// 设置步长加10
		redisAtomicLong.addAndGet(9);
		return redisAtomicLong.incrementAndGet() + "";
	}

	public static String prefix() {
		String temp_str = "";
		Date dt = new Date();
		// 最后的aa表示“上午”或“下午” HH表示24小时制 如果换成hh表示12小时制
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
		temp_str = sdf.format(dt);
		return temp_str;
	}

}

1.5, Twitter of Snowflake (snow) algorithm to generate the global id (best performance)

The result is a long type of ID, its core idea is :

Random high + milliseconds + machine code (data center + machine ID ) +10 bit number of water

Github Address : HTTPS : // github.com/twitter-archive/snowflake

Snowflake principle :

snowflake生产的ID是一个18位的long型数字,二进制结构表示如下(每部分用-分开):
0 - 00000000 00000000 00000000 00000000 00000000 0 - 00000 - 00000 - 00000000 0000
第一位未使用,接下来的41位为毫秒级时间(41位的长度可以使用69年,从1970-01-01 08:00:00),然后是5位datacenterId(最大支持2^5=32个,二进制表示从00000-11111,也即是十进制0-31),和5位workerId(最大支持2^5=32个,原理同datacenterId),所以datacenterId*workerId最多支持部署1024个节点,最后12位是毫秒内的计数(12位的计数顺序号支持每个节点每毫秒产生2^12=4096个ID序号).所有位数加起来共64位,恰好是一个Long型(转换为字符串长度为18).单台机器实例,通过时间戳保证前41位是唯一的,分布式系统多台机器实例下,通过对每个机器实例分配不同的datacenterId和workerId避免中间的10位碰撞。最后12位每毫秒从0递增生产ID,再提一次:每毫秒最多生成4096个ID,每秒可达4096000个

1.6, based on Zookeeper generate the global id

1.7, SpringCloud way

Published 52 original articles · won praise 116 · views 50000 +

Guess you like

Origin blog.csdn.net/RuiKe1400360107/article/details/103931821