Postgres and Redis Sitting in a Tree | In today’s world of polyglot persistence, it’s likely that companies will be using multiple data stores for storing and working with data based on the use case. Typically a company will
start with a relational database like Postgres and then add Redis for more high velocity use-cases. What if you could tie the two systems together to enable so much more?
12. By using redis_fdw
•Cache results without leaving Postgres
•Cross reference data
•Reduce complexity in app code
•Maybe even replace PG functionality
with that of Redis
23. neovintage::DB=> CREATE EXTENSION redis_fdw;
CREATE EXTENSION
neovintage::DB=> CREATE SERVER redis_server
neovintage::DB-> FOREIGN DATA WRAPPER redis_fdw
neovintage::DB-> OPTIONS (
neovintage::DB-> ADDRESS ‘127.0.0.1’,
neovintage::DB-> PORT ‘6379’
neovintage::DB-> );
CREATE SERVER
neovintage::DB=> CREATE USER MAPPING FOR PUBLIC
neovintage::DB-> SERVER redis_server OPTIONS (password ‘pass’);
CREATE USER MAPPING
47. Benefits
• Cross reference data in Postgres with high velocity
information
• Issue one query to take snapshots of counts in Redis.
Make data warehousing easier.
51. psudeo-code
FUNCTION get_top_commenters():
list = redis.get(“top:comments”)
time = redis.get(“top:comments:refresh_time”)
IF (Time.now - time) > 90
mutex do
list = SQL_DB("SELECT ... ORDER BY rank LIMIT …”)
redis.set(“top:comments”, list)
redis.set(“top:comments:refresh_time”, Time.now)
end
END
RETURN list
END
52. neovintage::DB=> d users
Table "public.users"
Column | Type | Modifiers
----------+---------+----------------------------------------------------
id | bigint | not null default nextval('users_id_seq'::regclass)
name | text |
comments | integer |
neovintage::DB=> select * from users;
id | name | comments
-----+---------+----------
1 | rimas | 10
2 | chuck | 10000
3 | lucy | 300
62. neovintage::DB=> INSERT INTO redis_set (cache_key, commenters)
(SELECT ‘mylist’
, array_agg(name) as top_commenters
FROM users
GROUP BY 1) as subquery
ON CONFLICT (cache_key)
DO UPDATE SET value = subquery.top_commenters
WHERE cache_key = ‘mylist’;
ERROR: there is no unique or exclusion constraint matching the ON
CONFLICT specification
63.
64. Challenges
• You will get errors if keys already exist in Redis
• sets, lists, zsets can be more of a challenge to update
in place if you have many processes trying to grab the
same key
• Unique constraints on foreign tables in postgres
aren’t a thing :-(
65. Tips
• Updates work well for scalar keys
• Atomic updates to lists, sets and zsets will require
some creativity
• If you’re going to use zset, try the singleton_key when
defining the foreign table in postgres.
• Get rid of nasty mutex code by running a cron job on a
periodic basis that executes update queries.