Pull to refresh

Comments 16

Вы говорите про базу данных, а статья про слой доступа к данным в вашем приложении.

MS SQL 2014 in-memory — это возможность хранить таблицы целиком в памяти в сервере базы данных, но у вас всё равно остается слой ORM(или сырых SQL-запросов) в вашем коде, так же остается сетевой запрос за данным, т.е. нету всех тех плюсов что были описаны выше.

Корректнее было бы сравнить мой подход с кэшированием внутри Entity Framework / других ORM, и тут в моём варианте значимым отличием было бы только то, что я гарантирую отсутствие сетевых запросов / ленивых запросов при получении данных после старта.
EF Core InMemoryProvider не предполагает сохранения данных куда-либо, он нужен для локальных тестов.
Также я не в курсе насколько хорошо один и тот же инстанс datacontext из ef переживает обращения из разных потоков.
Если приложение упадет — можно частично потерять данные.

Не только "когда упадет приложение", а еще и при многих других вариантах отказов. В этом, собственно, крупная проблема всех "а давайте сделаем in-memory".

Да, это правда. С другой стороны — условно-мгновенная репликация на соседний сервис и поддержание постоянно активным хотя бы одного инстанса должно решить эту проблему, нет?

Неа. У вас же репозиторий в памяти приложения (ну или какого-то из его слоев), а не снаружи, иначе никакого смысла в нем нет, можно сразу Redis взять. А если так, то получается смешное. Возьмем, скажем, веб-приложение, однослойное, для простоты. Вот крутится у вас в его памяти репозиторий, все вроде нормально. И в какой-то момент запись репозитория в персистентное хранилище ломается. Нет, с приложением все хорошо, а вот хранилище отвалилось. Как вам помогла репликация в соседнюю реплику приложения? Да никак. Вам надо понять, что эта ситуация случилась, уронить свое приложение, чтобы балансировщик перед ним переключился на другое, а ваше собственное — начало перезапускаться. Более того, когда вы все это делаете, вам еще надо быть уверенным, что, собственно, ваша репликация тоже работала без сбоев. Что, в сумме, настолько усложняет решение, что возникает вопрос "а зачем, и не проще ли взять redis".

Если ломается запись в хранилище — это вроде как раз решается retry-политиками?

Допустим мы делаем Active-Active решение из N инстансов, каждый со своим хранилищем и условно-мгновенной репликацией друг с другом.

Да, вы правы что тут есть некоторые сложности, но не вижу значительно больших сложностей, чем иметь high-available redis (который также может упасть, к слову).
Если ломается запись в хранилище — это вроде как раз решается retry-политиками?

А если retry так и не прошел?


Допустим мы делаем Active-Active решение из 3 инстансов, каждый со своим хранилищем и условно-мгновенной репликацией друг с другом.

Если это Active-Active, как вы конфликты разрешать будете?


Да, вы правы что тут есть некоторые сложности, но не вижу значительно больших сложностей, чем иметь high-available redis

Понимаете, за HA Redis отвечаете не вы. Вам не надо думать, как он устроен, как разрешены конфликты, что там и как.

Если это Active-Active, как вы конфликты разрешать будете?

Это то, о чем я и писал в «планах на будущее» — либо распределенные транзакции, либо «кто последний, тот и прав». Оба варианта так себе, но для pet project-ов подойдёт.

Понимаете, за HA Redis отвечаете не вы. Вам не надо думать, как он устроен, как разрешены конфликты, что там и как.

Не согласен с подходом. То что вы можете найти hosted ha redis, или перенести ответственность на другую команду / SRE — не означает что не стоит думать о том, что делать когда(не если, а когда) оно приляжет / потеряются данные за последние N минут.

Но в ряде случаев вы правы, если это уже не pet-project — то с т.з. рисков — проще писать всё в отдельную базу данных, которую не ты администрируешь. А лучше сразу в облако — оно-то точно не упадет.
Это то, о чем я и писал в «планах на будущее»

А пока у вас этого нет, это не решение.


То что вы можете найти hosted ha redis, или перенести ответственность на другую команду / SRE — не означает что не стоит думать о том, что делать когда(не если, а когда) оно приляжет / потеряются данные за последние N минут.

Думать о том, что делать, если хранилище недоступно — это одна задача, и ее вам решать в обоих случаях. Думать о том, что делать, чтобы оно не было недоступно — это другая задача, и ее в одном случае из двух можно избежать.

По большому счёту это ничем не отличается от любого внешнего nosql-хранилища. Тут основной плюс в том, что это в том же самом процессе работает.
UFO just landed and posted this here
Спасибо за идеи!

1) Да, но это решается на уровне хранилища / IStorage, если цель оптимизировать потребление дискового пространства. Если цель оптимизировать потребление памяти — то такое, конечно, можно сделать, но смысла в этом я вижу мало, если честно.

Если только какой-то конкретный уникальный проект, в котором сотни тысяч текстов по >10 кбайт (а это всего лишь 1 гб!) — тогда это можно решать в рамках какого-то конкретного проекта.

2) Аналогично п.1, хотя есть другой частый кейс, который возможно имеет смысл поддерживать прямо в ObjectRepository — это хранение бинарных файлов (например, картинки?). Очевидно, что писать их прямо в underlying storage не лучшая идея, вероятно их стоит хранить рядом на диске (или в облачном object storage: S3, Azure Blob Storage).

3) TableDictionary уже реализует IEnumerable, поэтому тут уже работает обычный LINQ:
var count = repository.Set<ParentModel>().Where(v=> v.Property == "123").Count();

Я почему-то предполагал это очевидным, поэтому не упомянул в статье, каюсь.

4) Хорошая мысль! В своих проектах я делал на базе Roslyn прямо в админке консоль для ObjectRepository, можно это вынести и в отдельную тулзу.

Расскажите, как работает LINQ с этим репозиторием - он будет работать как с обычной коллекцией, т.е. перебирать все элементы, соответствующие выражению или будет использовать какой-нибудь поиск по дереву? насколько поиск будет производителен? опыт показывает, что если в коллекции несколько миллионов объектов, то их перебор будет занимать довольно много времени, иногда обращение к SQL-серверу за небольшой выборкой в этом случае будет работать даже быстрее. А кэширование в памяти все же затевается ради производительности.

Sign up to leave a comment.

Articles

Change theme settings