Memcached 与 Redis:直接比较
需要考虑的要点
当用于同样的事情时,以下是他们如何使用原始问题的“要考虑的要点”进行比较:
- 读/写速度:两者都非常快。基准测试因工作负载、版本和许多其他因素而异,但通常显示 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-sentinel)。在过去的几年里,redis也已成为第三方工具领域的明显领导者。Redis Labs、Amazon 等公司提供了许多有用的 redis 工具和服务。redis周围的生态系统要大得多。大规模部署的数量现在可能比 memcached 的数量要多。
Redis Superset
Redis 不仅仅是一个缓存。它是一个内存中数据结构服务器。下面,您将快速了解 Redis 可以做的事情,而不仅仅是像 memcached 这样的简单键/值缓存。redis 的大多数功能都是 memcached 无法做到的。
文档
Redis 比 memcached 有更好的文档记录。虽然这可能是主观的,但它似乎一直越来越真实。
redis.io 是一个非常容易导航的资源。它允许您在浏览器中试用 redis,甚至为您提供文档中每个命令的实时交互式示例。
现在,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 提供了许多用于利用列表的命令,包括推送/弹出项目、在列表之间推送/弹出、截断列表、执行范围查询等命令。
列表是持久的、原子的、队列。这些非常适合作业队列、日志、缓冲区和许多其他用例。
- 集合(命令)
集合是唯一值的无序集合。它们经过优化,可让您快速检查某个值是否在集合中,快速添加/删除值,并测量与其他集合的重叠。
这些非常适合访问控制列表、独特的访客跟踪器和许多其他东西。大多数编程语言都有类似的东西(通常称为 Set)。就是这样,只是分布式。
Redis 提供了多个命令来管理集。存在明显的功能,例如添加、删除和检查集合。不太明显的命令(如弹出/读取随机项)以及用于执行与其他集合的并集和交集的命令也是如此。
- 有序集合(命令)
排序集也是唯一值的集合。顾名思义,这些是有序的。它们按分数排序,然后按词典顺序排列。
此数据类型针对按分数快速查找进行了优化。获取最高、最低或介于两者之间的任何值范围都非常快。
如果您将用户连同他们的高分一起添加到排序集,您就拥有了一个完美的排行榜。当新的高分出现时,只需将他们再次添加到他们的高分中,它就会重新排列您的排行榜。也非常适合跟踪用户上次访问的时间以及谁在您的应用程序中处于活动状态。
存储具有相同分数的值会导致它们按字典顺序排序(按字母顺序排列)。这对于自动完成功能等功能非常有用。
许多排序的集合命令类似于集合的命令,有时还带有附加的 score 参数。还包括用于管理分数和按分数查询的命令。
Geo(地理)
Redis 具有多个用于存储、检索和测量地理数据的命令。这包括半径查询和测量点之间的距离。
从技术上讲,redis 中的地理数据存储在排序集中,因此这不是一个真正独立的数据类型。它更像是排序集之上的扩展。
Bitmap 和 HyperLogLog
与 geo 一样,这些不是完全独立的数据类型。这些命令允许您将字符串数据视为位图或超日志。
位图是我在下面引用的位级运算符的用途。这种数据类型是 reddit 最近合作艺术项目 r/Place 的基本构建块。Strings
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
结论
如果让我选择,我会毫不犹豫的选择 redis 而不是 memcached 用于任何新项目或尚未使用 memcached 的现有项目。
以上听起来好像我不喜欢 memcached。相反:它是一种强大、简单、稳定、成熟和硬化的工具。甚至在某些用例中,它比 redis 快一点。我爱memcached。我只是认为这对未来的发展没有多大意义。
Redis 可以做 memcached 所做的一切,而且通常做得更好。memcached 的任何性能优势都是次要的,并且特定于工作负载。还有一些工作负载的 redis 会更快,还有更多的工作负载 redis 可以做,而 memcached 根本做不到。面对功能上的巨大鸿沟,微小的性能差异似乎微不足道,而且这两种工具都非常快速和高效,它们很可能是您不得不担心扩展的基础架构的最后一部分。
只有一种情况 memcached 更有意义:memcached 已用作缓存。如果您已经在使用 memcached 进行缓存,那么如果它满足您的需求,请继续使用它。迁移到 redis 可能不值得付出努力,如果您打算仅将 redis 用于缓存,它可能无法提供足够的好处来值得您花时间。如果 memcached 不能满足您的需求,那么您可能应该迁移到 redis。无论您是需要扩展到 memcached 之外,还是需要其他功能,都是如此。