Мы постоянно обрабатываем тысячи субъектов времени, и у нас есть проблемы с производительностью, которые считывают много данных из хранилища данных, процессы являются вычислительными и не вызывают проблем. Мы создали синтетический тест, имитирующий реальный серверный трафик, где мы тестируем 25 тыс. Элит.GAE Datastore read performance
Мы используем среду выполнения Java и Objectify (5.1.1 и 5.1.8) для доступа к хранилищу данных.
Субъект
@Entity(name="logs")
@Cache
public class Log {
@Id
public Long id;
@Index
public Ref<User> user;
public String deviceId;
public String nonce;
public String version;
public String data;
@Index
public Date timestamp;
@OnSave
private void prePersist() {
if (timestamp == null) {
timestamp = new Date();
}
}
}
Запрос
query = ofy().load().type(Log.class).
filter("timestamp >", startDate).
order("timestamp").
limit(25000);
Мы пытались различную нагрузку субъектов. Сначала query.list()
, затем ofy().load().keys(query.keys())
, поэтому поиск будет проходить через memcache GAE, но результаты будут одинаковыми. Получение объектов размером 25 тыс. Занимает около 8 секунд (измеряется через System.nanoTime()
). В случае query.list()
этот вызов выполняется быстро, но итерация по объектам происходит медленно. Похоже, что объект извлекается из хранилища данных в тот самый момент, а не в query.list()
. Все это простой сервлет на внешнем экземпляре F4 с выделенным memcache, без задачи.
Чтение объектов 25k - это просто тест, чтобы получить некоторые цифры о производительности нашей серверной реализации. В реальном мире мы ожидаем читать до 500 тыс. Сущностей одновременно, можно ли это сделать до 30-60 секунд с хранилищем данных GAE и выделенным memcache? Через 2 года это могут быть миллионы юридических лиц.
Другой проблемой является ограниченная оперативная память, но она разрешима через управляемые виртуальные машины GAE или GCE.
Вопросы являются тем, что является самым быстрым способом получения временного объекта из выделенного хранилища данных + выделенного memcache с Objectify. Похоже, memcache не помогает Objectify в нашем случае. Memcache содержит десятки тысяч объектов Objectify внутри, но время загрузки такое же, как и с пустой memcache. Лучшая практика Objectify's/Datastore заключается в том, чтобы сделать пакетные операции, как это сделать? Является ли Objectify делать это под капотом с нашей сущностью и запросом или мы должны что-то изменить? Может ли API-интерфейс Datastore низкого уровня помочь нам улучшить производительность чтения? Спасибо.
EDIT Мы уже работаем над объединением журналов, поэтому каждый объект журнала будет содержать несколько текущих журналов. Это даст нам примерно 10-кратное усовершенствование тростника, которого все еще недостаточно для сотен тысяч записей.
Я пытаюсь представить сценарий, в котором вам нужно сразу же прочитать все свои ключи. Что именно вы делаете? –
Нам нужно прочитать журналы за последние несколько минут, затем загрузить активных пользователей на основе этих журналов, а затем выполнить итерацию по журналам на пользователя и обновить сущность пользователя на основе данных в журналах. Обработка выполняется быстро (задачи + потоки), но загрузка журналов и пользователей происходит медленно. Мы уже работаем над объединением журналов, поэтому каждый объект журнала будет содержать несколько текущих журналов. – shelll
Ну, я действительно не понимаю ваш случай использования, но по какой-либо причине вы не можете обновлять объект непосредственно в действии, а не хранить журнал и затем разбирать его? Дело в том, что, как вы обнаружили, GAE не подходит для такого использования; массовые операции лучше всего делать медленно, автономно, с помощью чего-то вроде map-reduce. –