Компонент для генерации распределённых серийных номеров
В эпоху микросервисов нам необходимо создавать непрерывные и понятные серийные номера, такие как номера заказов. Это становится довольно хлопотно. Здесь я предлагаю два широко используемых решения для создания компонента распределённой генерации серийных номеров:
Проект состоит из следующих компонентов:
<dependency>
<groupId>com.xuanner</groupId>
<artifactId>xsequence-core</artifactId>
<version>1.6</version>
</dependency>
v1.0 Добавлена новая функция: поддержка генерации серийных номеров с использованием базы данных. Документация: https://my.oschina.net/u/1271235/blog/1808103. Дата обновления: 2018/05/07.
v1.1 Добавлена новая функция: поддержка генерации серийных номеров с помощью Redis. Документация: https://my.oschina.net/u/1271235/blog/1809437. Дата обновления: 2018/05/09.
v1.2 Добавлена новая функция: поддержка алгоритма «снежинка». Документация: https://my.oschina.net/u/1271235/blog/1812305. Дата обновления: 2018/05/14.
v1.3 Добавлены новые функции: — дружественный API для минимизации взаимодействия с базовой реализацией; — результаты сравнительного анализа трёх реализаций с использованием JMH; — оптимизация алгоритма «снежинка», включая поддержку потоковой безопасности. Дата обновления: 2018/05/31.
v1.4 Никаких изменений не было внесено, но предыдущая версия была недоступна для загрузки через Maven. Версия 1.4 позволяет скачивать её без проблем. Информация: https://www.oschina.net/news/96840/xsequence-1-4-released.
v1.5 Добавлен класс UUIDUtils для генерации UUID.
v1.6 Поддерживает указание начального значения, например, если требуется начать с 60 000, можно установить stepStart=60000.
Подробные отчёты о тестах можно найти в папке jmh в каталоге doc. Здесь представлено краткое описание:
Конфигурация серверов для баз данных и Redis: CPU: одно ядро; ОЗУ: 1 ГБ; Операционная система: CentOS 6.8 64 бит; Широкополосный доступ: 1 Мбит/с.
Алгоритм реализации | ops/s (количество генерируемых серийных номеров в секунду) | Примечания |
---|---|---|
Получение интервала с использованием базы данных | 314 754,083 ± 1 089 932,384 ops/s | Mysql развёрнут на одном сервере, параметры подключения указаны в тестовом пакете, шаг равен 1000 |
Получение интервала с помощью Redis | 244 326,027 ± 518 524,654 ops/s | Redis развёрнут на одном сервере, шаг равен 1000 |
Использование алгоритма «снежинка» | 4 076 501,612 ± 449 55,567 ops/s | Недостатком является длина серийного номера |
Создание уникальных идентификаторов с помощью класса UUIDUtils | 3 368 986,174 ± 724 159,973 ops/s | Недостаток — длина 32 бита и отсутствие порядка |
Заключение: Производительность методов, основанных на использовании шага для генерации серийных номеров, сильно зависит от конкретной конфигурации базы данных или Redis, а также от размера шага. В этом примере использовались относительно слабые аппаратные ресурсы. Однако даже при таких условиях генерация серийных номеров остаётся возможной. Алгоритм «снежинка» демонстрирует высокую производительность, которая практически не зависит от аппаратных ресурсов. Его потенциал для оптимизации ещё не исчерпан. Метод с использованием Redis показывает наибольший потенциал для улучшения производительности.
(1) Использование метода получения интервала с базой данных:
public class DbTest_Api extends BaseTest {
private Sequence sequence;
@Before
public void setup() {
// Данные источника
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl("xxx");
dataSource.setUsername("xxx");
dataSource.setPassword("xxx");
dataSource.setMaxActive(300);
dataSource.setMinIdle(50);
dataSource.setInitialSize(2);
dataSource.setMaxWait(500);
/**
* Параметры пояснения следующие:
* dataSource: источник данных базы данных
* bizName: серийный номер для конкретного бизнеса
* step: [необязательно] по умолчанию 1000, то есть каждый раз, когда redis получает значение шага, оно устанавливается в соответствии с конкретным бизнес-трафиком. Чем больше значение, тем лучше производительность. Однако риск нарушения серийного номера также увеличивается.
*/
sequence = DbSeqBuilder.create().dataSource(dataSource).bizName("userId").build();
}
@Test
public void test() {
long start = System.currentTimeMillis();
for (int i = 0; i < 100; i++) {
System.out.println("++++++++++id:" + sequence.nextValue());
}
System.out.println("интервал времени:" + (System.currentTimeMillis() - start));
}
}
(2) Использование метода получения интервала с Redis:
/**
* Параметры пояснения следующие:
* ip: IP-адрес соединения redis
* порт: порт соединения redis
* auth: если redis настроен с паролем, его необходимо настроить, иначе нет необходимости настраивать
* bizName: конкретный серийный номер бизнеса
* step: [необязательно] по умолчанию 1000, то есть каждый раз, когда redis получает значение шага, оно устанавливается в соответствии с конкретным бизнес-трафиком. Чем больше значение, тем лучше производительность. Однако риск нарушения серийного номера также увеличивается.
*/
sequence = RedisSeqBuilder.create().ip("xxx").port(6379).auth("xxx").step(1000).bizName(
"userId").build();
(3) Использование алгоритма «снежинка»:
/**
* Параметры объяснения следующие:
* datacenterId: обычно можно установить идентификатор центра обработки данных, значение может быть установлено только между [0-31]
* workerId: обычно устанавливается идентификатор хоста, значение может быть установлено только между [0-31]
* Только эти два значения используются для обеспечения уникальности сервера.
*/
sequence = SnowflakeSeqBuilder.create().datacenterId(1).workerId(2).build();
(4) Использование класса UUIDUtils:
UUIDUtils.uuid()
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )