Объективировать - много писем одному и тому же лицу за короткий промежуток времени с транзакцией и без нее

Что я делаю, это создание транзакции, где

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/ сек.

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