Обработка количества задач при сохранении производительности

79
8

Я знаю, что это вопрос, специфичный для конкретного приложения, но я хотел посмотреть, есть ли у кого-то умное решение, о котором я не думал. Это сложный вопрос, поэтому основные моменты (и реквизиты) для всех, кто может изящно решить эту проблему.


У меня есть приложение ruby ​​on rails с глобальной навигацией, которая содержит количество задач (см. изображение ниже)


Global navitation with task counts


Проблема состоит в том, что для генерации этих счетчиков требуются интенсивные запросы. И потому что его глобальный, он на КАЖДОЙ странице. Они также должны обновляться, когда люди заботятся о задачах. Это делает его особенно сложным.


Тем не менее, сейчас я кэширую навигационный HTML в течение 10 минут через memcached. Если кто-то позаботится о задаче, хорошо. Навигатор обновляется каждые 10 минут. Ужасное решение, я знаю, но это мой показатель остановки пробела, пока я не придумаю правильное решение.


Я хочу, чтобы не добавлять кучу крючков по всему приложению (например: доставка обрабатывается, срабатывает крючок, который уменьшает количество для каждого соответствующего пользователя). Имейте в виду, что эти счета имеют дело с несколькими объектами в системе, а логика несколько сложна. Он имеет дело с доступом (каждый пользователь имеет разные значения в зависимости от системы прав), и определение этих показателей может быть сложным в некоторых ситуациях. Крюки будут очень беспорядочными, и логика создания этих счетчиков будет дублироваться.


Любая помощь будет принята с благодарностью.

спросил(а) 2021-01-19T15:03:21+03:00 9 месяцев назад
1
Решение
65

Если добавить дополнительный код для автоматического увеличения/уменьшения счетчиков, одно из решений - использовать кеш и эффективно использовать его. Псевдокод ниже.


class User

def counters
needs_update(user_id)
memcache.read(counter_user_id)
end

def needs_update(user_id)
some_job_queue_for_counters.insert(Job.new(User.update_counters(user_id)))
end

#executed by the job runner
def update_counters user_id
counter_hash = {:counter1 => complex_logic1, :counter2 => complex_logic2 ...}
memcache.write(counter_user_id, counter_hash.to_json.gzipped)
end

end

Несколько замечаний.


    Выполните вызов AJAX из браузера, скажем один раз в 1 минуту или более в зависимости от времени выполнения логики счетчика.
    Метод счетчиков так же быстро, как и может, потому что
    memcache.read() возвращает сжатую строку json. Нулевая обработка до
    генерировать ответ.
    Вы можете разогреть memcache для всех пользователей один раз в начале
    приложения. Затем после этого обновления счетчика происходит только для
    пользователей, которые вызывают метод couters, то есть для пользователей, которые сохраняют
    открытие браузера/мобильного приложения.
    needs_update метод может выполнять объединение данных для user_id, чтобы избежать дублирования.

ответил(а) 2021-01-19T15:03:21+03:00 9 месяцев назад
-5

Update:


Простым решением было бы удалить все кэшированные навигационные html для всех затронутых пользователей изменения. Вы также можете загрузить navHTML с помощью вызова ajax, чтобы вам не приходилось ждать загрузки этой страницы (и сохраняйте кэшированную версию navHTML в localStorage на клиенте, и всякий раз, когда страница загружается, вы можете затем активируйте reset navHTML, если это необходимо).


Более сложным решением было бы следующее:


Загрузите это в 2 слоя (navHTML, а затем отдельные элементы/пользователи/статусные элементы). Вам нужно будет найти способ обновления областей, чтобы они знали, на что рассчитывает, они должны запускать reset. Поэтому, если вы измените статус доставки на конечной машине, вы должны reset использовать все счетчики для этой доставки и удалить кэш-память для уязвимых пользователей.


Я бы поместил все ключи для каждого элемента поставки в кеш в некоторых пространствах имен, например "доставка: 234324-user: 123-status", поэтому всякий раз, когда Поставка с идентификатором # 234324 изменяется, вы выполняете итерирование и удаление всего кеша предметы, которые относятся к этой доставке (возможно, лучше всего держать ее как можно глубже). Вы можете вычислять и хранить счеты в кеше, когда кто-то запрашивает страницу, и просто удаляет кеш при изменении фактического объекта. Затем вы можете полностью кэшировать nav html, но всякий раз, когда что-то меняется с вашим пользователем и идентификатором в нем (например, пользователь-123), вы удаляете навигационный кеш и заставляете navHTML перезагружаться. Добавьте к этому какое-то время кэширования для навигатора (например, максимальный возраст 1 мин или что-то еще), чтобы учитывать ошибки. Элемент nav должен строить через кеш отдельных элементов, которые не должны проходить через каждый элемент.

Вероятно, вы захотите добавить Cache Sweeper, подключенную к вашим связанным моделям http://guides.rubyonrails.org/caching_with_rails.html


Здесь кеш счетчика для справки (я думаю, что создание модели базы данных, позволяющей использовать счетный кеш, - лучший способ справиться с этим).


http://railscasts.com/episodes/23-counter-cache-column


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

ответил(а) 2021-01-19T15:03:21+03:00 9 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема