Синхронизация кэша
От: corpse56  
Дата: 07.09.23 12:16
Оценка:
Здравствуйте!

Задача стоит следующая. Есть порядка 50 толстых клиентов, которые работают с одной и той же базой. Клиенты тормозят из-за того, что каждый объект заново запрашивается из БД. Начал прикручивать кэш, ситуация улучшилась, но теперь проблема с синхронизацией кэшей... Поискал по разделу, нашёл интересное решение, которое бы мне подошло, но он только на линуксе. Подскажите, пожалуйста, есть ли похожие для windows?

Объекты изменяются, а клиенты должны непременно получать свежую версию. Но так как сейчас кэш у каждого клиента свой, то происходят всякие нежелательные последствия. Нужен как бы единый кэш для всех клиентов. Когда какой-то клиент обновляет объект, то и в кэше его тоже следует обновить, чтобы другие клиенты получали обновлённую версию этого же объекта.

Может быть есть какой-то способ самому это реализовать? Я так понимаю здесь нужно будет веб-приложение, или всё же использовать TCP-протокол для таких задач?
Наверняка уже существует что-то для такой задачи типа Memcached но под виндоус


Я использую c# .NET.

спасибо
Re: Синхронизация кэша
От: BlackEric http://black-eric.lj.ru
Дата: 07.09.23 12:34
Оценка: 1 (1)
Здравствуйте, corpse56, Вы писали:

Можно использовать Redis и хранить один общий кеш в нем. И проверять из него.
Можно через очередь сообщений или скажем веб-сокеты рассылать изменившиеся объекты через сервер на клиенты
https://github.com/BlackEric001
Re: Синхронизация кэша
От: vmpire Россия  
Дата: 07.09.23 12:34
Оценка: 1 (1)
Здравствуйте, corpse56, Вы писали:

C>Объекты изменяются, а клиенты должны непременно получать свежую версию. Но так как сейчас кэш у каждого клиента свой, то происходят всякие нежелательные последствия. Нужен как бы единый кэш для всех клиентов. Когда какой-то клиент обновляет объект, то и в кэше его тоже следует обновить, чтобы другие клиенты получали обновлённую версию этого же объекта.


C>Может быть есть какой-то способ самому это реализовать? Я так понимаю здесь нужно будет веб-приложение, или всё же использовать TCP-протокол для таких задач?

C>Наверняка уже существует что-то для такой задачи типа Memcached но под виндоус
Попробуй редиску
Re: Синхронизация кэша
От: Sinclair Россия https://github.com/evilguest/
Дата: 13.09.23 12:32
Оценка: 2 (1)
Здравствуйте, corpse56, Вы писали:
C>Задача стоит следующая. Есть порядка 50 толстых клиентов, которые работают с одной и той же базой. Клиенты тормозят из-за того, что каждый объект заново запрашивается из БД.
Обычно это симптом того, что у вас неудачно реализовано взаимодействие с БД.
C> Начал прикручивать кэш, ситуация улучшилась, но теперь проблема с синхронизацией кэшей...
Ага. Неизбежная проблема. Решения типа memcached или redis помогут оттянуть решение проблемы, но до конца ничего не решат.

Чтобы разговор был конструктивным, нужны подробности.
1. Клиенты — это разные приложения на одной машине, или это одно и то же приложение на 50 разных машинах?
2. Что значит "заново запрашивается"? Расскажите, что за действия тормозят, и как они устроены "внутри".
Обычно описываемые вами симптомы характерны для тяжеловесных ORM, поднятых на клиенте; когда одна бизнес-операция превращается в N+1 раундтрипов в СУБД, тормозит примерно всё, как ты его ни оптмизируй.
Кэширование на стороне клиента означает потерю актуальности данных, кэширование на стороне сервера означает те же проблемы с производительностью.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Синхронизация кэша
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 13.09.23 13:31
Оценка:
Здравствуйте, corpse56, Вы писали:

В 1С используют RDP база и сервер RDP находятся на одном сервере.
Самое простое решение. 50 клиентов это немного
и солнце б утром не вставало, когда бы не было меня
Re[2]: Синхронизация кэша
От: corpse56  
Дата: 13.09.23 15:22
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, corpse56, Вы писали:

C>>Задача стоит следующая. Есть порядка 50 толстых клиентов, которые работают с одной и той же базой. Клиенты тормозят из-за того, что каждый объект заново запрашивается из БД.
S>Обычно это симптом того, что у вас неудачно реализовано взаимодействие с БД.




C>> Начал прикручивать кэш, ситуация улучшилась, но теперь проблема с синхронизацией кэшей...

S>Ага. Неизбежная проблема. Решения типа memcached или redis помогут оттянуть решение проблемы, но до конца ничего не решат.
Почему не решат? Ведь, если объект изменился, то меняем его и в централизованном кэше, чтобы другие получали обновлённый.

S>Чтобы разговор был конструктивным, нужны подробности.

S>1. Клиенты — это разные приложения на одной машине, или это одно и то же приложение на 50 разных машинах?
одно приложение на 50 машинах
S>2. Что значит "заново запрашивается"? Расскажите, что за действия тормозят, и как они устроены "внутри".
Использую SqlDataAdapter. Получается, что каждый раз запрашиваю с помощью него объекты. Сами запросы проходят быстро. А вот когда раскладываю DataTable на бизнес объект, то тут и происходят основные тормоза. ORM в этом проекте не использую.
S>Обычно описываемые вами симптомы характерны для тяжеловесных ORM, поднятых на клиенте; когда одна бизнес-операция превращается в N+1 раундтрипов в СУБД, тормозит примерно всё, как ты его ни оптмизируй.
S>Кэширование на стороне клиента означает потерю актуальности данных, кэширование на стороне сервера означает те же проблемы с производительностью.
Я считал, что получить готовый объект из кэша на стороне сервера быстрее, чем запросить его из БД и построить новый объект.


Спасибо за ответ.
Re[2]: Синхронизация кэша
От: corpse56  
Дата: 13.09.23 15:23
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Здравствуйте, corpse56, Вы писали:


S>В 1С используют RDP база и сервер RDP находятся на одном сервере.

S>Самое простое решение. 50 клиентов это немного

тут так не получится... спасибо за ответ
Re[3]: Синхронизация кэша
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 13.09.23 15:53
Оценка: +1
Здравствуйте, corpse56, Вы писали:

S>>В 1С используют RDP база и сервер RDP находятся на одном сервере.

S>>Самое простое решение. 50 клиентов это немного

C>тут так не получится... спасибо за ответ

Тогда проще один сервер приложений, а 50 клиентов получают данные через него.
Можно кэшировать запросы, а если произошла запись в таблицу, то сбрасывать кэши.
Может в EF есть кэширование https://learn.microsoft.com/ru-ru/ef/ef6/fundamentals/performance/perf-whitepaper#3-caching-in-the-entity-framework
и солнце б утром не вставало, когда бы не было меня
Re: Синхронизация кэша
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 13.09.23 20:17
Оценка: 1 (1)
Здравствуйте, corpse56, Вы писали:

C>Здравствуйте!


C>Задача стоит следующая. Есть порядка 50 толстых клиентов, которые работают с одной и той же базой. Клиенты тормозят из-за того, что каждый объект заново запрашивается из БД.

Нормально спроектированная база выдерживает сотни и тысячи запросов в секунду. Тем более если это одни и те же объекты, то они просто лежат в памяти сервера БД и не запрашиваются с диска.


C>Объекты изменяются, а клиенты должны непременно получать свежую версию. Но так как сейчас кэш у каждого клиента свой, то происходят всякие нежелательные последствия. Нужен как бы единый кэш для всех клиентов. Когда какой-то клиент обновляет объект, то и в кэше его тоже следует обновить, чтобы другие клиенты получали обновлённую версию этого же объекта.

Если вам нужно оповещать клиентов об изменении объектов — возьмите redis, не мучайте базу лишними запросами. А если вам лень этим заниматься, то просто сделайте индекс по дате последнего изменения и получайте из небольшого индекса идентификаторы изменившихся записей.

C>Может быть есть какой-то способ самому это реализовать? Я так понимаю здесь нужно будет веб-приложение, или всё же использовать TCP-протокол для таких задач?

C>Наверняка уже существует что-то для такой задачи типа Memcached но под виндоус
Может и есть, но вам он недоступен.
Re[3]: Синхронизация кэша
От: Sinclair Россия https://github.com/evilguest/
Дата: 14.09.23 01:46
Оценка:
Здравствуйте, corpse56, Вы писали:
C>Почему не решат? Ведь, если объект изменился, то меняем его и в централизованном кэше, чтобы другие получали обновлённый.
Смотря что вы храните в "централизованном кэше".
S>>Чтобы разговор был конструктивным, нужны подробности.
S>>1. Клиенты — это разные приложения на одной машине, или это одно и то же приложение на 50 разных машинах?
C>одно приложение на 50 машинах
S>>2. Что значит "заново запрашивается"? Расскажите, что за действия тормозят, и как они устроены "внутри".
C>Использую SqlDataAdapter. Получается, что каждый раз запрашиваю с помощью него объекты. Сами запросы проходят быстро. А вот когда раскладываю DataTable на бизнес объект, то тут и происходят основные тормоза. ORM в этом проекте не использую.
Непонятно, откуда могут взяться тормоза в тривиальной операции раскладывания уже готовых данных в объект. Самый тормоз — это сеть; за ней идёт обращение к диску.
C>Я считал, что получить готовый объект из кэша на стороне сервера быстрее, чем запросить его из БД и построить новый объект.
В целом это быстрее, но обычно несущественно. Грубо говоря, вам надо протащить N мегабайт данных по сети — вот это и тормозит. Тащите вы их в виде TDS или в виде "бизнес-объекта" — разница не слишком велика.
Если в вашем случае всё именно так (и подтверждено профайлингом), тогда есть смысл задуматься о реализации сервера приложений, который может быть оборудован в том числе и внутренним кэшем.
В таком подходе основное, что меня пугает — критерии устаревания кэша. Если у вас все операции чётко делятся по границам бизнес-объектов — тогда всё хорошо, и вы легко прикрутите обновление кэша к вашему коду.
А если (как обычно и бывает) "бизнес-объект" собран по ссылкам из нескольких разных мест (которые могут меняться независимо), то построение полного списка элементов кэша, устаревших после выполнения операции, может оказаться затруднительным.

Поэтому я бы всё же начал с того, чтобы отпрофилировать:
— сколько времени занимает выполнение запроса к БД на стороне БД
— сколько времени занимает передача результатов запроса по сети
— сколько времени занимает преобразование DataAdapter в бизнес-объект

В зависимости от распределения времён между этими этапами, выбрал бы порядок оптимизации.
— Посмотрел бы, всё ли в порядке с моим SQL; нет ли там каких-то O(N) операций из-за отсутствия необходимых индексов.
— Посмотрел бы, точно ли в клиент едут только нужные данные; оценил бы перспективы оптимизации использования компрессии
— Посмотрел бы, откуда такие расходы времени на маппинг в бизнес-объект. Нельзя ли там что-то оптимизировать
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Синхронизация кэша
От: corpse56  
Дата: 14.09.23 12:01
Оценка:
Здравствуйте, gandjustas, Вы писали:


C>>Здравствуйте!


C>>Задача стоит следующая. Есть порядка 50 толстых клиентов, которые работают с одной и той же базой. Клиенты тормозят из-за того, что каждый объект заново запрашивается из БД.

G>Нормально спроектированная база выдерживает сотни и тысячи запросов в секунду. Тем более если это одни и те же объекты, то они просто лежат в памяти сервера БД и не запрашиваются с диска.
я неправильно выразился. Запросы из базы не тормозят. Тормозит при раскладывании записи из базы на бизнес объект. Извините.


G>Если вам нужно оповещать клиентов об изменении объектов — возьмите redis, не мучайте базу лишними запросами. А если вам лень этим заниматься, то просто сделайте индекс по дате последнего изменения и получайте из небольшого индекса идентификаторы изменившихся записей.

с индексом по дате изменения — хорошая идея! сейчас пробую redis прикрутить.


спасибо за ответ.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.