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

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

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

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

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

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

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

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

16
SetiSeeker 1 Сен 2017 в 08:00

7 ответов

Лучший ответ

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

Однако вы можете использовать HASH для решения проблемы: сопоставить вашу таблицу SQL с HASH.

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

9
for_stack 1 Сен 2017 в 05:45

Как сказал @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

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

2
GuangshengZuo 6 Сен 2017 в 07:53

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

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

1
saaj 10 Сен 2017 в 11:55

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

Кроме того, издержки доступа можно оптимизировать, отключив параметр копирования при чтении https://apacheignite.readme.io/docs/performance-tips#section-do-not-copy-value-on-read

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

4
Denis 1 Сен 2017 в 11:03

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

1
Srini Sydney 7 Сен 2017 в 07:44

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

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

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

1
Mehmet Kaplan 11 Сен 2017 в 06:07

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

0
Sameer 12 Сен 2017 в 11:37