Подходы к созданию автоматически увеличивающихся числовых идентификаторов в CouchDB

Поскольку CouchDB не поддерживает SQL, как AUTO_INCREMENT, каков был бы ваш подход к генерации последовательных уникальных числовых идентификаторов для ваших документов?

Я использую числовые идентификаторы для:

  • Удобные идентификаторы (например, TASK-123, RQ-001 и т. Д.)
  • Интеграция с библиотеками / системами, требующими числовой первичный ключ

Я знаю о проблемах с репликацией и т. Д. Поэтому мне интересно, как люди пытаются решить эту проблему.


person aku    schedule 22.02.2011    source источник


Ответы (6)


Как говорит Доминик Барнс, целые числа с автоматическим приращением не масштабируются, не подходят для распределения или облака. Кажется, что каждое приложение в настоящее время нуждается в мобильной версии с автономной поддержкой, которая напрямую не совместима с целыми числами с автоматическим приращением. Мы все это знаем, но это правда: целые числа с автоматическим приращением необходимы для устаревшего кода и, возможно, для других вещей.

В обоих сценариях вы несете ответственность за создание автоматически увеличивающегося целого числа. Представление выполняется emit(the_numeric_id, null). (У вас также может быть пространство имен "тип", например, emit([doc.type, the_numeric_id], null). Запрос последней строки (например, с startkey=MAXINT&descending=true&limit=1, увеличьте возвращаемое значение на единицу, и это будет ваш следующий идентификатор. Попытка сохранения находится в цикле, который может повторить попытку, если произошло столкновение.

Вы также можете подшутить, если вам не нужна 100% плотность списка идентификаторов. Например, вы можете добавить отметки времени к emit() строкам, оценить скорость создания документа и увеличить на эту скорость, умноженную на время вычислений и передачи. Вы также можете просто увеличить на случайное целое число от 1 до N, поэтому большую часть времени первая вставка работает за счет неоднородных идентификационных номеров.

Что касается того, где хранить целое число, я думаю, что есть стратегия id и стратегия попробуйте и проверьте.

Стратегия id проще и быстрее в краткосрочной перспективе. Идентификаторы документов являются целыми числами (возможно, с префиксом типа для добавления пространства имен). Поскольку Couch гарантирует уникальность поля _id, вы просто беспокоитесь об автоинкременте. Сделайте это в цикле: 409 Conflict запускает повторную попытку, 201 Accepted означает, что все готово.

Я думаю, что основная проблема этого трюка заключается в том, что если и когда возникают конфликты, у вас есть два совершенно не связанных друг с другом документа, и один из них необходимо скопировать в новый документ. . Если были связи с другими документами, все они должны быть исправлены. (На ум приходит трюк с CouchDB 0.11 emit(key, {_id: some_foreign_doc_id}).)

В стратегии попробуйте и проверьте в качестве doc._id используется UUID по умолчанию, поэтому каждая вставка будет успешной. В идеале все или большая часть ваших междокументных отношений основана на неизменяемом UUID _id, а не на целом числе. Это просто используется для пользователей и пользовательского интерфейса. Автоматически увеличивающееся целое число - это просто поле в документе {"int_id":20}. Вид конечно же emit(doc.int_id, null). (Вы можете искать документ по целочисленному идентификатору с параметром ?key=23?include_docs=true представления.

Конечно, после репликации у вас могут возникнуть конфликты идентификаторов (не официальные конфликты CouchDB, а просто документы с одним и тем же числовым идентификатором). Представление, которое генерируется по идентификатору, также будет иметь фазу сокращения: достаточно просто _count. Затем вы должны патрулировать БД, запрашивая это представление с помощью ?group=true и ища любую строку (соответствующую целочисленному идентификатору), которая имеет счетчик> 1. С другой стороны, исправление числового идентификатора документа является незначительным изменением, потому что оно действительно не требовать создания нового документа.

Это мои идеи. Теперь, когда я их записал, я чувствую, что вы должны поддерживать отношения независимо от того, где хранится идентификатор; так что, возможно, использование _id все-таки лучше. Единственный другой недостаток, который я вижу, - это то, что вы постоянно состоите в браке с принципиально нарушенной моделью именования для некоторого определения «навсегда».

person JasonSmith    schedule 22.02.2011
comment
Возможно, поскольку существует так много вопросов об автоматическом увеличении чисел, особенно связанных с couch db, разработчики должны реализовать именно это поле, которое автоматически увеличивается. Просто говорю' - person Aaron H.; 25.03.2016
comment
Поле с автоматическим приращением невозможно в дизайне CouchDB. Например, CouchDB поддерживает 2-узловой кластер CouchDB, где один узел находится на Марсе. (Или, что более распространено, у одного узла очень медленное или неустойчивое Интернет-соединение, например, в удаленных районах). Невозможно гарантировать автоматическое увеличение в каждом месте, так как они могут быть вне связи. Часто люди хотят, чтобы автоматическое приращение получило уникальные значения, и для этого лучше использовать UUID. В других случаях автоинкремент также может представлять угрозу безопасности (люди могут угадывать информацию друг друга). Это компромисс дизайна. - person JasonSmith; 25.03.2016

Есть ли какая-то конкретная причина, по которой вы хотите использовать числовые идентификаторы вместо UUID, которые CouchDB может сгенерировать для вас? UUID идеально подходят для распределенной парадигмы, которую использует CouchDB, придерживайтесь того, что встроено.

Если вы обнаружите, что в вашей архитектуре имеется более одного узла CouchDB, вы получите конфликтующие идентификаторы документов, если будете полагаться на что-то вроде «автоматического увеличения», когда придет время репликации. Даже если вы сейчас используете только 1 узел, это, вероятно, будет не всегда, тем более что CouchDB так хорошо работает в распределенной и «автономной» архитектуре.

person Dominic Barnes    schedule 22.02.2011
comment
Мне нужны короткие, удобочитаемые идентификаторы. На данный момент меня не волнует масштабируемость, но я бы предпочел избежать потенциальных проблем с репликацией. - person aku; 22.02.2011

Мне очень повезло, просто используя дату в формате iso в качестве ключа:

http://wiki.apache.org/couchdb/IsoFormattedDateAsDocId

Это довольно просто сделать, доступно для чтения человеком, и он в основном встраивает несколько опций запросов, просто существуя. :-)

person lysdexia    schedule 25.02.2011

Помня о проблемах, связанных с репликацией и конфликтами, вы можете использовать функцию обновления для генерации возрастающих идентификаторов, которые гарантированно уникальны в одной основной настройке.

function(doc, req) {
    if (!doc) {
        doc = {
            _id: req.id,
            type: 'idGenerator',
            count: 0
        };
    }
    doc.count++;
    return [doc, toJSON(doc.count)];
}

Включите эту функцию в проектный документ следующим образом:

{
   "_id": "_design/application",
   "language": "javascript",
   "updates": {
       "generateId": "function (doc, req) {\n\t\t\tif (!doc) {\n\t\t\t\tdoc = {\n\t\t\t\t\t_id: req.id,\n\t\t\t\t\ttype: 'idGenerator',\n\t\t\t\t\tcount: 0\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tdoc.count++;\n\t\t\t\n\t\t\treturn [doc, toJSON(doc.count)];\n\t\t}"
   }
}

Тогда назовите это так:

curl -XPOST http://localhost:5984/mydb/_design/application/_update/generateId/entityId

Замените entityId на что угодно, чтобы создать несколько независимых последовательностей идентификаторов.

person Tamlyn    schedule 09.04.2015

Не идеальное решение, но что-то, что сработало для меня. Создайте независимую службу, которая генерирует автоматически увеличивающиеся идентификаторы. Да, вы, вероятно, скажете, что «это нарушает автономную модель couchdb», но что, если вы получите пул идентификаторов N, которые затем можно использовать всякий раз, когда вам нужно получить новый автоматически увеличивающийся идентификатор. Затем каждый раз, когда вы в сети, вы получаете еще несколько идентификаторов, и если у вас заканчиваются идентификаторы, вы говорите своим пользователям - пожалуйста, выходите в онлайн. Если пул достаточно большой (например, ежемесячный трафик), этого не должно происходить. Опять же, не идеально, но, возможно, может быть полезным для некоторых людей.

person ganoro    schedule 02.03.2017

Вместо явного создания увеличивающегося целочисленного ключа вы можете использовать неявный индекс, который couchDB принимает для разбиения на страницы.

Параметр skip принимает целое число, которое фактически обеспечивает автоматически увеличивающийся индекс, к которому вы привыкли.

http://wiki.apache.org/couchdb/HTTP_view_API#Querying_Options

Недостатком является то, что это не жизнеспособное решение для «удобных для пользователя идентификаторов». Индекс не привязан к документу и может измениться, если вы переписываете историю.

Если ваше единственное ограничение - «интеграция с библиотеками / системами, требующими числовой первичный ключ», это позволит устранить пробел без потери преимуществ ключевой структуры couchDB.

person Jared Deckard    schedule 15.11.2014