What is Redis and what is Memcached? Why use Redis and when Memcached? Way we can call Redis a NoSQL database? Today I want to present my conclusions about which cache engine to use? Redis versus Memcached.
What is Memcached?
Memcached is an in-memory kay-value storage system. We can store data with an expiration time of each value separately. It is the good option to succor for a bit systems with responses, like database requests (with resultsets), REST requests results (if we can), whole rendered pages results and others. But you can imagine different situations to use key-value like sessions, calculations delayed in time (when our number can or can not expire) or even to show some math results which you want to store just for a while.
It can be distributed on many servers, so we can estimate a risk. We can configure it to use two (or more servers) separately or combined, it depends on us that we care about total memory to use (from every server as one big Memcached memory) or safety (redundancy).
Genesis
Memcached is project which was written in Perl in 2003 but soon after it appears this is a good product, it was rewritten in C. Memcached is older then Redis and sometimes Redis is called “Memcache on steroids” so it describes that Redis have the same functionality as Memcached but it have other options, which Memcached don’t have. Redis was written at 2009 and from start it was written in ANSI C. Authors were also Memcached users and their goal was to build something better than Memcached, in many aspects, it is much better.
When Memcached?
When we don’t care about crashes, persistence, data lost and others problems we almost ever can choose Memcached. But it’s not obvious. We can have several instances to prevent data lost, we can consider which data can be stored to Memcached and which not, and so one.
There is one place when sometimes Redis can be worst – speed. Memcached can be faster but in most situation, Redis is the safest decision.
For example, we can use Memcached as a cache for rendered page and when we miscalculate the amount of memory we can have a big problem. If the whole cache breaks when we have a big traffic, it can be a big problem, when new, clean Memcached starts again, with no cache and everybody will receive a fresh new data straight from a tiny database. If database survived this, it can be killed when Memcached stops in next few minutes.
Redis have a couple of solutions for these case.
As first, when it fails we don’t lose data – Redis Persistence (next paragraph). As second, since Redis 2.0 we have a new toy, called Virtual Memory. It can be configured to use a file to store rarely used data or even when we have too many data and not enough memory we can start Redis with keys in memory (fast search) and values in files. Of course, this is a bad situation and we must solve the problem with RAM amount, but even in this environment, Redis is doing his job.
More Redis features
Persistence – Redis have 2 different methods to save data in disk: RDB and AOF.
The RDB persistence performs point-in-time snapshots of your dataset at specified intervals (one or more). It saves the files in RDB files which can be treated as backups.
The AOF persistence logs every operation and after the crash, it can restore one by one from this log. This is a more safe method when you want to use Redis more like a database, it can be the better choice. When the system starts again it can read every instruction and go back to last known state without data loss. Especially there is a smart Redis option to clean log when Redis is working when the log gets too big it can be rewritten on background, it runs a forked process to do it.
You can read more on Redis Documentation about how to use both of this methods at the same time.
Replication – it’s master-slave replication and Redis can have multiple slaves which are exact copies of masters. It’s well documented, it works and it have many useful options
Data Types – not only text values, serialized objects but also “Redis Lists”, “Redis Hashes”, “Redis Sets”, “Redis Sorted sets”, “Bitmaps and HyperLogLogs”. So if you want to add another value to your list, you use instruction LPUSH or RPUSH. If you use hashes, you use instructions HMSET, HGETALL, HSET, HGETALL. For “sets” you will be interested about SADD, SINTER, SPOP or SRANDMEMBER commands, and so on and so on.
Please refer to the introduction to Redis data types for information about those types.
Partitioning – as we know data are safe, so we can use the whole amount of all Redis servers RAM and use it as one, but how? This is obvious wen we use Redis as cache (whatever) but in other cases, we have to choose – I invite you to read.
Transactions – we can say that every operation on Redis is atomic, but even then, we can separate our data to store the whole set of values in atomic operations in one transaction. It’s nice, Memcached doesn’t have this. Buy it was a bad example, for this Redis have another tool – Redis Mass Insertion. For transactions this example is better:
WATCH watched_key
val = GET watched_key
val = val + 1
MULTI
SET mykey $val
EXEC
If “watched_key” have changed, the whole transaction fails.
Distributed locks
With Redis we can implement a DLM (Distributed Lock Manager) – yes it can handle it.
As authors say, it has 3 properties:
- Safety property: Mutual exclusion. At any given moment, only one client can hold a lock.
- Liveness property A: Deadlocks free. Eventually, it is always possible to acquire a lock, even if the client that locked a resource crashed or gets partitioned.
- Liveness property B: Fault tolerance. As long as the majority of Redis nodes are up, clients are able to acquire and release locks.
PHP RedLock simple demonstration
$servers = [
['127.0.0.1', 6379, 0.01],
['192.168.1.5', 6379, 0.01],
['192.168.1.5', 6389, 0.01],
];
$redLock = new RedLock($servers);
$locked = $redLock->lock('my_resource_name', 1000);
if ($locked){
//Do some stuff, without care about deadlock!
$redLock->unlock($locked);
}else{
//You can try again, do some delay or omit this part
}
This code can’t be easier to read but in few words. We have ‘my_resource_name‘ and we have it just for us or when is locked to another process we are simply excluded. Everybody knows what is going on. Of course, we can try again or do the construction with while(), but this was done in this one instruction lock(). It is possible to setup the number of retries (by default 3) and the retry delay (by default 200 milliseconds) used to acquire the lock.
This is a powerful functionality of Redis, you can read more on Redis Documentation or in the primary article on this page.
Conclusions, what Redis have that Memcached don’t?
- Persistence
- Replication
- Data types
- Locking
- Virtual Memory
- Partitioning
- Transactions
- Distributed locks
There are more examples how to use Redis, it have even a Publish/Subscribe messaging system (Simple demo to showcase Redis PubSub with EventMachine) but this article (as in subject) was about comparing Redis to Memcached.
Hope, this helps.
Have nice cache