Having the ability to set a TTL on the cache key is a critical feature of a cache, not something that can be tacked on later.
I always find these "don't use redis" posts kind of strange. Redis is so simple to operate at any scale, I don't quite get why it is important to remove it.
In similar vein, I’d always thought Redka (https://github.com/nalgeon/redka) was a neat idea since it gives you access to a subset of the Redis API backed by either SQLite or Postgres
This seems to be testing how the software is optimized for low core deployments… how does Postgres perform vary as you add more cores and ram? It’s the sort of software where I’d presume more cores and ram yields better performance. Assuming as always that mature systems software sees more many core perf engineering.
If you use an UNLOGGED table in Postgres as a cache, and your DB restarts, you no longer have a cache. Then your main table gets a huge spike in traffic and likely grinds to a halt.
This isn't a great test setup.
It's testing RTT rather than the peak throughput of Redis.
I'd suggest using Redis pipelining -- or better: using the excellent rueidis redis client which performs auto-pipelining. Wouldn't be surprising to see a 10x performance boost.
When I last benchmarked Redis vs. PostgreSQL for a simple k/v cache it was about ~1ms for PostgreSQL to fetch a key, and ~0.5ms for Redis with a similar setup as in this post (although I used "value bytea" instead of "value string" – I don't know if it matters, probably not; 1ms was fast enough that I didn't care to test).
I didn't measure setting keys or req/sec because for my use case keys were updated infrequently.
I generally find ms to be a more useful metric than reqs/sec or latency at full load, as this is not a typical load. Or at least wasn't for my use case.
Of course all depends on your use case etc. etc. In some cases throughput does matter. I would encourage everyone to run their own benchmarks suited to their own use case to be sure – should be quick and easy.
As I rule I recommend starting with PostgreSQL and using something else only if you're heavily using the cache or you run in to problems. Redis isn't too hard to run, but still just one less service to worry about. Or alternatively, just use a in-memory DB. Not always appropriate of course, but sometimes it is.
A difference of 0.5ms is negligible with single digit network latency. You would need significant batching to experience the effects of this difference.
Of course such sensitive environments are easily imaginable but I wonder why you'd select either in that case.
Having the ability to set a TTL on the cache key is a critical feature of a cache, not something that can be tacked on later.
I always find these "don't use redis" posts kind of strange. Redis is so simple to operate at any scale, I don't quite get why it is important to remove it.
In similar vein, I’d always thought Redka (https://github.com/nalgeon/redka) was a neat idea since it gives you access to a subset of the Redis API backed by either SQLite or Postgres
Came here to post this. I’m wondering how Redka will compare with Postgres (and Redis) in terms of performance though.
Edit: https://antonz.org/redka/#performance
I think you just convinced me to drop redis for my new project.
Definitely a premature optimization on my part.
“Premature optimization” typically refers to optimizing before profiling. Ie optimizing in places that won’t help.
Is redis not improving your latency? Is it adding complexity that isn’t worth it? Why bother removing it?
“Dropping” something from a “new” project is premature optimization?
Wherever you go, there you are.
Presumably adding Redis to a new project with no performance issues (yet?) is the premature optimisation.
I read it as dropping something that _had been_ a premature optimisation.
This seems to be testing how the software is optimized for low core deployments… how does Postgres perform vary as you add more cores and ram? It’s the sort of software where I’d presume more cores and ram yields better performance. Assuming as always that mature systems software sees more many core perf engineering.
If you use an UNLOGGED table in Postgres as a cache, and your DB restarts, you no longer have a cache. Then your main table gets a huge spike in traffic and likely grinds to a halt.
Same as the folks who use in-memory Redis. Is there something uniquely bad about Postgres for this situation?
If your cache is so performance critical that you can't lose the data then it sounds like you need a (denormalized) database.
This isn't a great test setup. It's testing RTT rather than the peak throughput of Redis.
I'd suggest using Redis pipelining -- or better: using the excellent rueidis redis client which performs auto-pipelining. Wouldn't be surprising to see a 10x performance boost.
https://github.com/redis/rueidis
Postgres also supports query pipelining - at it seems like the popular go Postgres client library pgx supports it: https://github.com/jackc/pgx/issues/1113#event-6964024724
The big with for Redis is pipelining IMO.
When I last benchmarked Redis vs. PostgreSQL for a simple k/v cache it was about ~1ms for PostgreSQL to fetch a key, and ~0.5ms for Redis with a similar setup as in this post (although I used "value bytea" instead of "value string" – I don't know if it matters, probably not; 1ms was fast enough that I didn't care to test).
I didn't measure setting keys or req/sec because for my use case keys were updated infrequently.
I generally find ms to be a more useful metric than reqs/sec or latency at full load, as this is not a typical load. Or at least wasn't for my use case.
Of course all depends on your use case etc. etc. In some cases throughput does matter. I would encourage everyone to run their own benchmarks suited to their own use case to be sure – should be quick and easy.
As I rule I recommend starting with PostgreSQL and using something else only if you're heavily using the cache or you run in to problems. Redis isn't too hard to run, but still just one less service to worry about. Or alternatively, just use a in-memory DB. Not always appropriate of course, but sometimes it is.
A difference of 0.5ms is negligible with single digit network latency. You would need significant batching to experience the effects of this difference.
Of course such sensitive environments are easily imaginable but I wonder why you'd select either in that case.
> A difference of 0.5ms is negligible with single digit network latency
Yes, that was my take-away.
When you benchmarked Postgres did you disable WAL for the cache table? That may minimize the difference.
Unlogged table, yes. 1ms is more than fast enough so I didn't look further.
Don't tell DHH
Didn't DHH just release a sqlite-only cache?
Solid Cache, default in Rails 8.
Doesn’t require SQLite.
Works with other DBs:
https://github.com/rails/solid_cache