摘要 (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 没有转储到磁盘的机制。
-
缩放:在您需要多个实例作为缓存之前,两者都为您提供了大量的空间。 Redis 包含的工具可帮助您超越这一点,而 memcached 则没有。
内存缓存
Memcached 是一个简单的易失性缓存服务器。它允许您存储键/值对,其中值被限制为不超过 1MB 的字符串。
它擅长于此,但仅此而已。您可以通过它们的键以极高的速度访问这些值,这通常会导致可用网络甚至内存带宽饱和。
当您重新启动 memcached 时,您的数据就消失了。这对于缓存来说很好。你不应该在那里存放任何重要的东西。
如果您需要高性能或高可用性,可以使用第三方工具、产品和服务。
redis
Redis 可以完成与 memcached 相同的工作,并且可以做得更好。
Redis 也可以act as a cache。它也可以存储键/值对。在 redis 中,它们甚至可以达到 512MB。
您可以关闭持久性,它也会很高兴在重新启动时丢失您的数据。如果您希望您的缓存在重新启动后仍然存在,那么您也可以这样做。事实上,这是默认设置。
它也非常快,但通常受到网络或内存带宽的限制。
如果一个 redis/memcached 实例的性能不足以满足您的工作负载,那么 redis 是明确的选择。 Redis 包括cluster support 并带有高可用性工具 (redis-sentinel) 就在“盒子里”。在过去的几年里,redis 也已成为 3rd 方工具的明显领导者。 Redis Labs、Amazon 等公司提供许多有用的 redis 工具和服务。 redis 周围的生态系统要大得多。大规模部署的数量现在可能比 memcached 多。
Redis 超集
Redis 不仅仅是一个缓存。它是一个内存数据结构服务器。您将在下面快速了解 Redis 可以做的事情,而不仅仅是像 memcached 这样的简单键/值缓存。 大部分 redis 的功能是 memcached 无法做到的。
文档
Redis 比 memcached 有更好的文档记录。虽然这可能是主观的,但似乎越来越真实。
redis.io 是一个很棒的易于导航的资源。它可以让您try redis in the browser 甚至为您提供文档中每个命令的实时交互式示例。
现在 redis 的 stackoverflow 结果是 memcached 的 2 倍。 2 倍的 Google 结果。更多语言的更易于访问的示例。更积极的发展。更积极的客户开发。这些测量值单独可能意义不大,但结合起来,它们清楚地描绘了对 redis 的支持和文档更强大和更新的清晰画面。
默认情况下,redis 使用一种称为快照的机制将数据持久化到磁盘。如果您有足够的 RAM 可用,它能够将所有数据写入磁盘而几乎不会降低性能。它几乎是免费的!
在快照模式下,突然崩溃可能会导致少量数据丢失。如果您绝对需要确保不会丢失任何数据,请不要担心,redis 也支持 AOF(仅附加文件)模式。在这种持久性模式下,数据可以在写入时同步到磁盘。这可以将最大写入吞吐量降低到磁盘可以写入的速度,但仍然应该很快。
如果需要,有许多配置选项可以微调持久性,但默认设置非常合理。这些选项可以轻松地将 redis 设置为存储数据的安全、冗余的地方。这是一个真实的数据库。
多种数据类型
Memcached 仅限于字符串,但 Redis 是一种数据结构服务器,可以提供许多不同的数据类型。它还提供了充分利用这些数据类型所需的命令。
最大为 512MB 的简单文本或二进制值。这是 redis 和 memcached 共享的唯一数据类型,尽管 memcached 字符串限制为 1MB。
Redis 通过提供用于按位运算、位级操作、浮点递增/递减支持、范围查询和多键操作的命令,为您提供了更多利用此数据类型的工具。 Memcached 不支持这些。
字符串对于各种用例都很有用,这就是 memcached 单独用于这种数据类型的原因。
哈希有点像键值存储中的键值存储。它们在字符串字段和字符串值之间映射。使用散列的字段->值映射比使用常规字符串的键->值映射更节省空间。
哈希可用作命名空间,或者当您想要对许多键进行逻辑分组时。使用哈希,您可以有效地获取所有成员、将所有成员一起过期、一起删除所有成员等。非常适合您有多个需要分组的键/值对的任何用例。
哈希的一个示例用途是在应用程序之间存储用户配置文件。使用用户 ID 作为键存储的 redis 哈希将允许您根据需要存储尽可能多的用户数据位,同时将它们存储在单个键下。使用哈希而不是将配置文件序列化为字符串的优点是,您可以让不同的应用程序读取/写入用户配置文件中的不同字段,而不必担心一个应用程序会覆盖其他应用程序所做的更改(如果您序列化过时,可能会发生这种情况数据)。
Redis 列表是有序的字符串集合。它们针对从列表的顶部或底部(又名:左侧或右侧)插入、读取或删除值进行了优化。
Redis 提供了许多commands 用于利用列表,包括推送/弹出项目的命令、列表之间的推送/弹出、截断列表、执行范围查询等。
列表是非常持久的原子队列。它们非常适用于作业队列、日志、缓冲区和许多其他用例。
集合是唯一值的无序集合。它们经过优化,可让您快速检查集合中是否存在值、快速添加/删除值以及测量与其他集合的重叠。
这些非常适合访问控制列表、唯一访问者跟踪器和许多其他内容。大多数编程语言都有类似的东西(通常称为 Set)。就是这样,只是分布式的。
Redis 提供了几个commands 来管理集合。存在诸如添加、删除和检查集合之类的明显操作。诸如弹出/读取随机项目以及与其他集合执行联合和交集的命令等不太明显的命令也是如此。
Sorted Sets 也是唯一值的集合。顾名思义,这些是有序的。它们按分数排序,然后按字典顺序排列。
此数据类型针对按分数快速查找进行了优化。获取最高值、最低值或介于两者之间的任何值范围都非常快。
如果您将用户连同他们的高分一起添加到排序集中,您就拥有了一个完美的排行榜。当新的高分出现时,只需将他们的高分再次添加到集合中,它就会重新排列您的排行榜。也非常适合跟踪用户上次访问的时间以及谁在您的应用程序中处于活动状态。
存储具有相同分数的值会使它们按字典顺序排列(按字母顺序排列)。这对于自动完成功能等功能很有用。
许多排序集commands 类似于集的命令,有时带有额外的分数参数。还包括用于管理分数和按分数查询的命令。
地理位置
Redis 有几个commands 用于存储、检索和测量地理数据。这包括半径查询和测量点之间的距离。
从技术上讲,redis 中的地理数据存储在排序集中,因此这并不是真正独立的数据类型。它更像是对有序集合的扩展。
位图和 HyperLogLog
与地理一样,这些不是完全独立的数据类型。这些命令允许您将字符串数据视为位图或超级日志。
位图是我在Strings 下引用的位级运算符的用途。这种数据类型是 reddit 最近合作艺术项目的基本构建块:r/Place。
HyperLogLog 允许您使用恒定的极小空间以惊人的准确性计算几乎无限的唯一值。仅使用大约 16KB,您就可以有效地统计您网站的唯一身份访问者的数量,即使该数字以百万计。
事务和原子性
redis 中的命令是原子的,这意味着您可以确定,只要将值写入 redis,该值对连接到 redis 的所有客户端都是可见的。无需等待该值传播。从技术上讲,memcached 也是原子的,但是随着 redis 在 memcached 之外添加所有这些功能,值得注意且令人印象深刻的是,所有这些额外的数据类型和特性也是原子的。
虽然与关系数据库中的事务不太一样,但 redis 也有使用“乐观锁定”的transactions (WATCH/MULTI/EXEC)。
流水线
Redis 提供了一个名为“pipelining”的功能。如果您有许多要执行的 redis 命令,您可以使用流水线将它们一次性发送到 redis,而不是一次一个。
通常,当您对 redis 或 memcached 执行命令时,每个命令都是一个单独的请求/响应周期。通过流水线,redis 可以缓冲多个命令并同时执行它们,在一个回复中响应所有命令的所有响应。
这可以让您在批量导入或其他涉及大量命令的操作时获得更大的吞吐量。
发布/订阅
Redis 有commands 专用于pub/sub functionality,允许redis 充当高速消息广播器。这允许单个客户端向连接到通道的许多其他客户端发布消息。
Redis 的发布/订阅功能与几乎所有工具一样。像RabbitMQ 这样的专用消息代理可能在某些领域具有优势,但事实上,同一台服务器还可以为您提供持久的持久队列和您的发布/订阅工作负载可能需要的其他数据结构,Redis 通常会被证明是最好和最简单的工具。
Lua 脚本
您可以将lua scripts 想象成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 还是需要其他功能,这都是正确的。