如果 Redis 已经是堆栈的一部分,为什么 Memcached 仍然与 Redis 一起使用?

Redis 可以做 Memcached 提供的所有事情(LRU 缓存、项目过期,现在在版本3中集群化。X + ,目前还处于测试阶段)或者使用 twemxy 这样的工具。性能也差不多。此外,Redis 还增加了持久性,因此在服务器重新启动时不需要进行缓存预热。

参考一些比较 Redis 和 Memcache 的老答案,其中一些更喜欢 Redis 作为 Memcache 的替代品(如果已经存在于堆栈中) :

尽管如此,通过研究大型网络公司如 Instagram、 Pinterest、 Twitter 等,我发现他们使用 Memcached 和 Redis 的目的不同,而不是使用 Redis 进行主缓存。主缓存仍然是 Memcached,Redis 用于其基于逻辑缓存的数据结构。

截至2014年,为什么 memcached 仍然值得作为附加组件添加到您的堆栈中,而您已经有一个 Redis 组件可以做 memcached 可以做的所有事情?除了已经存在的 Redis 之外,还有什么有利的地方可以让架构师/工程师继续使用 memcached?

更新:

对于我们的平台,我们已经完全放弃了 Memcached,并使用 redis 来满足普通和逻辑缓存需求 性能良好、灵活可靠。

以下是一些例子:

  • 按特定模式列出所有缓存键,并读取或删除它们的值。在 reis 中非常容易,在 memcached 中不能(容易地)做到。
  • 在 memcached 中存储超过1mb 的有效负载,这很容易做到,需要对板块大小进行调整,这有其自身的性能副作用。
  • 当前缓存内容的简单快照
  • Redis 集群和语言驱动程序都已经准备就绪,因此集群部署也很容易。
16536 次浏览

Habits are hard to break :)

Seriously though, there are two main reasons - to my understanding - why Memcached is still used:

  1. Legacy - there developers that are comfortable and familiar with Memcached, as well as applications that support it. This also means that it is a mature and well-tested technology.
  2. Scaling - standard Memcached is easily horizontally scalable, whereas Redis (until and excluding the soon-to-be-released v3) requires more work to that end (i.e. sharding).

However:

  1. Re. legacy - given Redis' robustness (data structures, commands, persistence...), it being actively developed and clients in every conceivable language - new applications are usually developed with it.
  2. Re scaling - besides the upcoming v3, there are solutions that can make scaling much easier. For example, Redis Cloud offers seamless scaling without data loss or service interruption. Another popular approach to scaling/sharding Redis is twemproxy.

The main reason I see today as an use-case for memcached over Redis is the superior memory efficiency you should be able to get with plain HTML fragments caching (or similar applications). If you need to store different fields of your objects in different memcached keys, then Redis hashes are going to be more memory efficient, but when you have a large number of key -> simple_string pairs, memcached should be able to give you more items per megabyte.

Other things which are good points about memcached:

  • It is a very simple piece of code, so if you just need the functionality it provides, it is a reasonable alternative I guess, but I never used it in production.
  • It is multi-threaded, so if you need to scale in a single-box setup, it is a good thing and you need to talk with just one instance.

I believe that Redis as a cache makes more and more sense as people move towards intelligent caching or when they try to preserve structure of the cached data via Redis data structures.

Comparison between Redis LRU and memcached LRU.

Both memcached and Redis don't perform real LRU evictions, but only an approximation of that.

Memcache eviction is per-size class and depends on the implementation details of its slab allocator. For example if you want to add an item which fits in a given size class, memcached will try to remove expired / not-recently-used items in that class, instead to try a global attempt to understand what is the object, regardless of its size, which is the best candidate.

Redis instead tries to pick a good object as a candidate for eviction when the maxmemory limit is reached, looking at all the objects, regardless of the size class, but is only able to provide an approximately good object, not the best object with the greater idle time.

The way Redis does this is by sampling a few objects, picking the one which was idle (not accessed) for the longest time. Since Redis 3.0 (currently in beta) the algorithm was improved and also takes a good candidates pools across evictions, so the approximation was improved. In the Redis documentation you can find a description and graphs with details about how it works.

Why memcached has a better memory footprint than Redis for simple string -> string maps.

Redis is a more complex piece of software, so values in Redis are stored in a way more similar to objects in a high level programming language: they have associated type, encoding, reference counting for memory management. This makes Redis internal structure good and manageable, but has an overhead compared to memcached which only deals with strings.

When Redis starts to be more memory efficient

Redis is able to store small aggregate data types in a special memory saving way. For example a small Redis Hash representing an object, is stored internally not with an hash table, but as a binary unique blob. So setting multiple fields per object into an hash is more efficient than storing N separated keys into memcached.

You can, actually, store an object into memcached as a single JSON (or binary-encoded) blob, but contrary to Redis, this will not allow you to fetch or update independent fields.

The advantage of Redis in the context of intelligent caching.

Because of Redis data structures, the usual pattern used with memcached of destroying objects when the cache is invalidated, to recreate it from the DB later, is a primitive way of using Redis.

For example, imagine you need to cache the latest N news posted into Hacker News in order to populate the "Newest" section of the site. What you do with Redis is to take a list (capped to M items) with the newest news inserted. If you use another store for your data, and Redis as a cache, what you do is to populate both the views (Redis and the DB) when a new item is posted. There is no cache invalidation.

However the application can always have logic so that if the Redis list is found to be empty, for example after a startup, the initial view can be re-created from the DB.

By using intelligent caching it is possible to perform caching with Redis in a more efficient way compared to memcached, but not all the problems are suitable for this pattern. For example HTML fragments caching may not benefit from this technique.