题 Memcached与Redis?


我们正在使用Ruby网络应用程序 Redis的 用于缓存的服务器。有没有必要进行测试 Memcached的 代替?

什么会给我们更好的表现? Redis和Memcached之间的任何优缺点?

需要考虑的要点:

  • 读/写速度。
  • 内存使用情况。
  • 磁盘I / O转储。
  • 缩放。

1138
2018-05-11 20:52


起源


除了以下评论之外的另一个分析: Google趋势:redis与memcached - MarkHu
一条评论无法回答:如果你正在寻找这两个系统的基于云的服务(例如heroku插件),无论出于何种原因,Memcached服务有时会相当便宜。 - Ben Roberts
为了可扩展性: Imgur和Twitter使用两者 - the_red_baron


答案:


摘要(TL; DR)

2017年6月3日更新

Redis比memcached更强大,更受欢迎,支持更好。 Memcached只能完成Redis可以做的一小部分事情。即使它们的特征重叠,Redis也会更好。

对于任何新的东西,请使用Redis。

Memcached vs Redis:直接比较

这两种工具都是功能强大,快速的内存数据存储,可用作缓存。两者都可以通过缓存数据库结果,HTML片段或生成可能很昂贵的任何其他内容来帮助加速您的应用程序。

要考虑的要点

当用于相同的事情时,这里是他们如何使用原始问题的“要点考虑”进行比较:

  • 读/写速度:两者都非常快。基准测试因工作负载,版本和许多其他因素而异,但通常显示redis与memcached一样快或几乎一样快。我推荐redis,但不是因为memcached很慢。不是。
  • 内存使用情况:Redis更好。
    • memcached:指定缓存大小,当您插入项目时,守护程序会快速增长到略大于此大小。除了重新启动memcached之外,从来没有真正的方法可以回收任何空间。您的所有密钥都可以过期,您可以刷新数据库,它仍然会使用您配置的完整RAM块。
    • redis:设置最大尺寸取决于您。 Redis永远不会使用超过它的内容,并且会给你不再使用的内存。
    • 我将100,000~2KB的随机句子(~200MB)存储到两者中。 Memcached RAM使用量增长到~225MB。 Redis RAM使用量增长到大约228MB。冲洗后,redis下降到~29MB,memcached保持在~225MB。它们在存储数据的方式上同样有效,但只有一个能够回收它。
  • 磁盘I / O转储:redis的明显胜利,因为默认情况下这样做并具有非常可配置的持久性。如果没有第三方工具,Memcached没有转储到磁盘的机制。
  • 缩放:在您需要多个实例作为缓存之前,两者都会为您提供大量的空间。 Redis包含的工具可以帮助您超越,而memcached则不会。

memcached的

Memcached是一个简单的易失性缓存服务器。它允许您存储键/值对,其中值限制为最大为1MB的字符串。

它很擅长,但就是这样。您可以通过其密钥以极高的速度访问这些值,通常会使可用网络饱和甚至占用内存带宽。

当你重新启动memcached时,你的数据就消失了。这适用于缓存。你不应该存储重要的东西。

如果您需要高性能或高可用性,则可以使用第三方工具,产品和服务。

Redis的

Redis可以执行与memcached相同的工作,并且可以更好地完成它们。

Redis可以 充当缓存 同样。它也可以存储键/值对。在redis中,它们甚至可以高达512MB。

您可以关闭持久性,它也会在重启时丢失您的数据。如果您希望缓存能够在重新启动后继续运行,那么您也可以执行此操作。事实上,这是默认值。

它也非常快,通常受到网络或内存带宽的限制。

如果一个redis / memcached实例的性能不足以满足您的工作负载,那么redis是明智的选择。 Redis包括 集群支持 并附带高可用性工具(Redis的哨兵)“在框中”。在过去几年中,redis也成为第三方工具的明显领导者。像Redis Labs,亚马逊等公司提供了许多有用的redis工具和服务。 redis周围的生态系统要大得多。现在,大规模部署的数量可能大于memcached。

Redis Superset

Redis不仅仅是一个缓存。它是内存中的数据结构服务器。下面您将快速了解Redis可以做的事情,而不仅仅是像memcached这样的简单键/值缓存。  redis的功能是memcached无法做到的事情。

文档

Redis比memcached更好地记录。虽然这可能是主观的,但它似乎越来越真实。

redis.io 是一个非常容易导航的资源。它可以让你 在浏览器中尝试redis 甚至为您提供文档中每个命令的实时交互式示例。

现在,redis的堆栈溢出结果是memcached的2倍。谷歌搜索结果的2倍。更容易访问更多语言的示例。更积极的发展。更积极的客户开发。这些测量结果可能并不是单独的,但结合起来,它们描绘了一个清晰的图景,即redis的支持和文档更新,更新。

坚持

默认情况下,redis使用称为快照的机制将数据持久保存到磁盘。如果您有足够的RAM可用,它可以将所有数据写入磁盘,几乎不会降低性能。它几乎是免费的!

在快照模式下,突然崩溃可能会导致少量数据丢失。如果你绝对需要确保没有数据丢失,请不要担心,redis也支持AOF(仅附加文件)模式。在此持久性模式下,数据可以在写入时同步到磁盘。这可以降低磁盘写入速度的最大写入吞吐量,但仍然应该非常快。

如果需要,有许多配置选项可以微调持久性,但默认值非常合理。通过这些选项,可以轻松将redis设置为存储数据的安全冗余位置。它是一个 真实 数据库。

许多数据类型

Memcached仅限于字符串,但Redis是一个可以提供许多不同数据类型的数据结构服务器。它还提供了充分利用这些数据类型所需的命令。

弦乐(命令

简单的文本或二进制值,最大可达512MB。这是唯一的数据类型redis和memcached共享,但memcached字符串限制为1MB。

通过提供用于按位运算,位级操作,浮点递增/递减支持,范围查询和多键操作的命令,Redis为您提供了更多利用此数据类型的工具。 Memcached不支持任何这些。

字符串对各种用例都很有用,这就是为什么memcached仅对这种数据类型非常有用。

哈希(命令

散列有点像键值存储中的键值存储。它们映射字符串字段和字符串值。使用散列的Field->值映射比使用常规字符串的key-> value映射稍微更节省空间。

哈希值可用作命名空间,或者您希望对多个键进行逻辑分组。使用哈希,您可以有效地获取所有成员,将所有成员一起过期,将所有成员一起删除等。非常适合您需要分组的多个键/值对的任何用例。

散列的一个示例使用是用于在应用程序之间存储用户简档。以用户ID作为密钥存储的redis哈希将允许您根据需要存储关于用户的多个数据位,同时将它们存储在单个密钥下。使用哈希而不是将配置文件序列化为字符串的优点是,您可以让不同的应用程序在用户配置文件中读/写不同的字段,而不必担心一个应用程序覆盖其他人所做的更改(如果序列化过时,可能会发生这种情况)数据)。

列表(命令

Redis列表是有序的字符串集合。它们经过优化,可以从列表的顶部或底部(也就是左侧或右侧)插入,读取或删除值。

Redis提供了很多 命令 用于利用列表,包括推送/弹出项目的命令,列表之间的推送/弹出,截断列表,执行范围查询等。

列表使持久,原子,队列。这些对于作业队列,日志,缓冲区和许多其他用例非常有用。

套装(命令

集是唯一值的无序集合。它们经过优化,可让您快速检查集合中是否存在值,快速添加/删除值以及测量与其他集合的重叠。

这些非常适合访问控制列表,独特的访问者跟踪器和许多其他内容。大多数编程语言都有类似的东西(通常称为Set)。就像这样,只是分发。

Redis提供了几个 命令 管理集。存在明显的添加,删除和检查集合。因此,不太明显的命令如弹出/读取随机项目以及用于执行联合和与其他集合交叉的命令。

分类集(命令

排序集也是唯一值的集合。顾名思义,这些是有序的。他们按照分数排序,然后按字典顺序排列。

此数据类型已针对按分数快速查找进行了优化。获得最高,最低或任何范围的值都非常快。

如果您将用户添加到排序集以及他们的高分,您将拥有一个完美的排行榜。随着新的高分进入,只需再次以高分将它们添加到该组中,它将重新排序您的排行榜。也非常适合跟踪用户上次访问的时间以及在您的应用程序中处于活动状态的用户。

存储具有相同分数的值会导致按字典顺序排序(按字母顺序排列)。这对于自动完成功能等功能非常有用。

许多排序集 命令 类似于集合的命令,有时带有额外的分数参数。还包括用于管理分数和按分数查询的命令。

地理

Redis有几个 命令 用于存储,检索和测量地理数据。这包括半径查询和测量点之间的距离。

技术上,redis中的地理数据存储在有序集中,因此这不是真正独立的数据类型。它更像是排序集之上的扩展。

位图和HyperLogLog

与geo一样,这些并不是完全独立的数据类型。这些命令允许您将字符串数据视为位图或超级日志。

位图是我引用的位级运算符 Strings 是给。这种数据类型是reddit最近的协作艺术项目的基本构建块: R /地点

HyperLogLog允许您使用恒定的极小空间来计算几乎无限的唯一值,并具有令人震惊的准确性。仅使用~16KB即可有效计算您网站的唯一身份访问者数量,即使该数字为数百万。

交易和原子性

redis中的命令是原子的,这意味着只要将值写入redis,就可以确保连接到redis的所有客户端都可以看到该值。没有等待该值传播。从技术上讲,memcached也是原子的,但是redis在memcached之外添加了所有这些功能,值得注意的是,所有这些额外的数据类型和功能都是原子的。

虽然与关系数据库中的事务不完全相同,但redis也有 交易 使用“乐观锁定”(//EXEC)。

流水线

Redis提供了一个名为'的功能流水线”。如果您要执行许多redis命令,可以使用流水线技术将它们一次性发送到redis,而不是一次一个地发送。

通常,当您执行redis或memcached命令时,每个命令都是一个单独的请求/响应周期。使用流水线技术,redis可以缓冲多个命令并一次执行所有命令,并在单个回复中响应所有命令的所有响应。

这可以让您在批量导入或涉及大量命令的其他操作上实现更高的吞吐量。

发布/订阅

Redis有 命令 致力于 发布/子功能,允许redis充当高速消息广播器。这允许单个客户端将消息发布到连接到通道的许多其他客户端。

Redis确实有pub / sub以及几乎任何工具。专门的消息经纪人喜欢 的RabbitMQ 可能在某些方面具有优势,但同一服务器也可以为您的发布/订阅工作负载可能提供持久的持久队列和其他数据结构,Redis通常被证明是最佳和最简单的工具。

Lua Scripting

你可以想到 lua脚本 就像redis自己的SQL或存储过程一样。它的内容越来越少,但这种类比大多有效。

也许你想要redis执行复杂的计算。也许你不能让你的交易回滚并且需要保证复杂过程的每一步都会以原子方式发生。使用lua脚本可以解决这些问题以及更多问题。

整个脚本以原子方式执行,因此如果您可以将逻辑放入lua脚本中,则通常可以避免搞乱乐观锁定事务。

缩放

如上所述,redis包含对集群的内置支持,并与其自己的高可用性工具捆绑在一起 redis-sentinel

结论

我会毫不犹豫地为任何新项目或者尚未使用memcached的现有项目推荐redc over memcached。

以上可能听起来像我不喜欢memcached。相反:它是一种强大,简单,稳定,成熟和强化的工具。甚至有一些用例比redis快一点。我喜欢memcached。我认为这对未来的发展没有多大意义。

Redis做了memcached所做的一切,通常更好。 memcached的任何性能优势都是次要的,并且特定于工作负载。还有一些工作负载,其中redis会更快,而redis可以执行的工作负载更多,而memcached根本无法完成。面对功能上的巨大鸿沟以及这两种工具如此快速和高效的事实,微小的性能差异似乎很小,它们很可能是您需要担心扩展的最后一块基础设施。

memcached只有一个场景更有意义:memcached已经被用作缓存。如果您已经使用memcached进行缓存,那么请继续使用它,如果它满足您的需求。转移到redis可能不值得,如果你打算使用redis进行缓存,它可能无法提供足够的好处来值得花时间。如果memcached不能满足您的需求,那么您应该转向redis。无论您是需要扩展到memcached还是需要其他功能,都是如此。


1642
2018-06-29 06:54



Memcached如何以服务器本身存在的方式提供集群?我一直使用散列算法或模数分布到memcached服务器池的库。 Redis也是如此。我主要使用Python,似乎有很多模块不依赖于memcached库来处理连接池。 - whardier
“具有乐观锁定的交易(WATCH / MULTI / EXEC)” - Redis没有正确的交易。即如果[multi,cmd1,cmd2,cmd3(例外),exec]则执行cmd1和cmd2。 - Oleg
@Oleg实际上并不是真的。如果你使用multi-exec命令被缓冲(即:不执行),直到exec发生,所以如果你在exec之前有一个异常,那么实际上没有命令执行。如果调用exec,则所有缓冲的命令都以原子方式执行,当然,除非首次调用multi,否则watch变量已被更改。后一种机制是乐观锁定部分。 - Carl Zulauf
@whardier你是对的。更新的答案反映了memcached的群集“支持”由其他工具启用。应该研究得更好。 - Carl Zulauf
如何使用couchbase服务器进行群集? (memcached兼容) - Ken Liu


如果使用Redis

  1. 您需要有选择地删除/过期缓存中的项目。 (你需要这个)

  2. 您需要能够查询特定类型的键。 EQ。 'blog1:posts:*','blog2:categories:xyz:posts:*'。哦耶!这个非常重要。使用此选项可以有选择地使某些类型的缓存项无效。您也可以使用它来使片段缓存,页面缓存,给定类型的AR对象等无效。

  3. 持久性(你也需要这个,除非你的缓存在每次重启后都必须预热。对于很少改变的对象非常重要)

使用memcached if

  1. Memcached让你头疼!
  2. 嗯...聚集? MEH。如果你要走那么远,使用Varnish和Redis来缓存片段和AR对象。

根据我的经验,我使用Redis比Memcached有更好的稳定性


128
2017-07-05 06:04



Redis文档说使用模式需要进行表扫描。 blog1:posts:*可能需要进行O(N)表扫描。当然,由于Redis速度很快,因此在合理大小的数据集上仍然很快。测试或管理员应该没问题。 - wisty
Headached 是个玩笑,对吧? :-)我google了 memcached头疼 但没有找到任何合理的东西。 (我是Memcached和Redis的新手) - KajMagnus
投 下 出于同样的原因而不是@pellucide。 Redis可能比Memcached更好,但Memcached很容易使用。我从来没有遇到任何问题,配置起来很简单。 - Diego Jancic
谢谢@KajMagnus让我的一天......可能是整个星期 - alex


Memcached是多线程和快速的。

Redis具有很多功能并且非常快,但完全限于一个核心,因为它基于事件循环。

我们两个都用。 Memcached用于缓存对象,主要是减少数据库的读取负载。 Redis用于排序集合之类的东西,这些集合可以方便地汇总时间序列数据。


76
2018-05-03 16:41



在memcached中投入大量资金且在“用户配置文件”类似非关系数据上存在数据库瓶颈的高流量站点应该进行评估 couchbase 与通常的Mongo,Redis平行 - Barry
@siliconrockstar - 非常确定Redis 3仍然是单核心;至少AWS Redis(使用3.2.6或3.2.10)警告在查看例如时考虑到这一点 EngineCpuUtilization指标 - dwanderson
看起来你是对的,我想当我发表评论时,我的基础是不完整的来源。删除了评论。 - siliconrockstar
但你仍然可以启动Redis的$ core_count实例 - Imaskar


这太长了,不能作为对已经接受的答案的评论发布,所以我把它作为一个单独的答案

还有一点需要考虑的是,您是否希望缓存实例具有硬性内存上限。

由于redis是一个具有大量功能的nosql数据库,缓存只是一个可以使用的选项,它会根据需要分配内存 - 放入的对象越多,它使用的内存就越多。该 maxmemory 选项不严格执行内存上限使用。当您使用缓存时,密钥被逐出并过期;机会是你的键大小不一样,所以内部内存碎片发生。

默认情况下,redis使用 jemalloc 内存分配器,它尽量使用内存紧凑和快速,但它是一个通用的内存分配器,它无法跟上大量的分配和高速率的对象清除。因此,在某些加载模式上,由于内部碎片,redis进程显然会泄漏内存。例如,如果您的服务器具有7 Gb RAM并且您希望将redis用作非持久性LRU缓存,则可能会发现redis进程与 maxmemory 随着时间的推移设置为5Gb将使用越来越多的内存,最终达到总RAM限制,直到内存不足的杀手干扰。

memcached更适合上述场景,因为它以完全不同的方式管理其内存。 memcached分配一大块内存 - 它将需要的一切 - 然后使用自己实现的内容自行管理这个内存 slab分配器。此外,memcached努力将内部碎片保持在低水平,实际上也是如此 使用per-slab LRU算法,当考虑对象大小完成LRU驱逐时。

话虽如此,memcached仍然在环境中具有强势地位,其中必须强制执行和/或可预测内存使用。我们试图在10-15k op / s的工作负载中使用最新的稳定redis(2.8.19)作为基于嵌入式非持久性LRU的memcached替换,并且它泄漏了内存A LOT;由于同样的原因,相同的工作负载在一天左右的时间内导致亚马逊的ElastiCache redis实例崩溃。


68
2018-03-02 11:13



从 redis.io/topics/faq: Redis具有内置保护功能,允许用户设置内存使用的最大限制,使用配置文件中的maxmemory选项限制Redis可以使用的内存。如果达到此限制,Redis将开始回复错误以写入命令(但将继续接受只读命令),或者您可以将其配置为在使用Redis时达到最大内存限制时逐出密钥用于缓存。如果您打算将Redis用作LRU缓存,我们会提供文档。  链接 - StefanNch
@StefanNch redis' maxmemory 选项不考虑内部内存碎片。有关详细信息,请参阅上面的评论 - 我在“Redis作为LRU缓存”页面中描述的情况下看到了我所描述的问题,其中启用了内存限制选项。另一方面,memcached使用不同的方法来避免内存碎片问题,因此其内存限制更加“难”。 - artyom


Memcached很擅长做一个简单的键/值存储,并擅长做key => STRING。这使得它非常适合会话存储。

Redis擅长做key => SOME_OBJECT。

这真的取决于你将要放在那里。我的理解是,就性能而言,它们非常均匀。

如果你确实找到了一些亲切的发送方式,也可以找到任何客观的基准测试。


44
2018-05-11 23:27



IMO Redis Hash数据类型对于存储会话变量比将它们序列化为memcached字符串更有意义。 - Carl Zulauf
如果您关心用户体验,请不要将会话放在缓存中。 dormando.livejournal.com/495593.html - sleblanc
@sebleblanc这在理论上不应该是Redis的问题,因为还有磁盘持久性。 - haknick
@sebleblanc memcache仍然擅长会话存储,你实现它很差或没有。是驱逐是一个问题,但不是无法克服的,如果你不担心驱逐,也不是内存问题。我相信大多数memcache会话解决方案都使用cookie作为备份。 - Erik Petersen
“不要把你的会话放在缓存中”是误导性的。你的意思是“不要只在缓存中存储你的会话”。任何只在memcache中存储重要数据的人都应立即解雇。 - Jacob


如果你不介意粗鲁的写作风格, Redis vs Memcached 在Systoilet博客上值得从可用性的角度阅读,但在得出关于性能的任何结论之前,一定要在评论中来回阅读;有一些方法问题(单线程繁忙循环测试),Redis自从撰写文章以来也做了一些改进。

没有基准链接是完整的而不会让事情有点混乱,所以也请查看一些冲突的基准 多尔蒙多的LiveJournal 和 Antirez博客

编辑  - 正如Antirez所指出的那样,Systoilet分析是相当错误的。即使超出单线程不足,这些基准测试中的大部分性能差异都可归因于客户端库而不是服务器吞吐量。基准点 Antirez博客 确实提出了更多的苹果对苹果(同嘴)比较。


36
2018-06-15 22:38



该 Redis vs Memcached 基准是错误的构思。oldblog.antirez.com/post/redis-memcached-benchmark.html - App Work
你不是在开玩笑。 - ocodo
超过2010年,过时的博客 - Siddharth


我有机会在我使用过的缓存代理中同时使用memcached和redis,让我分享一下我在哪里使用了什么和背后相同的原因....

Redis>

1)用于通过群集索引缓存内容。我有超过十亿个密钥分布在redis集群上,redis响应时间非常少且稳定。

2)基本上,它是一个键/值存储,所以在你的应用程序中你有类似的东西,人们可以使用redis打扰很多。

3)Redis持久性,故障转移和备份(AOF)将使您的工作更轻松。

Memcache>

1)是的,可以用作缓存的优化内存。我使用它来存储缓存内容,访问频率非常高(50次点击/秒),大小小于1 MB。

2)当我的单个内容大小> 1MB时,我在memcached中只分配了16GB中的2GB。

3)当内容增长接近极限时,偶尔我会在统计数据中观察到更高的响应时间(而不是redis的情况)。

如果您要求整体体验,Redis非常环保,因为它易于配置,具有稳定可靠的功能,非常灵活。

此外,还有一个基准测试结果 链接 ,下面是几个相同的高光,

enter image description here

enter image description here

希望这可以帮助!!


18
2017-10-16 10:20