Out of Process в таблице базы данных памяти, которая поддерживает запросы для высокоскоростного кэширования
У меня есть таблица SQL, к которой обращаются постоянно, но очень редко меняются.
Таблица разделена на UserID, и каждый пользователь имеет много записей в таблице.
Я хочу сохранить ресурсы базы данных и переместить эту таблицу ближе к приложению в виде кэша памяти.
В процессе кэширования слишком интенсивный объем памяти, поэтому он должен быть внешним для приложения.
Хранилища ключевых значений, такие как Redis, оказываются неэффективными из-за накладных расходов на сериализацию и десериализацию таблицы в Redis и обратно.
Я ищу что-то, что может хранить эту таблицу (или разделы данных) в памяти, но позвольте мне запросить только необходимую информацию без сериализации и десериализации больших блоков данных для каждого чтения.
Есть ли что-нибудь, что обеспечило бы Out of Process в таблице базы данных памяти, которая поддерживает запросы для высокоскоростного кэширования?
Поиск показал, что Apache Ignite может быть возможным вариантом, но я ищу более обоснованные предложения.
Ответы
Ответ 1
Так как это вне процесса, он должен выполнять сериализацию и десериализацию. Проблема заключается в том, как уменьшить сериализацию/десеризацию. Если вы используете тип Redis STRING
, вы НЕ МОЖЕТЕ уменьшить эту работу.
Однако вы можете использовать HASH
для решения проблемы: сопоставление вашей таблицы SQL с HASH
.
Предположим, что у вас есть следующая таблица: person: id(varchar), name(varchar), age(int)
, вы можете взять человека id
в качестве ключа и взять name
и age
в качестве полей. Если вы хотите найти имя пользователя, вам нужно только получить поле имени (HGET person-id name
), другие поля не будут десериализованы.
Ответ 2
Ignite - действительно возможное решение для вас, поскольку вы можете оптимизировать служебные данные сериализации/десериализации, используя внутреннее двоичное представление для доступа к полям объектов. Вы можете обратиться к этой странице документации для получения дополнительной информации: https://apacheignite.readme.io/docs/binary-marshaller
Также могут быть оптимизированы служебные данные доступа, отключив параметр копирования на чтение https://apacheignite.readme.io/docs/performance-tips#section-do-not-copy-value-on-read
Сопоставление данных по идентификатору пользователя также возможно с помощью Ignite: https://apacheignite.readme.io/docs/affinity-collocation
Ответ 3
Как сказал @for_stack, Hash
будет очень подходящим для вашего случая.
вы сказали, что каждый пользователь имеет много строк в db, индексированных user_id
и tag_id
. Таким образом, (user_id, tag_id) однозначно указывает одну строку. Каждая строка функциональна, зависит от этого кортежа, вы можете использовать кортеж как HASH KEY.
Например, если вы хотите сохранить строку (user_id, tag_id, имя пользователя, возраст), какие значения ( "123456", "FDSA", "gsz", 20) перерисовать, вы можете сделать это:
HMSET 123456:FDSA username "gsz" age 30
Если вы хотите запросить имя пользователя с помощью user_id и tag_id, вы можете сделать следующее:
HGET 123456:FDSA username
Таким образом, каждый хэш-ключ будет комбинацией user_id
и tag_id
, если вы хотите, чтобы ключ был более читабельным для человека, вы могли бы добавить строку префикса, такую как "USERINFO". например: USERINFO:123456:FDSA
.
НО Если вы хотите запросить только с user_id и получить все строки с этим user_id, этого метода выше будет недостаточно.
И вы можете создать вторичные индексы в redis для вас HASH.
как указано выше, мы используем user_id:tag_id
как клавишу HASH. Потому что он может создавать уникальные точки в одной строке. Если мы хотим запросить все строки об одном user_id.
Мы могли бы использовать sorted set
для создания вторичной индексации для индекса, который Хэш хранит информацию об этом user_id.
Мы могли бы добавить это в SortedSet:
ZADD user_index 0 123456:FDSA
Как и выше, мы устанавливаем member
в string of HASH key
и устанавливаем score
равным 0. И правило состоит в том, что мы должны установить для всех баллов в этом zset значение 0, а затем мы могли бы использовать лексикографический порядок для запроса диапазона. обратитесь zrangebylex.
например. Мы хотим получить все строки о user_id 123456,
ZRANGEBYLEX user_index [123456 (123457
Он вернет все ключи HASH с префиксом 123456, а затем мы используем эту строку как HASH-ключ и hget или hmget для получения информации о том, что мы хотим.
[
означает включительно, а (
означает исключение. и почему мы используем 123457
? очевидно. Поэтому, когда мы хотим получить все строки с user_id, мы будем указывать верхнюю границу, чтобы сделать user_id строкой leftmost char значение ascii плюс 1.
Подробнее о lex index вы можете обратиться к статье, упомянутой выше.
Ответ 4
Вы можете попробовать apache mnemonic, запущенный intel. Ссылка - http://incubator.apache.org/projects/mnemonic.html. Он поддерживает беспроигрышные функции.
Ответ 5
Для read-dominant рабочей нагрузки MySQL MEMORY
engine должен работать нормально (запись DMLs блокирует всю таблицу). Таким образом, вам не нужно изменять логику поиска данных.
В качестве альтернативы, если вы в порядке с изменением логики поиска данных, Redis также является опцией. Чтобы добавить к тому, что описал @GuangshengZuo, ReJSON Redis динамически загружаемый модуль (для Redis 4+), который реализует хранилище документов сверху Редиса. Это может еще больше уменьшить требования к сортировке больших структур взад и вперед по сети.
Ответ 6
С помощью всего лишь 6 принципов (которые я собрал здесь), человек, настроенный SQL, очень легко адаптируется к подходу Redis. Вкратце они:
- Самое главное, не бойтесь генерировать много пар ключ-значение. Поэтому не стесняйтесь хранить каждую строку таблицы в другом ключе.
- Использовать тип данных хэш-карты Redis
- Имя ключа формы из значений первичных ключей таблицы разделителем (например, ":" )
- Сохранять оставшиеся поля как хэш
- Если вы хотите запросить одну строку, непосредственно формируйте ключ и извлекайте его результаты
- Если вы хотите запросить диапазон, используйте wild char "*" к вашему ключу. Но имейте в виду, что клавиши сканирования прерывают другие процессы Redis. Поэтому используйте этот метод, если вам действительно нужно.
Ссылка просто дает простой пример таблицы и как ее моделировать в Redis. Следуя этим 6 принципам, вы можете продолжать думать так же, как и обычные таблицы. (Конечно, без каких-либо не очень важных понятий, таких как CRUD, ограничения, отношения и т.д.)
Ответ 7
используя комбинацию Memcache и REDIS поверх MYSQL, приходит в ум.