MCP

вторник, 27 февраля 2018 г.

Хранение данных в памяти

Очень давно вынашиваю идею о том, что базу данных для приложения стоит размещать в памяти. Конечно, не полностью в памяти, основную базу оставить, но использовать очень и очень агрессивное кеширование. Зачем? Об этом ниже.

Для начала скажу, что сам я, пока так и не реализовал эту идею в полной мере, были продукты, где это активно использовалось, но в основном, продукты, за которые я ответственен работают достаточно быстро и так, так что как-то и не требуется усложнение и смена парадигмы. Но, когда-нибудь, обязательно попробую!

Почему не стоит полагаться на кеш SQL-сервера?

Потому что он построен именно на модели кеша для данных, и в него можно попадать или не попадать. Конечно, в MS SQL есть OLTP таблицы, которые хранятся в памяти, но они больше для очень активных данных, и вообще это на уровне SQL, причём MS SQL. А без них — используются стандартные алгоритмы для поиска, оптимизированные для данных, находящихся на диске, как результат, необходимый кеш для очень 100% попадания в память многократно превышает размер реальных данных.

Я же предлагаю забить на это, и максимально хранить все данные из базы в памяти (загружать их из базы на старте, или ленивым образом).

Что это даёт?


  • Резко упрощается внешняя логика пользователя. Во многих случаях можно отказаться от джойнов, если нет дополнительной фильтрации. Например, классический джойн с данных с пользователем (например, вывести автора данных) можно заменить на выборку данных и доставание всех пользователей по ID. Это очёнь дешёво
  • Можно использовать очень тупые алгоритмы, и это всё равно будет очень быстро. Фуллскан 10000 записей почти незаметная вещь, а если надо будет ещё быстрее — всегда можно будет прикрутить "индекс" в виде словарика
  • Можно избавиться от отдельного кеша для тяжёлых данных, ибо и так всё в памяти
  • Тупо быстрее из-за отсутствия запросов к внешнему SQL-серверу
  • Легко хранить данные, которые тяжело забирать из SQL (объект с зависимыми детишками, слабо-структурированные документы, JSON/XML поля)
  • При этом, если приложение написано с использованием LINQ, то местами можно вообще не заметить разницы между базой и памятью (если грамотно спланировать архитектуру приложения)

 А в память влезет?

А вот это как раз главный вопрос, который всех останавливает и которого все боятся. И из-за этого, всё так и останавливается на уровне идей. Но давайте прикинем необходимое количество памяти.
  • База данных в 20ГБ содержит где-то 20ГБ данных (логично, да?), в памяти это будет занимать примерно столько же. Найти подходящий сервер — не так уж и сложно. Естественно, базы в 100МБ вообще влезут в память без проблем
  • Очень часто в "больших" базах большой объём занимают всякие полумёртвые данные — журналы, результаты импорта, файлы, подписанные данные, акксесс логи... Эти данные нужны очень редко, их можно не хранить в памяти, тем самым кардинально снизив объём "реальных" данных
  • Многие данные нужны только в небольшом количестве. Например, у вас есть 10000 пользователей в системе, но активны только 1000, тут можно использовать какой-нить LRU кеш и не держать в памяти все объекты, а только активные. Опять же, очень сокращает необходимый объём памяти
  • Ну и для реально огромных баз данных можно уж держать в памяти только специально выделенные объекты (например, справочники). Хотя, с такими объёмами у вас будет проблем побольше чем просто держать в памяти

Как реализовать?

Поскольку я ещё не делал это в полном виде, то могу только предположить следующие варианты:
  • Собственный кеш класса, ратающего с сущностью (e.g. UserManager), он сам решает, что и как кешировать. Проблемы в куче аналогичного кода в разных классах и сложность с инвалидацией. Плюсы: в каждом конкретном случае можно использовать самые эффективные варианты
  • Мемоизация и автомемоизация методов. Плюсы: очень упрощается код, минусы: сложно инвалидировать и оптимально использовать данные. 
  • Обёртка над ORM (или использование встроенных средств типа Second Level Cache), которая сделает всё сама. Проблемы: сложно в реализации и конфигурировании. Плюсы: полная прозрачность в использовании со стороны кода

Краткий итог

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