В PostgreSQL есть замечательная функция, называемая Foreign Data Wrappers (FDW), которая позволяет ему напрямую подключаться к внешним системам . Хотя настройка может быть немного сложной, когда она станет доступной, вы можете запускать запросы с объединениями или подзапросами к ним, вставлять данные, создавать представления и т. Д. Heroku значительно упростил процесс использования FDW с PostgreSQL и Redis благодаря Data Links . Давайте попробуем это.
«Посмотрите, как @Heroku упростила использование сторонних упаковщиков данных с Postgres и Redis».
Ссылки на данные
Ранее мы использовали связи данных с Heroku PGBackups, когда использовали их для подключения нашей действующей базы данных PostgreSQL к недавно восстановленной резервной копии. Это позволило нам выполнить запрос к обоим, чтобы перезагрузить случайно удаленные данные. Это было круто, я знаю … но мы только царапали поверхность.
PostgreSQL потрясающий. Это опыт «как я когда-либо жил без этого», как только вы ощутите его доброту . Но, несмотря на его особенности, у него все еще есть варианты использования, для которых он не идеален, как любая другая реляционная база данных. Оболочки сторонних данных фактически устраняют эту проблему, позволяя вам разгрузить части ваших данных, которые лучше подходят для других систем, и в то же время позволяют PostgreSQL взаимодействовать с ними и запрашивать их так же, как если бы они находились в любой другой таблице.
Оказывается, Redis отлично подходит почти для всех случаев, когда PostgreSQL может быть не идеальным. Как хранилище данных в памяти, оно идеально подходит для прямых запросов с высоким трафиком как для чтения, так и для записи, включая специальные структуры данных, такие как отсортированные наборы, данные с истекшим сроком, pubsub и многое другое. Эти структуры обеспечивают уровень функциональности наравне с общими объектами в многопоточной системе, без необходимости иметь дело с мьютекс-блокировками и ограничениями единой системы общих объектов в многопоточной системе.
«Redis отлично подходит почти для всех случаев, когда PostgreSQL может быть не идеальным».
Когда вы сложите их вместе, вам будет трудно найти проблему с данными, которую вы не можете решить, и которая не сводится просто к перерастанию машины. Данные ссылки соединяют их. Пожалуйста.
Присоединиться
Не стесняйтесь проходить через эти примеры кода со мной. Однако следует помнить, что Heroku Data Links доступна только для баз данных Heroku PostgreSQL производственного уровня, использующих версии 9.4 и выше. Это означает, что вам придется заплатить, чтобы играть. Подробные инструкции можно найти здесь , но чтобы мы могли быстрее показать себя, я собираюсь пропустить.
Как только ваша база данных производственного уровня настроена с использованием приложения для начинающих Ruby , подготовьте Heroku Redis и затем свяжите их так:
$ heroku pg:links create REDIS_URL DATABASE_URL --as hredis
И увидеть, что это сработало:
$ heroku pg:links
=== DATABASE_URL (postgresql-vertical-7958)
==== redis_sinuous_9442
Created: 2015-09-11 03:44 UTC
Remote: REDIS_URL (redis-sinuous-9442)
Remote Name: redis_sinuous_9442
=== HEROKU_POSTGRESQL_ONYX_URL (postgresql-vertical-7958)
==== redis_sinuous_9442
Created: 2015-09-11 03:44 UTC
Remote: REDIS_URL (redis-sinuous-9442)
Remote Name: redis_sinuous_9442
Отлично! Теперь давайте повеселимся.
Запрос к внешним данным
Данные заставляют мир вращаться, но запись на диск создает большую нагрузку на машину, чем почти все остальное. Счетчики являются хорошим примером для иллюстрации проблемы, потому что вы можете использовать счетчик практически для всего. Это могут быть счетчики просмотров, счетчики регулирования использования, счетчики загрузок, счетчики общего доступа, счетчики кликов и т. Д. Как правило, записи базы данных связаны с тем, что вы считаете, будь то запись в блоге, запись пользователя или что-то еще.
PostgreSQL не рискует с вашими данными, настаивая на том, чтобы они были записаны на диск, прежде чем он сообщит вам, что запись прошла успешно. Redis может записывать на диск с интервалом, например каждую секунду, что позволяет ему обрабатывать логику, подобную этой, намного быстрее.
Вот быстрый тест на приращение 25 записей в 10 одновременных потоках 50000 раз, так что все ясно:
p = Benchmark.measure do
threads = []
10.times { threads << Thread.new { puts Benchmark.measure { 50000.times { |i| Widget.increment_counter(:stock, (i % 25) + 1) } }.real } }
threads.each { |thr| thr.join }
end
puts "PostgreSQL: #{p.real} seconds"
PostgreSQL: 258.2195017640479 seconds
r = Benchmark.measure do
threads = []
10.times { threads << Thread.new { puts Benchmark.measure { $redis.pipelined { 50000.times { |i| $redis.incr "widget:#{(i % 25) + 1}" } } }.real } }
threads.each { |thr| thr.join }
end
puts "Redis: #{r.real} seconds"
Redis: 4.218563660047948 seconds
Когда они связаны через Data Link, я могу запустить запрос в PostgreSQL, чтобы объединиться с данными Redis и включить его в результаты моего запроса, например, так:
SELECT w.id, w.name, w.stock, r.value my_counter
FROM widgets w
INNER JOIN hredis.redis r ON r.key = CONCAT('widget:',w.id)
ORDER BY r.value DESC
Поскольку это просто другой запрос, я могу создать представление из этого. Или я могу создать Dataclip для отправки по офису.
Это всего лишь один вариант использования, но вы должны получить представление о том, как на данный момент вы можете включить оперативные аналитические данные в свои запросы. Для выполнения более сложных запросов вы можете периодически записывать необходимые значения в столбец кэша в PostgreSQL с помощью одного оператора INSERT / UPDATE, непосредственно ссылающегося на Redis. Это значительно упрощает объединение функциональности PG для запуска полнотекстового поиска, который географически ограничен данными PostGIS и оперативными / популярными данными о популярности. Есть много возможностей, которые открываются.
Push Data Out
К сожалению, на данный момент ссылка Redis доступна только для чтения. Когда функциональность FDW расширяется, чтобы использовать преимущества логики записи , она открывает намного больше дверей, таких как использование триггера для записи данных в Redis или Memcached при их обновлении.
В очень высокопроизводительных средах это может помочь полностью разгрузить определенный трафик чтения из PostgreSQL, позволяя ему передавать изменения в кеширование напрямую, гарантируя, что управление кешем или его истечение больше не являются проблемой. Чтобы снять опасения по поводу любых ограничений прямой оболочки, вы всегда можете использовать поведение LISTEN / NOTIFY с внешним сценарием, чтобы передавать изменения непосредственно в кэши.
Удачной ссылки!