繁体   English   中英

Memcached 与 Redis? [关闭]

[英]Memcached vs. Redis? [closed]

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

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

需要考虑的要点:

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

总结 (TL;DR)

2017 年 6 月 3 日更新

Redis 比 memcached 更强大、更流行、支持更好。 Memcached 只能做 Redis 能做的一小部分。 即使它们的功能重叠,Redis 也更好。

对于任何新事物,请使用 Redis。

Memcached 与 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 没有在没有 3rd 方工具的情况下转储到磁盘的机制。
  • 缩放:在您需要多个实例作为缓存之前,两者都为您提供了大量的空间。 Redis 包含可帮助您超越这些的工具,而 memcached 则没有。

内存缓存

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

它擅长于此,但仅此而已。 您可以通过它们的键以极高的速度访问这些值,这通常会使可用网络甚至内存带宽饱和。

当您重新启动 memcached 时,您的数据就消失了。 这对于缓存来说很好。 你不应该在那里存放任何重要的东西。

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

Redis

Redis 可以完成与 memcached 相同的工作,并且可以做得更好。

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

您可以关闭持久性,它也会在重新启动时愉快地丢失您的数据。 如果你想让你的缓存在重启后继续存在,它也可以让你这样做。 事实上,这是默认设置。

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

如果 redis/memcached 的一个实例不足以满足您的工作负载的性能,那么 redis 是明确的选择。 Redis 包括集群支持,并带有“开箱即用”的高可用性工具 ( redis-sentinel )。 在过去的几年里,redis 也成为 3rd 方工具的明显领导者。 Redis Labs、Amazon 等公司提供了许多有用的 Redis 工具和服务。 围绕 redis 的生态系统要大得多。 大规模部署的数量现在可能比 memcached 多。

Redis 超集

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

文档

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

redis.io是一个很棒的易于导航的资源。 它允许您在浏览器中尝试 redis,甚至为您提供文档中每个命令的实时交互式示例。

现在 redis 的 stackoverflow 结果是 memcached 的 2 倍。 Google 结果的 2 倍。 更多语言的更易于访问的示例。 更积极的发展。 更积极的客户开发。 这些测量单独可能没有多大意义,但它们结合起来描绘了一幅清晰的图景,即对 redis 的支持和文档更多且更新。

坚持

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

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

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

许多数据类型

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

字符串(命令

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

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

字符串对于各种用例都很有用,这就是 memcached 仅对这种数据类型非常有用的原因。

哈希(命令

哈希有点像键值存储中的键值存储。 它们在字符串字段和字符串值之间映射。 使用散列的字段->值映射比使用常规字符串的键->值映射的空间效率略高。

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

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

列表(命令

Redis 列表是字符串的有序集合。 它们针对从列表的顶部或底部(又名:左侧或右侧)插入、读取或删除值进行了优化。

Redis的提供许多命令为利用列表,包括命令到压入/弹出的项目,推/列表,截断列表之间弹出,执行范围查询等

列表是非常持久的、原子的、队列。 这些非常适用于作业队列、日志、缓冲区和许多其他用例。

设置(命令

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

这些对于访问控制列表、唯一访问者跟踪器和许多其他事物非常有用。 大多数编程语言都有类似的东西(通常称为 Set)。 就是这样,只有分布式。

Redis 提供了几个命令来管理集合。 存在明显的添加、删除和检查集等。 不那么明显的命令(例如弹出/读取随机项目)以及用于执行与其他集合的联合和交集的命令也是如此。

排序集(命令

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

此数据类型针对按分数快速查找进行了优化。 获取最高值、最低值或介于两者之间的任何值范围非常快。

如果您将用户连同他们的高分一起添加到排序集中,您就拥有了一个完美的排行榜。 当新的高分出现时,只需将它们以高分再次添加到集合中,它就会重新排列您的排行榜。 也非常适合跟踪用户上次访问的时间以及谁在您的应用程序中处于活动状态。

存储具有相同分数的值会导致它们按字典顺序排列(按字母顺序考虑)。 这对于自动完成功能之类的东西很有用。

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

地理

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

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

位图和 HyperLogLog

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

位图是我在Strings下引用的位级运算符的用途。 这种数据类型是 reddit 最近的协作艺术项目的基本构建块: r/Place

HyperLogLog 允许您使用恒定的极少量空间以惊人的精度计算几乎无限的唯一值。 仅使用约 16KB,您就可以有效地计算您网站的独立访问者数量,即使该数量以数百万计。

事务和原子性

redis 中的命令是原子的,这意味着您可以确保一旦向 redis 写入一个值,该值对所有连接到 redis 的客户端都是可见的。 无需等待该值传播。 从技术上讲,memcached 也是原子的,但是随着 redis 添加了除 memcached 之外的所有这些功能,值得注意的是,所有这些额外的数据类型和特性也是原子的,这有点令人印象深刻。

虽然与关系数据库中的事务不太一样,但 redis 也有使用“乐观锁定”( WATCH / MULTI / EXEC )的事务

流水线

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

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

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

发布/订阅

Redis 有专门用于发布/订阅功能的命令,允许 redis 充当高速消息广播器。 这允许单个客户端向连接到通道的许多其他客户端发布消息。

Redis 可以发布/订阅以及几乎所有工具。 RabbitMQ这样的专用消息代理可能在某些领域具有优势,但事实上,同一个服务器还可以为您提供持久耐用的队列和其他发布/订阅工作负载可能需要的数据结构,Redis 通常被证明是最好和最简单的工具为了工作。

Lua 脚本

您可以将lua 脚本视为 redis 自己的 SQL 或存储过程。 比这多或少,但类比大多有效。

也许您有想要 redis 执行的复杂计算。 也许您不能让您的事务回滚,并且需要保证复杂流程的每一步都将原子地发生。 这些问题以及更多问题都可以通过 lua 脚本来解决。

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

缩放

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

结论

对于任何新项目或尚未使用 memcached 的现有项目,我会毫不犹豫地推荐 redis 而不是 memcached。

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

Redis 可以完成 memcached 所做的一切,而且通常更好。 memcached 的任何性能优势都是次要的,并且是特定于工作负载的。 还有一些工作负载 redis 会更快,还有更多 redis 可以完成而 memcached 无法完成的工作负载。 面对巨大的功能鸿沟,微小的性能差异似乎微不足道,而且这两种工具都如此快速和高效,它们很可能是您不必担心扩展的最后一部分基础架构。

只有一种情况使 memcached 更有意义:memcached 已被用作缓存。 如果您已经使用 memcached 进行缓存,请继续使用它,如果它满足您的需求。 转移到 redis 可能不值得付出努力,如果您打算将 redis 仅用于缓存,它可能无法提供足够的好处,值得您花时间。 如果 memcached 不能满足您的需求,那么您可能应该转向 redis。 无论您需要扩展到 memcached 之外还是需要其他功能,这都是正确的。

使用 Redis 如果

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

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

  3. 持久性(您也将需要它,除非您对每次重启后都必须预热缓存没有问题。对于很少更改的对象非常重要)

使用 memcached 如果

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

根据我的经验,Redis 的稳定性比 Memcached 好得多

Memcached 是多线程的并且速度很快。

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

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

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

还需要考虑的一件事是,您是否希望对缓存实例设置严格的内存上限。

由于 redis 是一个具有大量功能的 nosql 数据库,而缓存只是它可以使用的一种选择,它会根据需要分配内存——放入的对象越多,它使用的内存就越多。 maxmemory选项不严格强制使用上限内存。 当您使用缓存时,密钥会被逐出并过期; 很可能您的密钥大小不同,因此会发生内部内存碎片。

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

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

话虽如此,在必须强制执行和/或可预测内存使用的环境中,memcached 仍然具有强大的地位。 我们尝试在 10-15k op/s 的工作负载下使用最新的稳定 redis (2.8.19) 作为非持久性基于 LRU 的 memcached 替代品,并且它泄漏了很多内存; 由于相同的原因,相同的工作负载在一天左右的时间内使 Amazon 的 ElastiCache redis 实例崩溃。

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

Redis 擅长做 key => SOME_OBJECT。

这真的取决于你要在那里放什么。 我的理解是,就性能而言,它们相当均匀。

也祝你好运找到任何客观的基准,如果你找到了一些,请把它们发送给我。

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

没有任何基准链接是完整的而不会让事情有点混乱,所以也请查看Dormondo 的 LiveJournalAntirez 博客上的一些相互冲突的基准。

编辑——正如 Antirez 指出的那样,Systoilet 分析相当不周全。 即使除了单线程不足之外,这些基准测试中的大部分性能差异也可以归因于客户端库而不是服务器吞吐量。 Antirez 博客上的基准测试确实提供了更多的苹果对苹果(同一张嘴)的比较。

我有机会在我使用过的缓存代理中同时使用 memcached 和 redis,让我与您分享我究竟在哪里使用了什么以及背后的原因......

Redis >

1) 用于索引缓存内容,在集群上。 我有超过 10 亿个键分布在 redis 集群中,redis 响应时间相当短且稳定。

2)基本上,它是一个键/值存储,所以无论在你的应用程序中你有什么类似的东西,你都可以使用 redis 麻烦很多。

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

内存缓存 >

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

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

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

如果您要求整体体验,Redis 非常绿色,因为它易于配置,非常灵活,具有稳定的强大功能。

此外,此链接上有一个基准测试结果,下面是相同的几个亮点,

在此处输入图片说明

在此处输入图片说明

希望这可以帮助!!

测试。 运行一些简单的基准测试。 很长一段时间我都认为自己是老派犀牛,因为我主要使用 memcached 并认为 Redis 是新来的。

在我目前的公司中,Redis 被用作主要缓存。 当我深入研究一些性能统计数据并开始测试时,Redis 在性能方面与 MySQL 相当或略

尽管 Memcached 很简单,但它完全将 Redis 炸了出来。 它的规模要好得多:

  • 对于更大的值(需要改变板坯尺寸,但有效)
  • 对于多个并发请求

此外,在我看来,memcached 驱逐策略实施得更好,从而在处理比缓存可以处理的数据更多的同时,使平均响应时间整体更稳定。

一些基准测试表明,在我们的例子中,Redis 的性能非常差。 我认为这与许多变量有关:

  • 运行 Redis 的硬件类型
  • 您存储的数据类型
  • 获取和设置的数量
  • 您的应用程序的并发性如何
  • 你需要数据结构存储吗

就个人而言,我不同意 Redis 作者对并发和多线程的看法。

另一个好处是可以非常清楚 memcache 在缓存场景中的行为方式,而 redis 通常用作持久性数据存储,尽管它可以配置为就像 memcached 一样,也就是在达到 max 时驱逐最近最少使用的项目容量。

我使用过的一些应用程序只是为了明确我们打算如何处理数据——内存缓存中的东西,我们编写代码来处理它不存在的情况——redis 中的东西,我们依赖它存在.

除此之外,对于大多数用例而言,Redis 通常被认为是优越的,因为它的功能更丰富,因此更灵活。

如果我们说redis是(缓存+数据结构)的组合,而memcached只是一个缓存,那就没有错了。

针对 redis-2.2.2 和 memcached 设置和获取 10 万个唯一键和值的非常简单的测试。 两者都在 linux VM(CentOS)上运行,我的客户端代码(粘贴在下面)在 Windows 桌面上运行。

Redis

  • 存储 100000 个值所花费的时间 = 18954ms

  • 加载 100000 个值所花费的时间 = 18328ms

内存缓存

  • 存储 100000 个值所需的时间 = 797ms

  • 检索 100000 个值所花费的时间 = 38984ms


Jedis jed = new Jedis("localhost", 6379);
int count = 100000;
long startTime = System.currentTimeMillis();
for (int i=0; i<count; i++) {
  jed.set("u112-"+i, "v51"+i);
}
long endTime = System.currentTimeMillis();
System.out.println("Time taken to store "+ count + " values is ="+(endTime-startTime)+"ms");

startTime = System.currentTimeMillis();
for (int i=0; i<count; i++) {
  client.get("u112-"+i);
}
endTime = System.currentTimeMillis();
System.out.println("Time taken to retrieve "+ count + " values is ="+(endTime-startTime)+"ms");

这里没有指出的一个主要区别是,Memcache 始终具有内存上限,而 Redis 默认没有(但可以配置为)。 如果您总是希望将键/值存储一段时间(并且永远不会因为内存不足而将其驱逐),那么您想要使用 Redis。 当然,你也有内存不足的风险......

如果您对性能感兴趣,Memcached 会更快,即使因为 Redis 涉及网络(TCP 调用)。 此外,内部 Memcache 速度更快。

正如其他答案所提到的,Redis 具有更多功能。

我们认为 Redis 是我们工作中项目的负载起飞。 我们认为通过在nginx使用一个名为HttpRedis2Module的模块或类似的东西,我们将获得惊人的速度,但是当使用 AB-test 进行测试时,我们被证明是错误的。

也许模块不好或者我们的布局不好,但这是一项非常简单的任务,使用 php 获取数据然后将其填充到 MongoDB 中甚至更快。 我们使用 APC 作为缓存系统,并使用 php 和 MongoDB。 它比nginx Redis 模块快得多。

我的建议是自己测试它,这样做会向您显示适合您环境的结果。 我们决定在我们的项目中使用 Redis 是不必要的,因为它没有任何意义。

剩下的最大原因是专业化。

Redis 可以做很多不同的事情,其中​​一个副作用是开发人员可能会开始在同一个实例上使用许多不同的功能集。 如果您将 Redis 的 LRU 功能用于非 LRU 硬数据存储的缓存,则完全有可能耗尽内存。

如果您要设置一个专用的 Redis 实例,仅用作 LRU 实例以避免出现这种特定情况,那么在 Memcached 上使用 Redis 并没有任何令人信服的理由。

如果您需要一个可靠的“永不停机”的 LRU 缓存……Memcached 将符合要求,因为它不可能在设计上耗尽内存,并且特殊功能可防止开发人员试图使其成为可能危及它的东西。 简单的关注点分离。

Redis 更好。

Redis的优点是,

  1. 它有很多数据存储选项,例如字符串、集合、排序集合、散列、位图。
  2. 记录的磁盘持久性
  3. 存储过程( LUA脚本)支持
  4. 可以使用 PUB/SUB 充当消息代理

Memcache是内存中的键值缓存类型系统。

  1. 不支持各种数据类型存储,如列表、redis 中的集合。
  2. 主要的缺点是 Memcache 没有磁盘持久性。

好吧,我大部分时候都使用我的应用程序,Memcache用于缓存会话,而redis用于理论/规范查询对象。 就性能而言,两者几乎相同。

是亚马逊提供的非常棒的文章/差异

与 memcached 相比,Redis 是一个明显的赢家。

Memcached 只有一个加分点,它是多线程的,速度很快。 Redis 有很多很棒的特性并且速度非常快,但仅限于一个核心。

Memcached 不支持 Redis 的优点

  • 快照 - 用户可以拍摄 Redis 缓存的快照并在任何时间点保留在二级存储上。
  • 对许多数据结构的内置支持,如 Set、Map、SortedSet、List、BitMaps 等。
  • 在 redis 中支持 Lua 脚本

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM