Объективировать - много писем одному и тому же лицу за короткий промежуток времени с транзакцией и без нее
Что я делаю, это создание транзакции, где
1) У субъекта A счетчик обновлен до +1
2) Новый объект B записывается в хранилище данных.
Это выглядит так:
WrappedBoolean result = ofy().transact(new Work<WrappedBoolean>() {
@Override
public WrappedBoolean run() {
// Increment count of EntityA.numEntityBs by 1 and save it
entityA.numEntityBs = entityA.numEntityBs +1;
ofy().save().entity(entityA).now();
// Create a new EntityB and save it
EntityB entityB = new EntityB();
ofy().save().entity(entityB).now();
// Return that everything is ok
return new WrappedBoolean("True");
}
});
То, что я делаю, ведет учет того, сколько EntityB имеет entityA. Эти две операции должны быть в транзакции, поэтому либо происходит сохранение, либо ни одно не происходит.
Однако, возможно, что многие пользователи будут выполнять метод API, который содержит вышеуказанную транзакцию. Я боюсь, что я могу столкнуться с проблемами слишком многих людей, пытающихся обновить entityA. Это связано с тем, что если несколько транзакций пытаются обновить один и тот же объект, выигрывает первый коммит, но все остальные завершаются неудачно.
Это приводит меня к двум вопросам:
1) Является ли транзакция, которую я написал, плохой идеей и предназначена для того, чтобы записи не производились, если много вызовов было сделано для метода API? Есть ли лучший способ достичь того, что я пытаюсь сделать?
2) Что, если будет сделано много обновлений для объекта, не входящего в транзакцию (например, для обновления счетчика, имеющегося у объекта) - вы в конечном итоге столкнетесь с проблемой масштабирования, если за короткий период будет выполнено много обновлений времени? Как хранилище данных справляется с этим?
Извините за длинный вопрос, но я надеюсь, что кто-то может пролить свет на то, как эта система работает для меня с вышеуказанными вопросами. Благодарю.
Изменить: Когда я имею в виду множество обновлений, которые делаются для сущности за короткий промежуток времени, рассмотрим что-то вроде Instagram, где вы хотите отслеживать, сколько "лайков" имеет картинка. У некоторых пользователей есть миллионы подписчиков, и когда они публикуют новую фотографию, они могут получить что-то вроде 10-50 лайков в секунду.
1 ответ
Хранилище данных допускает примерно 1 запись / секунду на группу объектов. Что может показаться неочевидным, так это то, что автономные сущности (то есть сущности без родителей и потомков) по-прежнему принадлежат одной группе сущностей - своей собственной. Таким образом, на повторные записи в одну и ту же отдельную сущность распространяется одно и то же ограничение скорости.
Превышение лимита записи в конечном итоге приведет к сбою операций записи с чем-то вроде TransactionFailedError(Concurrency exception.)
Повторные записи в одну и ту же сущность, выполненные вне транзакций, могут перезаписывать друг друга. В этом могут помочь транзакции - конфликтующие записи будут автоматически повторены несколько раз. Ваш подход выглядит хорошо с этой точки зрения. Но это работает, только если средняя скорость записи остается ниже предела.
Вы, вероятно, хотите прочитать Избежание разногласий в хранилище данных. Вы должны осколок своего счетчика, чтобы иметь возможность считать события с частотой более 1/ сек.