Хранилище данных с высокой репликацией в App Engine

Я новичок в App Engine, и хочу подтвердить свое понимание хранилища данных с высокой репликацией.

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

Может ли кто-нибудь привести примеры, когда запросы могут быть "устаревшими"? Это говорит о том, что я мог бы потенциально сохранить сущность без какого-либо родителя (т. Е. Своей собственной группы), затем запросить ее очень скоро и не найти? Означает ли это также, что если я хочу, чтобы данные всегда были обновлены на 100%, мне необходимо сохранить их все в одной группе сущностей?

Является ли обычным обходным решением для этого использование memcache для кэширования объектов в течение периода времени, превышающего среднее время, которое требуется для того, чтобы данные стали согласованными во всех центрах обработки данных? Какова задержка для этого?

Спасибо

3 ответа

Это говорит о том, что я мог бы потенциально сохранить сущность без какого-либо родителя (т. Е. Своей собственной группы), затем запросить ее очень скоро и не найти?

Правильный. Технически, это относится и к обычному хранилищу данных Master-Slave, так как индексы обновляются асинхронно, но на практике окно времени, в которое это может произойти, настолько невероятно мало, что вы никогда его не увидите.

Если под "запросом" вы подразумеваете "сделать ключ", это всегда будет возвращать строго согласованные результаты в любой реализации.

Означает ли это также, что если я хочу, чтобы данные всегда были обновлены на 100%, мне необходимо сохранить их все в одной группе сущностей?

Вам нужно будет определить, что вы подразумеваете под "100% актуальностью", прежде чем можно будет на это ответить.

Является ли обычным обходным решением для этого использование memcache для кэширования объектов в течение периода времени, превышающего среднее время, которое требуется для того, чтобы данные стали согласованными во всех центрах обработки данных?

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

Если вам необходимо гарантировать, что вы видите последнюю версию, вам всегда доступны строго согласованные варианты получения. Однако без конкретного примера того, что вы пытаетесь сделать, трудно дать рекомендацию.

Обязательный пример блога; Authors иметь Posts

class Author(db.Model):
    name = db.StringProperty()

class Post(db.Model):
    author = db.ReferenceProperty()
    article = db.TextProperty()

bob = Author(name='bob')
bob.put()

Первое, что нужно запомнить, это то, что обычные операции get / put / delete для одной группы сущностей (включая одну сущность) будут работать как положено:

post1 = Post(article='first article', author=bob)
post1.put()

fetched_post = Post.get(post1.key())
# fetched_post is latest post1

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

fetched_posts = Post.all().filter('author =', bob).fetch(x)
# fetched_posts _might_ contain latest post1

fetched_posts может содержать последние post1 от bob, но это не так. Это потому что все Posts не находятся в той же группе лиц. Когда вы делаете запрос в HR, вы должны подумать: "Принесите мне, вероятно, последние сообщения для Боба".

Поскольку в нашем приложении важно, чтобы автор мог видеть свое сообщение в списке сразу после его создания, мы будем использовать parent атрибут, чтобы связать их вместе, и использовать ancestor запросить выборку сообщений только из этой группы:

post2 = Post(parent=person, article='second article', author=bob)
post2.put()

bobs_posts = Post.all().ancestor(bob.key()).filter('author =', bob).fetch(x)

Теперь мы знаем, что post2 будет в нашем bobs_posts Результаты.

Если бы целью нашего запроса было получить "вероятно, все последние сообщения + определенно последние сообщения от Боба", нам нужно было бы сделать еще один запрос.

other_posts = Post.all().fetch(x)

Затем объедините результаты other_posts а также bobs_posts вместе, чтобы получить желаемый результат.

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

Рассмотрим классический пример гостевой книги, где вы put() Новая запись в гостевой книге, а затем немедленно запросить все записи в гостевой книге. С хранилищем данных с высокой репликацией вы не увидите, как новое сообщение появится в результатах запроса, пока через несколько секунд (при вводе-выводе Google инженеры Google заявили, что задержка была порядка 2-5 секунд).

Теперь на практике ваше приложение гостевой книги, вероятно, делает запись AJAX новой записи записи гостевой книги. После отправки нового сообщения не нужно повторно получать все сообщения. Веб-приложение может просто вставить новую запись в пользовательский интерфейс после успешного выполнения запроса AJAX. К тому времени, когда пользователь покидает веб-страницу и возвращается на нее или даже нажимает кнопку обновления браузера, пройдет несколько секунд, и весьма вероятно, что новое сообщение будет возвращено запросом, который извлекает все сообщения гостевой книги.

Наконец, обратите внимание, что конечная производительность согласованности применяется только к запросам. если ты put() сущность и немедленно позвонить db.get() чтобы получить его обратно, результат строго согласован, то есть вы получите последний снимок объекта.

Другие вопросы по тегам