Причина, по которой я написал эту статью, заключается в том, что, когда я сегодня работал над модулем заказов, я увидел, что правило формирования заказа, описанное в предыдущем PRD, состоит из года, месяца и дня + двухзначного идентификатора пользователя + цифры идентификатора предприятия. +Четырёхзначный автовозрастающий номер. Потом меня опровергли и внезапно поменяли на точное время + 4-значное автоувеличивающееся число, чем я еще больше разочаровался.
Давайте подумаем об этом. По моим общим заказам, это в основном 14-20 человек. (год, месяц, день, час, минута, секунда и случайное число) в основном состоят из 14 цифр. Хотя общие проекты не могут быть такими, как Taobao Double 11. Пиковая скорость оплаты достигает 100 000 заказов в секунду. Но я думаю, что это можно хотя бы учесть заранее. Думаю, Taobao, возможно, не осознавал, что в будущем он будет так хорошо развиваться.
Для достижения генерации бизнес-заказов. Я думаю, что он должен соответствовать как минимум следующим трем типам:
В сложных распределенных системах многие сценарии требуют сценариев с глобально уникальными идентификаторами. Обычно для предотвращения конфликтов можно рассматривать 36. Бит UUID, снежинка твиттера и т. д.
Но можете ли вы задуматься над этими вопросами?
После ознакомления с соответствующей информацией основными из них являются следующие:
Структура снежинки следующая (каждая часть разделяется знаком -):
Но в основном я хочу сказать, что алгоритм снежинки генерирует идентификаторы. Что касается причины, я тестировал другие и чувствую, что этот метод генерации мне нравится больше.
Алгоритм снежинки Правила следующие
Используйте 41 бит в качестве количества миллисекунд, 10 бит в качестве идентификатора машины (5 бит — это центр обработки данных, 5 бит — идентификатор машины) и 12 бит в качестве серийного номера в течение миллисекунд (это означает, что каждый узел может генерировать 4096 идентификаторов в миллисекунду). ), В конце также есть знаковый бит, который всегда равен 0.
0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000
Реализация алгоритма по сути представляет собой бинарную операцию.
В сумме получается ровно 64 бита, что является длинной формой. (Преобразовано в длину строки 18)
Идентификаторы, сгенерированные Snowflake, обычно сортируются по приращению времени, и во всей распределенной системе не будет конфликтов идентификаторов (отличающихся по центру обработки данных и идентификатору работника), а эффективность будет высокой. Говорят, что снежинка может генерировать 260 000 идентификаторов в секунду.
Ниже приведен код Частичная ссылка и сеть 1 миллион идентификаторов занимает 2 секунды
/**
* Created by youze on 18-7-5
*/
public class IdWorker {
/**
* начальная отметка времени
*/
private final static long START_STMP = 1530795377086L;
/**
* Количество битов, занимаемых каждой частью
*/
/**
* Количество цифр, занимаемых серийным номером
*/
private final static long SEQUENCE_BIT = 12;
/**
* Количество цифр, занимаемое идентификатором машины
*/
private final static long MACHINE_BIT = 5;
/**
* центр обработки Количество цифр, занимаемых данными
*/
private final static long DATACENTER_BIT = 5;
/**
* максимальная стоимость каждой части
*/
private final static long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT);
private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);
private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);
/**
* Смещение каждой части влево
*/
private final static long MACHINE_LEFT = SEQUENCE_BIT;
private final static long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;
private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT;
/**
* центр обработки данных
*/
private long datacenterId;
/**
* Идентификация машины
*/
private long machineId;
/**
* серийный номер
*/
private long sequence = 0L;
/**
* последняя временная метка
*/
private long lastStmp = -1L;
public IdWorker(long datacenterId, long machineId) {
if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0) {
throw new IllegalArgumentException("datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0");
}
if (machineId > MAX_MACHINE_NUM || machineId < 0) {
throw new IllegalArgumentException("machineId can't be greater than MAX_MACHINE_NUM or less than 0");
}
this.datacenterId = datacenterId;
this.machineId = machineId;
}
/**
* Создать следующий индивидуальныйID
* @return
*/
public synchronized long nextId() {
long currStmp = getNewstmp();
if (currStmp < lastStmp) {
throw new RuntimeException("Clock moved backwards. Refusing to generate id");
}
if (currStmp == lastStmp) {
//в течение тех же миллисекунд,серийный номерсамовозрастающий
sequence = (sequence + 1) & MAX_SEQUENCE;
//Количество последовательностей за одну миллисекунду достигло максимума
if (sequence == 0L) {
currStmp = getNextMill();
}
} else {
//В пределах разных миллисекунд,серийный номер установлен на 0
sequence = 0L;
}
lastStmp = currStmp;
return (
//Часть отметки времени
currStmp - START_STMP) << TIMESTMP_LEFT
//центр обработки данныхчасть | datacenterId << DATACENTER_LEFT
//Идентификация машинычасть
| machineId << MACHINE_LEFT
//серийный номерчасть
| sequence;
}
private long getNextMill() {
long mill = getNewstmp();
while (mill <= lastStmp) {
mill = getNewstmp();
}
return mill;
}
private long getNewstmp() {
return System.currentTimeMillis();
}
public static void main(String[] args) {
IdWorker snowFlake = new IdWorker(2, 3);
long start = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
System.out.println(snowFlake.nextId());
}
System.out.println(System.currentTimeMillis() - start);
}
}
最后大家可以看этотТакже есть более подробное объяснение