Разбиение границы графа в Cosmos DB

Cosmos DB заранее анонсировала общедоступность Gremlin (Graph API). Вероятно, к концу 2017 года он выйдет из предварительного просмотра, поэтому мы можем считать его достаточно стабильным для производства. Это подводит меня к следующему:

Мы разрабатываем систему с ориентировочной пользовательской базой до 100 миллионов пользователей. У каждого пользователя будет несколько документов в Cosmos для хранения пользовательских данных, эти документы разделены по идентификатору пользователя (Guid). Таким образом, когда оценки сбудутся, у нас будет не менее 100 миллионов разделов, каждый из которых будет содержать кучу документов.

Мы будем хранить не только пользовательские данные, но и взаимосвязанные данные (отношения) между пользователями. На бумаге Cosmos должен очень хорошо подходить для таких сценариев, используя его кросс-API с Document API для обычных данных и Graph API исключительно для отношений.

Примером одного из таких отношений является Follow. Например, UserX может следовать UserY. Чтобы реализовать эту взаимосвязь, мы создали запрос Gremlin, который создает Edge:

    g.V().hasId('{userX.Id}').has('pkey','{userX.Partition}')
    .addE('follow').to(g.V().hasId('{userY.Id}').has('pkey','{userY.Partition}'))

Результирующий Edge автоматически назначается разделу UserX, потому что UserX является выходной вершиной.

При запросе исходящих ребер (всех пользователей, за которыми следит UserX) все в порядке, потому что запрос ограничен разделом для UserX.

    g.V().hasId('{userX.Id}').has('pkey','{userX.Partition}').outE('follow').inV()

Однако при инвертировании запроса (поиск всех последователей UserY) при поиске входящих ребер ситуация меняется - насколько мне известно, это приведет к полному межраздельному запросу:

    g.V().hasId('{userY.Id}').has('pkey','{userY.Partition}').inE('follow').outV()

На мой взгляд, полный межсекционный запрос со 100 миллионами разделов неприемлем.

Я попытался поместить Edge между UserX и UserY внутри отдельного раздела, но API Graph не позволяет мне это сделать. (Изменить: Cosmos изменен на Graph API)

Теперь я подошел к реализации пары ребер между UserX и UserY, одного исходящего Edge для UserX и одного исходящего Edge для UserY, пытаясь сохранить их синхронизацию. Все это для того, чтобы оптимизировать скорость моих запросов, а также для того, чтобы внести больше работы для достижения конечной согласованности.

Опять же, мне интересно, действительно ли Graph API подходит для таких сценариев - или мне действительно чего-то здесь не хватает?


person cldons    schedule 21.11.2017    source источник
comment
Это действительно ограничение того, как реализована функциональность графов Cosmo. Создание двух ребер для поддержки двунаправленных запросов может улучшить вашу производительность, но, очевидно, вам необходимо встроить логику приложения, чтобы гарантировать, что оба ребра всегда успешно создаются. Нет поддержки транзакций или ACID при работе с документами между разделами   -  person Jesse Carter    schedule 22.11.2017
comment
@JesseCarter Спасибо за ответ. На самом деле, именно так реализован Graph API, если мы начнем возиться непосредственно с REST-интерфейсом Cosmos, мы сможем получить от него больше. Прямо сейчас я изучаю создание вершин и ребер с помощью UDF для достижения некоторой формы транзакций ...   -  person cldons    schedule 22.11.2017
comment
@cldons, это был очень хороший вопрос, я искал ответ на него, и вы так хорошо его объяснили.   -  person ahmed nader    schedule 17.06.2020


Ответы (2)


Я начну с устранения вашего небольшого заблуждения относительно разбиения на разделы CosmosDB. 100 миллионов пользователей не означают 100 миллионов разделов. Они просто означают 100 миллионов ключей разделов. Когда вы создаете график cosmos dB, он начинается с 10 физических разделов (это начальное значение по умолчанию, которое можно изменить по запросу), а затем автоматически масштабируется по мере роста данных.

В этом случае 100 миллионов пользователей будут распределены между 10 физическими разделами. Следовательно, полный запрос между разделами попадет в 10 физических разделов. Также обратите внимание, что эти разделы будут задействованы параллельно, поэтому ожидаемая задержка будет аналогична попаданию в один раздел, если только операция не похожа на агрегаты по своей природе.

person Jayanta Mondal    schedule 22.11.2017
comment
@JayanteMondal Спасибо за ответ - к сожалению, это не совсем то, на что я надеялся. Я снова прочитал официальную документацию о разделении Cosmos и заметил, что в статье нет четкого различия между логическим и физическим разделением. Правильно ли я полагаю, что если я использую пару ребер (вход и выход) для определения отношения, RU, потраченные на запросы, будут намного меньше, чем только определение выходного края и запрос входящего? - person cldons; 22.11.2017

Это классическая дилемма разделения, не уникальная для Cosmos / Graph.

Если ваш шаблон использования - это множество запросов с небольшой областью, тогда перекрестное разделение - это плохо. Если он возвращает большие наборы данных, то накладные расходы на разделение, вероятно, незначительны по сравнению с преимуществами параллелизма. Если у вас нет постоянного большого объема запросов, я думаю, что накладные расходы на разделение переоценены (MS, похоже, думает, что все создают следующий Facebook на Cosmos).

В случае OP вы можете оптимизировать, чтобы x следует за y, или за x следует y, или для того и другого, имея край в каждом направлении. Обратите внимание, что RU резервируются для каждого раздела (т. Е. Общее количество RU / количество разделов), поэтому для их эффективного использования вам нужны либо большие объемы, равномерно распределенные, запросы с одним разделом, либо запросы, охватывающие несколько разделов.

person Ian Bennett    schedule 11.12.2018