2017-02-14 4 views
0

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

Ниже приведены данные сообщений в блогах. Сообщения могут быть помечены несколькими терминами, такими как «tag1», «tag2». Для того, чтобы найти, сколько сообщений помечаются с определенным тегом можно разветвление данные сообщения в теги пути путь, а также:

/posts/postid1:{“Title”:”Title 1”, “body”: “About Firebase”, “tags”: {“tag1:true, “tag2”: true}} 
/tags/tag1/postid1: {“Title”:”Title 1”, “body”: “About Firebase”} 
/tags/tag2/postid1: {“Title”:”Title 1”, “body”: “About Firebase”} 

Теперь рассмотрим одновременно,

1a), что User1 хочет изменить название postid1 и он строит следующее обновление многолучевой:

/posts/postid1/Title : “Title 1 modified” 
/tags/tag1/postid1/Title : “Title 1 modified” 
/tags/tag2/postid1/Title : “Title 1 modified” 

1b) в то же время Пользователь2 хочет добавить tag3 к postid1 и построить следующие мульти- путь обновление:

/posts/postid1/tags : {“tag1:true, “tag2”: true, “tag3”: true} 
/tags/tag3/postid1: {“Title”:”Title 1”, “body”: “About Firebase”} 

Так, по-видимому оба обновления могут сменяют друг за другом, и мы можем иметь данные тег/tag3/postid1 из синхронизации, как это имеет старое название.

Я могу думать о правилах безопасности, чтобы справиться с этим, но затем не уверен, что это правильно или будет работать.

Как мы можем иметь updatedAt и lastUpdatedAt поля и мы проверяем, если мы обновляем нашу собственную версию поста, что мы читаем:

posts":{ 
    "$postid":{ 
    ".write":true, 
    ".read":true, 
    ".validate": " 
     newData.hasChildren(['userId', 'updatedAt', 'lastUpdated', 'Title']) && (
     !data.exists() || 
     data.child('updatedAt').val() === newData.child('lastUpdated').val())" 
    } 
} 

Также для тегов мы не хотим, чтобы проверить, что снова и мы можем проверьте, является ли/tags/$ tag/$ postid/updatedAt таким же, как/posts/$ postid/updatedAt.

"tags":{ 
    "$tag":{ 
    "$postid":{ 
     ".write":true, 
     ".read":true, 
     ".validate": " 
     newData.hasChildren(['userId', 'updatedAt', 'lastUpdated', 'Title']) && (
     newData.child('updatedAt').val() === root.child('posts').child('$postid').val().child('updatedAt').val())”    
    } 
    }  
} 

К этому «/ сообщениям/$ сообщений дан» имеет управление параллелизмом в нем, и пользователи могут писать свои собственные читает Кроме того/сообщений/$ сообщений дан»становится источником истины и отдыха и другие пути веера из проверки, если updatedAt поля соответствуют ему основным источником пути истины.

Будет ли это приводить в соответствие или все еще есть проблемы? Или может привести к снижению производительности, когда это делается в масштабе?

Являются ли множественные обновления путей и правила атомарными вместе под этим я подразумеваю правило или оба правила оцениваются отдельно в изоляции для обновлений нескольких путей, таких как 1a и 1b выше?

+0

Одним из последствий дублирования заголовка является то, что вам придется либо обеспечить его ссылочную целостность в ваших правилах безопасности, запустить обновления из одного места (сервера), либо принять, что они могут выйти из синхронизации (и рассмотрите, какое значение является «мастером», чтобы вы могли реализовать процесс очистки, который гарантирует конечную согласованность). Нет ни одного правильного ответа, но вот варианты, которые я перечислял некоторое время назад: http://stackoverflow.com/questions/30693785/how-to-write-denormalized-data-in-firebase/30699277#30699277 –

+0

Спасибо. То, что я думал, что после 2 правил, которые я упомянул; даже если оба многолучевых обновления работают одновременно на сервере (и не последовательно), потому что правила перекрываются и конфликтуются в условиях, в которых они оба потерпят неудачу, или, по крайней мере, один из них потерпит неудачу (1b). Что ты думаешь? Как обрабатывается атомарность для правил, особенно когда в правилах используются пути из разных мест? На этом, похоже, нет документа. –

+0

Извините, сложно разобрать сложные правила (что, к сожалению, необходимо для таких сценариев, если только вы не используете одиночный писатель для всех зависимых данных). Этот бит 'newData.child ('updatedAt'). Val() === root.child ('posts'). Child ('$ postid'). Val(). Child ('updatedAt'). Val()) «Выглядит подозрительно, потому что вы ссылаетесь на« root »- который имеет старые данные. Если вы хотите, чтобы root-as-it-would-exist-after-this-write проходил к нему через 'newData.parent(). Parent() ....'. –

ответ

0

К сожалению, Firebase не предоставляет никаких гарантий или механизмов для обеспечения уровня детерминизма, который вы ищете. У меня была лучшая удача, завершающая такие обновления с помощью стека API (GCF и Lambda - это очень простые, без сервера методы для этого). Обновления могут быть сделаны в этом слое и даже сериализованы, если это абсолютно необходимо. Но в Firebase нет безопасного способа сделать это.

Существует множество вариантов «взлома», которые вы могли бы применить. Например, у вас может быть простой механизм блокировки с использованием выделенной коллекции для отслеживания блокировок записи. Клиенты могут отправлять сообщения в коллекцию блокировок, а затем проверять, что их ключ был единственным членом этой коллекции, перед выполнением записи. Но я надеюсь, вы согласитесь со мной в том, что такие кооперативные системы имеют слишком много потенциальных крайних случаев, потенциальных проблем безопасности и т. Д.В Firebase лучше всего сконструировать такие компоненты, чтобы этот компонент не требовал в первую очередь.

+0

Да, я НЕ ищу систему многофазного согласования с тайм-аутом. Я в порядке, если оба обновления многолучевого распространения терпят неудачу, или в конечном итоге согласованность, определить исходный путь и другие места должны синхронизироваться с этим в конечном итоге. Я буду использовать сервер для некоторых задач, но тогда сервер API будет масштабируемым (многие экземпляры), а рабочие серверы будут читайте из очереди Firebase, так что шансы 2 рабочих, работающих на s множество путей. –

+0

Извините, Firebase не предоставляет никакой внутренней механики, чтобы обеспечить синхронизацию от источника или скоординированные обновления. Он поддерживает транзакции, но они не будут очень полезны для того, что вы описываете. Я согласен с тем, что наилучшим ответом является координация этого извне от Firebase. –