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. Вкратце они:
- Самое главное, не бойтесь генерировать множество пар ключ-значение. Поэтому не стесняйтесь хранить каждую строку таблицы в отдельном ключе.
- Использовать тип данных Redis ' hash map
- Имя ключа формы из значений первичного ключа таблицы разделителем (например, ":")
- Сохраните оставшиеся поля как хеш
- Если вы хотите запросить одну строку, непосредственно сформируйте ключ и получите его результаты
- Когда вы хотите запросить диапазон, используйте дикий символ "*" в направлении вашего ключа. Но учтите, что клавиши сканирования прерывают другие процессы 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.