Я просматриваю сеть, пытаясь найти решение, которое позволит нам генерировать уникальные идентификаторы в региональной среде.
Я рассмотрел следующие варианты (среди прочего):
SNOWFLAKE (по щебетать)
UUID
АВТОИНКРИМЕНТ В ОТНОШЕНИИ БАЗЫ ДАННЫХ, КАК MYSQL
АВТОИНКРИМЕНТ В НЕЗАВИСИМОЙ БАЗЕ ДАННЫХ, КАК СОТРУДНИЧЕСТВО
Допустим, что у нас есть кластеры, состоящие из 10 узлов Couchbase и 10 приложений в 5 разных регионах (Африка, Европа, Азия, Америка и Океания). Это делается для обеспечения того, чтобы контент обслуживался из ближайшего к пользователю местоположения (для повышения скорости) и обеспечения избыточности в случае бедствий и т. Д.
Теперь задача состоит в том, чтобы генерировать идентификаторы, которые не сталкиваются, когда происходит репликация (и балансировка), и я думаю, что это может быть достигнуто за 3 шага:
Шаг 1
Всем регионам будут назначены целые идентификаторы (уникальные идентификаторы):
Шаг 2
Назначьте идентификатор каждому узлу приложения, который добавлен в кластер, имея в виду, что в одном кластере может быть до 99 999 серверов (хотя я сомневаюсь: как безопасная мера предосторожности). Это будет выглядеть примерно так (поддельные IP-адреса):
Обратите внимание, что все они находятся в одном кластере, поэтому вы можете иметь узел 00001 для каждого региона.
Шаг 3
Для каждой записи, вставленной в базу данных, для ее идентификации будет использоваться инкрементированный идентификатор, и так оно и будет работать:
Couchbase предлагает функцию инкремента, которую мы можем использовать для создания идентификаторов внутри кластера. Чтобы обеспечить избыточность, в кластере будут созданы 3 реплики. Поскольку они находятся в одном и том же месте, я думаю, что следует быть уверенным в том, что если весь кластер не работает, один из узлов, ответственных за это, будет доступен, в противном случае количество реплик может быть увеличено.
Объединяя все это
Скажем, пользователь подписывается из Европы: узел приложения, обслуживающий запрос, получит код региона (в этом случае 4), получит свой собственный идентификатор (скажем, 00005 ), а затем получит увеличенный идентификатор ( 1 ) из Couchbase (из того же кластер).
В итоге мы 4, 00005,1
3 компонента: 4, 00005,1
. Теперь, чтобы создать идентификатор из этого, мы можем просто присоединить эти компоненты к 4.00005.1
. Чтобы сделать его еще лучше (я не слишком уверен в этом), мы можем объединить (не добавлять их) компоненты, чтобы в итоге: 4000051
.
В коде это будет выглядеть примерно так:
$id = '4'.'00005'.'1';
NB: Не $id = 4+00005+1;
,
Pros
Cons
Я знаю, что каждое решение имеет недостатки и, возможно, больше того, что мы видим на поверхности. Можете ли вы выявить какие-либо проблемы с помощью всего этого подхода?
Заранее спасибо за вашу помощь 🙂
РЕДАКТИРОВАТЬ
Как предложил @DaveRandom, мы можем добавить 4-й шаг:
Шаг 4
Мы можем просто сгенерировать случайное число и добавить его к идентификатору, чтобы предотвратить предсказуемость. Эффективно, вы получите что-то вроде этого:
4000051357
вместо 4000051
.
Я думаю, что это выглядит довольно солидно. Каждый регион поддерживает согласованность, и если вы используете XDCR, конфликтов не возникает. INCR является атомарным внутри кластера, поэтому у вас не будет проблем. На самом деле вам не требуется часть машинного кода. Если все серверы приложений в регионе подключены к одному и тому же кластеру, это не имеет значения для инфиниции его части 00001. Если это полезно для вас по другим причинам (какая-то аналитика), то во что бы то ни стало, но это необязательно.
Таким образом, это может быть просто «4». 1 '(используя ваш пример)
Можете ли вы привести мне пример того, какая «сортировка» вам нужна?
Во-первых : один недостаток добавления энтропии (и я не уверен, зачем вам это нужно), вы не можете легко перебирать идентификационную коллекцию.
Например : если идентификаторы от 1 до 100, которые вы узнаете из простого запроса GET на клавише счетчика, вы можете назначать задания по группам, эта задача занимает 1-10, следующие 11-20 и т. Д., А работники может выполняться параллельно. Если вы добавите энтропию, вам нужно будет использовать Map / Reduce View, чтобы вытащить коллекцию, так что вы теряете преимущество шаблона значения ключа.
Во-вторых : поскольку вы заинтересованы в удобочитаемости, полезно добавить идентификатор типа документа / объекта, и это можно использовать в Map / Reduce Views (или вы можете использовать ключ json для определения этого).
Пример: 'u:'. '4'. '1'
Если вы ссылаетесь на ID извне, вы можете захотеть скрыть другие способы. Если вам нужен пример, дайте мне знать, и я могу добавить свой ответ с чем-то, что вы могли бы сделать.
@ scalabl3
Вас беспокоят идентификаторы по двум причинам:
Начиная со второго выпуска, «Внешний вид». Хотя UUID, конечно же, не очень красив, когда дело доходит до идентификатора, уменьшаются отдачи, поскольку вы вводите поистине уникальный номер в сложном центре обработки данных (или центрах обработки данных), как вы упомянули. Я не уверен, что в восприятии приложения происходит резкое изменение, когда длинный номер по сравнению с UUID используется, например, в URL-адресе веб-приложения. В идеале ни один из них не будет показан, и ID
будет только когда-либо отправляться через запросы Ajax и т. Д. Хотя предпочтительный чистый запоминающийся URL-адрес предпочтительнее, он никогда не останавливал меня от покупок на Amazon (где у них есть абсолютно отвратительные URL-адреса). 🙂
Даже с вашим предложением, идентификаторы, в то время как они будут короче в количестве символов, чем UUID, они не более запоминаются, чем UUID. Таким образом, появление, вероятно, останется спорным.
Говоря о первом пункте …, да, есть несколько случаев, когда известно, что UUID генерируют конфликты. Хотя это не должно происходить в правильно сконфигурированной и постоянно полученной архитектуре, я могу видеть, как это может произойти (но я лично гораздо меньше обеспокоен этим).
Итак, если вы говорите об альтернативах, я стал поклонником простоты объекта MongoDB ObjectId
и его методов избежания дублирования при создании идентификатора. Полная документация находится здесь . Быстрые релевантные элементы похожи на ваш потенциальный дизайн несколькими способами:
ObjectId – это 12-байтовый тип BSON, построенный с использованием:
Временная метка часто может быть полезна для сортировки. Идентификатор машины похож на ваш сервер приложений, имеющий уникальный идентификатор. Идентификатор процесса – это просто дополнительная энтропия и, наконец, чтобы предотвратить конфликты, есть счетчик, который автоматически увеличивается, когда временная метка такая же, как и в последний раз, когда создается ObjectId (так что ObjectIds могут быть созданы быстро). ObjectId
s может быть сгенерирован на клиенте или в базе данных. Кроме того, ObjectIds занимают меньше байтов, чем UUID (но только 4). Конечно, вы не могли использовать временную метку и сбросить 4 байта.
Для пояснения я не предлагаю использовать MongoDB, но должен быть вдохновлен техникой, которую они используют для генерации идентификатора.
Итак, я думаю, что ваше решение является достойным (и, возможно, вы хотите вдохновиться внедрением MongoDB уникального идентификатора) и выполнимым. Что касается того, нужно ли вам это делать, я думаю, что это вопрос, на который вы можете ответить.