При разработке серверной системы, чтобы адаптироваться к крупным и одновременным запросам данных, нам часто необходимо хранить данные асинхронно, особенно при работе в распределенной системе. В настоящее время мы не можем дождаться получения базы данных вставки, чтобы вернуть автоматический идентификатор. Вместо этого нам нужно генерировать глобальный уникальный идентификатор перед вставкой базы данных, используя глобальный уникальный идентификатор. На игровом сервере глобальный уникальный идентификатор может использоваться для будущих комбинаций серверов, и не будет никаких ключевых конфликтов. В будущем, в случае роста бизнеса, база данных и сплит -таблицы могут быть реализованы. Например, элементы пользователя должны быть размещены в одном и том же осколках, и этот осколок может быть определен на основе значения диапазона идентификатора пользователя, например, идентификатор пользователя с идентификатором пользователя, более 1000 и менее 100000 в осколках. В настоящее время обычно используются следующие:
1. Java's собственная Uuid.
Uuid.randomuuid (). ToString () может генерироваться локально через сервисную программу, а генерация ID не зависит от реализации базы данных.
Преимущества:
Создать идентификатор локально и не требует удаленных вызовов.
Мир - единственный, который не повторяется.
Горизонтальная способность расширения очень хорошая.
Недостатки:
Идентификатор имеет 128 бит, что занимает большое пространство и необходимо хранить в виде типа струны, а эффективность индексации чрезвычайно низкая.
Сгенерированный идентификатор не содержит метки времени, и тенденция не может быть гарантированно увеличиться. Трудно полагаться при разделении баз данных баз данных.
2. Метод увеличения на основе Redis
Сам Redis управляется однопоточным, и Incer обеспечивает атомно увеличенную работу. Он также поддерживает установку дополнительного размера шага.
Преимущества:
Это легко развернуть и легко использовать. Вам нужно только позвонить в Redis API.
Несколько серверов могут предоставить услугу REDIS для сокращения времени разработки общих данных.
Redis может быть развернут в кластерах, чтобы решить проблему единой точки отказа.
Недостатки:
Если система слишком велика, запрос нескольких услуг в Redis одновременно приведет к узким месту производительности.
3. Решение от мерцания
Это решение основано на идентификаторе автоматического интеграмента базы данных, который использует отдельную базу данных, специально предназначенные для генерации идентификаторов. Вы можете найти детали в Интернете. Я лично думаю, что это довольно неприятно использовать, и его не рекомендуется использовать его.
4. Снежнак в Твиттере
Snowflake - это алгоритм генерации распределенного идентификатора, который является открытым исходным кодом в Twitter. Его основная идея состоит в том, чтобы генерировать идентификатор длинного типа, используя 41-битное в качестве количества миллисекундов, 10-бит в качестве номера машины и 12-битный номер в качестве серийного номера в течение миллисекундов. Этот алгоритм теоретически может генерировать до 1000*(2^12) идентификаторов в секунду за машину, которая составляет около 400 Вт, что может полностью удовлетворить потребности бизнеса.
Согласно идее алгоритма снежинки, мы можем генерировать нашу собственную глобальную уникальную идентификацию на основе наших бизнес -сценариев. Поскольку длина длинного типа в Java составляет 64 бит, идентификатор, который мы разработали, необходимо контролировать на 64 бит.
Преимущества: высокая производительность, низкая задержка; независимое приложение; упорядочен по времени.
Недостатки: требуется независимая разработка и развертывание.
Например, идентификатор, который мы разработали, содержит следующую информацию:
| 41 бит: временная метка | 3 бита: зона | 10 бит: номер машины | 10 битов: серийный номер |
Код Java, который генерирует уникальный идентификатор:
/*** Пользовательский генератор идентификатора* Правила генерации идентификаторов: ID до 64 бит ** | 41 бит: временная метка (MS) | 3 бита: зона (компьютерная комната) | 10 бит: номер машины | 10 бит: серийный номер |*/public class GameUuid {// Справочное время частное длинное двойное дв. = 1288834974657L; // Чт, 04 ноября 2010 г. 01:42:54 GMT // Цифры флага региона Частные окончательные статические длинные регионадбиты = 3L; // Цифры идентификации машины Частные окончательные статические длинные рабочие Maximum value of machine ID private final static long maxWorkerId = -1L ^ (-1L << workerIdBits);// Maximum value of serial number ID private final static long sequenceMask = -1L ^ (-1L << sequenceBits);// The machine ID is shifted 10 bits to the left private final static long workerIdShift = sequenceBits;// The service ID is shifted left by 20 bits private final Статический длинный регион wareIdshift = sequenceBits + рабочие труды; // Время сдвинуто влево на 23 бита частного окончательного статического длинного времени. частный статический длинный LongttimestAmp = -1L; частная длинная последовательность = 0l; частный финальный долгий рабочий; Частный финальный длинный регион; public GameUuid (Long Workerid, Long RegionId) {// Если вне диапазона, исключение добавляется в IF (WorkerId> MaxWorkerId || работник <0) {бросить новое allosalArgumentException («Идентификатор работника не может быть больше, чем %d или меньше 0»);} if (regionid> maxregionid | %d или меньше 0 ");} this.WorkerId = работник; this.regionid = regionId;} public gameUuid (long kripeerid) {// Если из диапазона выброшен, если (работник> maxworkerid || this.nextid (false, 0);}/*** Фактический код, сгенерированный @param ispadding* @param busid* @return*/private synchronized long nextid (boolean ispadding, long busid) {long TimeStamp = timegen (); long paddingnum = regionId; if (iSpadding) {paddingNum = busId; if -strytempt {timeSt -ytempt {timeSt -ytempt) Новое исключение («часы перенесены назад. Отказ генерировать ID для" + (lasttimestamp - timestamp) + "миллионы секунд");} catch (Exception e) {e.printstacktrace ();}} // Если время последнего поколения такое же, как и в текущем времени, если (lasttimeStamp = timeStemper) в то же время, и тот же Millisecond, iftiveMpmAmp == timeStemp). Сама, поскольку последовательность составляет всего 10 бит, она объединяется с SequenceSak и удаляет последовательность с высоким BIT = (последовательность + 1) и SequenceMask; // Судить, переполняется ли она, то есть она превышает 1024 в каждой миллисекунду. Когда он составляет 1024, он объединяется с SequenceMask, а последовательность равна 0if (sequence == 0) {// Spin ожидает до следующего Millisecond TimeStamp = tailNextmillis (LastTimeStamp);}} else {// Если последовательность отличается от времени последнего поколения, отзывая последовательность, которая начинается с следующей Millisecond, и последовательность снова начинается. // Чтобы убедиться, что мантисса является более случайной, установите случайное число в последнем битовом последовательности = new SecureRandom (). NextInt (10);} LastTimestAmp = TimeStamp; return ((TimeStamp - Twepoch) << timestampleftsHift) | (paddingnum << regionIdShift) | (Рабочий << Рабочим переоборудованием) | Sequence;} // Предотвращение времени генерации меньше, чем предыдущее время (из -за таких проблем, как NTP -обратный вызов), и поддерживать инкрементную тренд. PRIVATE LONGNEXTMILLIS (FINAL LOND THEARTTIMESTAMP) {Long TimeStamp = This.TimeGen (); while (TimeStamp <= lastTimeStamp) {timeStampecemance = thiteMagn () returnamp; TimeGen () {return System.currentTimeMiLlis ();}}Некоторые вещи следует отметить при использовании пользовательских методов:
Чтобы поддерживать тенденцию к росту, необходимо избежать времени некоторых серверов на раннем этапе и некоторых серверов поздно, поэтому необходимо контролировать время всех серверов, и время, когда сервер NTP Time вызывает обратно на сервер; При пересечении миллисекундов серийный номер всегда достигает 0, что сделает больше идентификаторов с серийным номером 0, что приведет к неравномерным идентификаторам после модуляции, поэтому серийный номер не принадлежит 0 каждый раз, а случайное число от 0 до 9.
Мы можем выбрать методы, упомянутые выше в соответствии с нашими потребностями. В разработке игрового сервера вы можете выбрать в соответствии со своим собственным типом игры, таким как мобильные игры, и вы можете использовать простой метод Redis, который прост и не прост в ошибках. Поскольку количество новых идентификаторов, созданных отдельными серверами в такой игре, не слишком большое, оно может полностью удовлетворить потребности. Для крупных мировых игровых серверов они в основном распределены, так что вы можете использовать снежинка. Приведенный выше код снежинки является лишь примером и должен быть настроен в соответствии с вашими потребностями, поэтому существует дополнительный объем разработки, и вы должны обратить внимание на вышеуказанные меры предосторожности.
Выше приведено краткое изложение методов использования кода Java для реализации игрового сервера для создания глобального уникального идентификатора на основе кода Java. Я надеюсь, что это будет полезно для всех. Если у вас есть какие -либо вопросы, пожалуйста, оставьте мне сообщение, и редактор ответит всем вовремя. Большое спасибо за вашу поддержку сайту wulin.com!