Hacker News new | past | comments | ask | show | jobs | submit login
Is Redis a noSQL db, a cache, or a messaging server? (antirez.com)
59 points by akkartik on May 15, 2010 | hide | past | favorite | 22 comments



This needs repeating:

> This is how it is possible to write modular, scalable applications today: you need a very fast "global state" (the DB side), caching, ways to create queues of jobs as soon or later you need to process things in the background, and sometimes you need the ability to pass messages around in a pub/sub many-to-many scenario. And this things are converging, they are just different sides of the same things, at least when the DB part is designed as it is in Redis.


With Redis, memcached finally has a contender for most awesome cache... thing. However I'm surprised I don't see more benchmarks. Performance should be roughly the same unless there's huge I/O contention for persistent storing.


I'm a bit biased, but I'm not as optimistic as some.

memcached had a design similar to redis when I first got involved with it a few years ago. It was fine for a lot of systems, but didn't scale to the larger ones. It took a lot of work for us to get it to the point where it could saturate all of the cores you could give it.

If anyone can ever produce a benchmark where memcached does not perform better than redis, please file a bug in memcached, or at the very least, start a conversation.

The closest I've seen were tests that degraded to client tests. In one case, someone took a very poorly performing memcached client and compared it against a very well-tuned redis client and a couple of relational databases and showed that memcached was the slowest of all. sigh

In most of these cases, the test environments perform at the very least an order of magnitude slower than what I get on my development laptop (I have no trouble sustaining 90k writes per second with either of a simple c++ thing I threw together yesterday or my high level java client).

On real production-quality machines with good networks, 300-400k ops per second isn't hard to achieve. Even between two old "large" (2 core, 7GB) EC2 nodes, I've been doing 90k ops per second all day (which is somewhere around the point where they start to throttle my bandwidth).


Hello dlsspy, I never tested memcached, but I'm really sure about Redis numbers: you can get 150k ops/sec in a decent Linux box without problems, per core. So if you got 4 cores you can get 600k ops/sec, assuming you'll have enough bandwidth to saturate that.

I agree with you that if Redis performance is better than memcached there is to fill a bug or start a conversation, as there is something odd. Both are written in C and use multiplexing internally, against the same OSes. The performances should be very similar, or the memcached performances should be better as it supports less features.

Edit: p.s. can you please explain why running multiple memcached processes, one per core, was not good enough?


I'm certainly not trying to start a fight or anything, but there's a lot of bad testing out there, and people like trumpeting the results of such things.

Having more machines reduces the performance gained from multigets. This is often a pretty big performance boost. This is especially useful with synchronous clients that serialize requests across servers (which are very common in many popular languages because popular languages don't seem to encourage proper concurrency). Four times the number of servers will quite often make requests take four times longer.

Some of the memcached clients will do additional work to hash the keys using an independent node location key just to ensure locality of related data so the values can be retrieved more efficiently.


Sure, many tests are conducted in a wrong way, I fully agree.

About multi-gets, this is how Redis handle this, we have a concept called key tags, that I think it is very similar to the one you described. Basically a key in the form foo{bar} gets hashed in a special way, only the part inside {} is hashed ('bar' in my example).

So a client willing to optimize for multi get will use {user0}:name {user0}:surname and so forth. Well, not the perfect example as with Redis in this specific case you could use an Hash that is much more space efficient and will provide locality of related keys automatically.


is it too n00b/out-of-place of me to ask what went in to tuning memcached to do that? i'd love to pick your brain (and possibly eat them... creepy, right?)


The general path involves adding some locks around critical sections, then benchmarking until those locks bubble up, then reducing the number of locks, then repeating until your server has very little lock contention.

The process is pretty straightforward, but as you walk down the path, you end up with something that looks a bit different from where you started.


hmm, i'm clearly wrong, but it doesn't seem like there's any reason memcached couldn't be implemented completely locklessly... can't most of everything be done with CAS operations instead of taking out locks?


That's likely true. We're separating out storage engines and allowing people to write their own. Your engine doesn't need locks. The more stuff we can do in the core without them, the closer we get to your dream.

Lock-free hash tables without GC are kind of hard, but not possible. I'd certainly welcome a lock-free engine if you're working on one. :)


Redis isn't a direct competitor to memcached. The great thing about Redis (disk-backed cache) is actually a liability if you're using it like an L2 cache which is how memcached is intended to be used.

To be clear: in memcached you can effectively set-and-forget keys and never worry about running out of memory. It uses an LRU to figure out what to throw away when memory gets full. In Redis if you want to achieve that behavior you need to expire your keys, which is another round trip every time. That means expire alone is also not enough, because you could set the key successfully but fail to set the expire. That means you need to also keep track of all your keys and periodically do cleanup.

Redis is awesome, but I would definitely not use it to replace memcached except in the cases where I absolutely need the data to survive a reboot and am willing to go through the hassle of manually managing the cleanup of every key.


Hello, since 2.0 (RC1 is near now...) we have "SETEX" that is SET+EXPIRE in one operation, and with max-memory directive set when Redis runs out of memory will sample three random keys and will delete the one that is going to expire sooner. So this usage is actually supported.

What I think about Redis as a cache is that in many contexts the rich data types and operations supported allow better caching.

An example: oknotizie.virgilio.it is a large social news site, for this site I built a Redis cache where the "latest" news IDs are pushed into a Redis list, but they are also added to the MySQL DB that was formerly here.

So to paginate the "latest news" page I only use fast LRANGE calls against Redis, but if it will return a short read (the cache is empty since the Redis server was restarted) I'll use instead the MySQL server. This actually never happens and everything goes on Redis usually, but since there is no persistent storage needed in Redis side, it is actually a cache.

When a news is deleted I use LREM instead. And so forth.


Good to hear, but that algorithm isn't LRU, and LRU makes more sense when backing a cache.


Interestingly, I think if you tweaked it to be "Randomly sample three keys and blow away the LRU among them" it would be pretty close to a fully LRU implementation for a lot of typical workloads.

Consider a website where 10% of the cache is hot: you'd discard a single hot entry only once every thousand cache evictions. I think for a lot of sites that is likely to be Good Enough, depending on the impact of a cache miss.

Bonus: you can trivially tweak how sensitive that is by increasing the number of items to randomly sample.


To add my 2 cents here: I've been using both memcached and redis in various projects and for me they serve slightly different purposes.

For plain old caching I haven't (yet) had a need to use redis, which is younger and by nature more complex. RAM is so cheap nowadays, we just tend to stuff two memcached machines with 64G, which goes a ridiculously long way.

On the other hand, as antirez pointed out, redis shines when you need "a little more than caching". We have rolled a few custom queueing solutions on top of redis (similar to resque) and working with lists and the SUBSTR operation is an extremely pleasant experience.

Redis seems to be the optimal "roll-your-own-queue" toolkit at this point. We had some strong delivery- and persistence-guarantee requirements in our project but those were not a problem to meet with a simple WAL on the clients and a redis-pair. So far our solution wins over the previous rabbitmq setup big time in all areas (performance, reliability, complexity, transparency). It could have been done with memcached, but less efficiently due to the lack of the aforementioned list-operations.


LRU isn't a panacea. Maintaining a real LRU can involve non-trivial overhead. It also can have trouble predicting some access patterns. Random replacement can definitely out perform LRU, particularly for tree structures.


LRU has also memory overhead. So storing more data and using a less precise algorithm may be indeed better in some circumstances.

Also there is no way to mount a precise LRU schema that is O(1). O(log(N)) complexity is needed.


Do you know how memcached does it? Do they pay the performance overhead, or do they cheat in some way? I don't think perfect LRU is needed, but the general idea behind LRU works /very/ well for a memcached style cache.

Trying to achieve something similar using Redis by for example updating the expire on every read would be a bit of a pain and I think put extra load on the client and server. This isn't a complaint about Redis though, it has its own use cases which are wonderful and I have no objection to using both for their strengths.


It's not a cache because memcache is already all the cache we need. Not sure why you mention messaging server unless you're expecting listeners to poll the server instead of get told about events. So I think it's a noSQL DB.

For my practical uses I'm most interested in Redis as a backing store for distributed persistent redundant key-value stores like:

http://kumofs.sourceforge.net/ http://opensource.plurk.com/LightCloud/

And my requirements are: 1. Speed. Gobs of it. Ridiculous amounts of speed. 2. Data must get written to disk periodically and I don't care if you lose a few minutes worth when I lose a disk. I'd like some control over how much data I'm prepared to lose vs speed. 3. O(log N) scalability. 4. More interesting ways to sort, extract, modify and delete data stored in a key or multiple keys without impacting performance.

Thanks Salvatore for your hard work!!


"It's not a cache because memcache is already all the cache we need."

That's quite the display of logical thought there. Rottweilers aren't dogs because black labs are all the dog we need.


Just to clarify, there is no polling in redis blocking list ops. I believe the pub/sub doesn't require polling either. Given that, I can think of a lot cases where Redis will work fine as a messaging server. If you need a very sophisticated routing mechanism, you will need to look at a more dedicated solution. But if you can express the message routing in either the rpush/blpop style or in redis pub/sub, why not?


We've found the primitives that redis gave us to be sufficient even for a fairly complex routing design.

Rabbitmq (which we used previously) might still have an edge for very complex scenarios, but AMQP is generally a royal pain and we've had serious issues with rabbitmq reliability under load (and debugging the problems thereafter!).

Consequently we switched our hairy mix of bindings to a straightforward "LPUSH to everyone whom it may concern" and wouldn't look back.

That may be less efficient in theory, but the machine-load (i/o, CPU) went from "uh oh" to "barely measurable" for us. Even more importantly we now feel to have a much better grip on the system because if something goes wrong then we'll know where to look. In contrast rabbit was effectively a blackbox, which turned into a huge problem once it ceased to "just work".




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: