Out of Process в таблице базы данных памяти, которая поддерживает запросы для высокоскоростного кэширования

У меня есть таблица SQL, к которой обращаются постоянно, но меняются очень редко.

Таблица разделена по идентификатору пользователя, и у каждого пользователя есть много записей в таблице.

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

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

Хранилища Key Value, такие как Redis, оказываются неэффективными из-за накладных расходов по сериализации и десериализации таблицы в Redis и из нее.

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

Есть ли что-нибудь, что могло бы обеспечить Out of Process в таблице базы данных памяти, которая поддерживает запросы для высокоскоростного кэширования?

Поиск показал, что возможен вариант Apache Ignite, но я ищу более информированные предложения.

7 ответов

Решение

Поскольку он вне процесса, он должен выполнять сериализацию и десериализацию. Проблема, с которой вы сталкиваетесь, заключается в том, как уменьшить количество работ по сериализации / десерилизации. Если вы используете Redis' STRING типа, вы не можете уменьшить эту работу.

Тем не менее, вы можете использовать HASH решить проблему: сопоставить таблицу SQL с HASH,

Предположим, у вас есть следующая таблица: person: id(varchar), name(varchar), age(int)можно взять человека id в качестве ключа, и принять name а также age как поля. Если вы хотите найти чье-то имя, вам нужно только получить поле имени (HGET person-id name), другие поля не будут десериализованы.

Ignite - действительно возможное решение для вас, поскольку вы можете оптимизировать издержки сериализации / десериализации, используя внутреннее двоичное представление для доступа к полям объектов. Вы можете обратиться к этой странице документации для получения дополнительной информации: https://apacheignite.readme.io/docs/binary-marshaller

Кроме того, издержки доступа могут быть оптимизированы путем отключения опции копирования при чтении https://apacheignite.readme.io/docs/performance-tips

Совместное размещение данных по идентификатору пользователя также возможно с помощью Ignite: https://apacheignite.readme.io/docs/affinity-collocation

Как сказал @for_stack, Hash будет очень подходящим для вашего случая.

Вы сказали, что у каждого пользователя есть много строк в БД, проиндексированных user_id а также tag_id, Так что именно (user_id, tag_id) однозначно указывают одну строку. Каждый ряд является функциональным, в зависимости от этого кортежа, вы можете использовать кортеж в качестве HASH KEY.

Например, если вы хотите сохранить строку (user_id, tag_id, username, age), значения которой ("123456", "FDSA", "gsz", 20), в redis, вы можете сделать это:

HMSET 123456:FDSA username "gsz" age 30

Если вы хотите запросить имя пользователя с помощью user_id и tag_id, вы можете сделать так:

HGET 123456:FDSA username

Таким образом, каждый ключ Hash будет комбинацией 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, мы должны указать верхнюю границу, чтобы сделать значение ascii крайнего левого символа строки user_id плюс 1.

Подробнее о lex index вы можете сослаться на статью, которую я упомянул выше.

Имея всего 6 принципов (которые я собрал здесь), человеку, склонному к SQL, очень легко адаптироваться к подходу Redis. Вкратце они:

  1. Самое главное, не бойтесь генерировать множество пар ключ-значение. Поэтому не стесняйтесь хранить каждую строку таблицы в отдельном ключе.
  2. Использовать тип данных Redis ' hash map
  3. Имя ключа формы из значений первичного ключа таблицы разделителем (например, ":")
  4. Сохраните оставшиеся поля как хеш
  5. Если вы хотите запросить одну строку, непосредственно сформируйте ключ и получите его результаты
  6. Когда вы хотите запросить диапазон, используйте дикий символ "*" в направлении вашего ключа. Но учтите, что клавиши сканирования прерывают другие процессы Redis. Так что используйте этот метод, если вам действительно нужно.

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

Вы можете попробовать Apache Mnemonic, запущенный Intel. Ссылка - http://incubator.apache.org/projects/mnemonic.html. Поддерживает функции serdeless

Для чтения-доминирующей рабочей нагрузки MySQL MEMORY движок должен работать нормально (написание DML блокирует всю таблицу). Таким образом, вам не нужно менять логику поиска данных.

В качестве альтернативы, если вы согласны с изменением логики извлечения данных, тогда Redis также является опцией. Чтобы добавить к описанному @GuangshengZuo, есть динамически загружаемый модуль ReJSON Redis (для Redis 4+), который реализует хранилище документов поверх Redis. Это может еще больше снизить требования к распределению больших структур по сети.

Использование Memcache и REDIS в сочетании с MYSQL приходит в Mind.

Другие вопросы по тегам