Высокое хранилище данных для репликации приложений

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

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

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

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

Спасибо

Ответы

Ответ 1

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

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

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

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

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

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

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

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

Ответ 2

Обязательная настройка примера блога; 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, вы должны подумать: "Принесите мне, вероятно, последние сообщения для bob".

Поскольку в нашем приложении важно, чтобы автор мог видеть свое сообщение в списке сразу после его создания, мы будем использовать атрибут 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.

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

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

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

Ответ 3

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

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

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

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