Personally I'd use memcached or some equivalent for strictly cacheing, and then bring on Redis with persistence if you need its data structures for e.g scoreboards.
At $WORK we never imported either, our cache layer for slow operations keeps its data in both the filesystem and a db table (used as a k/v store). The database helps coordinate thundering herd problems - this operation is being calculated by another thread, so just wait for it. Reads from the same server just hit the filesystem, and reads from another server hit the db once and then keep it in the filesystem. We could change the fs layer to memcached but so far it's working great.
Back in the mid-2000s I worked on a scaled system that used memcache, and developers fell victim to all the exact same problems that are cited with Redis in the article.
- Developers attempting to endrun every one of the laws of distributed systems by using memcache.
- We had cache addiction, so the fleets got sized on the assumption that memcache was up, and then memecache had a problem, and suddenly we were DDOSed.
- write amplification, where one host would nuke a high-TPS key and every other host would DDOS a dependency to repopulate the key.
- hot keys which led to hot hosts and because we cohosted memcached with the service daemons, it meant mystery CPU spikes.
- stickiness from stale DNS entries causing memcache calls to blackhole.
Every single one was avoidable by using memcache in a better way, but the temptation to abuse it was too strong.
* Outages where Valkey had no memory policy, ate all the memory, and then caused write errors to its append-only file. Bonus points for another one where the disk itself was full, and AOF writes failed.
* 500s where Redis was fully expected to be live, running, and populated with data for every user, and no fallback to a slower path.
* Creative uses of sorted sets and other data structures which depended on the sets never being evicted.
Despite the observations from the field, I think it's still hard to recommend memcache ahead of Redis. It can be difficult to architect an app to have a memcache-friendly cache layout.
I'd almost guarantee a large enough team using memcache will find a way to need Redis. And then we're maintaining 2 cache technologies.
More features mean more users. Some stick to the old stuff, some embrace the new, and eventually certain values become the de facto default, not really optional anymore.
Take Redis. Turn off AOF and it works as a volatile in memory cache. But most of us don't even think about it that way. So there is this argument that fewer features and simpler is better.(Memcached is such an example in this context) The so called 'straitjacket' approach. That makes total sense for big teams. But on the other hand, open source projects need regular updates to keep getting funding or contributions, so there is a built in tension.
And sometimes that leads to specialized forks or spin offs that excel in one niche area. My personal take? There is no right answer. It all depends on the context. Communication itself isn't free, after all
Perhaps that's because I'm not giving admin access to random people who think that Redis is a persistent storage, but honestly it's one of those technologies I'd describe as absolutely rock solid and well designed. The API is dead basic and every time I need to do something slightly weird, there's a sensible and well thought out way to achieve it.
The comparison is especially weird as memcached is also not persistent.
That said, it's interesting when you learn in practice that sometimes an N+1 problem is actually faster as N+1 than trying to query across separate DBMS systems.
I used it with Ruby on Rails for many years. It sped up pages, and just worked.
The downside (and upside for speed) is (and always was) that cache was saved in memory not disk. This meant hosting would be expensive if you have a large scale site with a wide amount of data to cache.
Solid cache has been a savior for those cases for me. We have over 100gb of cache for a project I'm working on, and it's stored in postgres on disk, with fast lookups with an index and expirations that happen automatically in Rails to delete those rows.
If I had a smaller cache need and was already using Redis, I'd probably just use that. But if speed was the number 1 factor, and I'd try benchmarking Memcached vs Redis.
Maybe the client libraries can help by returning nulls 10% of time, in dev mode?
at notion we use redis for a lot of things, but actual caching we leave to memcached
Just trying to get a sense of where people draw the line.
1) Wrap your client library so that it's impossible to store anything without an expiry date. You don't want 6-months-old data suddenly coming up in your app!
2) Either turn off persistence, or use a separate database for the cache. In other words, don't mix volatile data with stuff you actually care about.
3) Set up a reasonable maxmemory value with an appropriate maxmemory-policy, so that Redis doesn't eat up all your RAM.
4) Resist the urge to use complex data structures. If you try to update a single field on an expired hash, you will end up with an incomplete object.
If you don't want all that hassle, then yes, Memcached probably works better out of the box.
Never felt the need to go back to memcached except when a legacy dependency needed it.
One big tip I should recommend is to increase the default memory size limit to something more realistic for modern hardware (and arguably this should just be increased on the upstream's side as well, instead of making everyone reconfigure shitty defaults). It's very easy to exceed the memcached default key value, since it's just 1mb; the maximum size of memcached as a whole is 64mb, which is similarly very low. Outside of that, it works very well and the lack of persistence is great at making it not do things it's not supposed to do (which is a big problem with Redis' feature creep, the projects mainpage promoting AI drivel alone should point towards that.)
> Dealing with memcached downtime is incredibly easy, because client libraries generally ignore connection exceptions. For instance, a simple get will just return the default value (or none) if the server is down.
This is a terrible idea in the context of things that might use Redis. If you use Redis with some kind of complex state (say, a document if you're working on a Notion clone, for instance), wtf even is a "default value"? In fact, I actually also want to know when the thing is down.
> Clustering memcached is wonderful, because memcached actually has no clustering built-in.
Yeah bro, this is yet another one of the reasons people use Redis: it handles consensus and clustering for you. What even is this article? It's a master class in straw-manning architectural decisions: most people use hammers as hammers, but screwdrivers make great hammers too, especially if you also need to screw stuff in! I mean.. technically true?