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个