相比于 memcached,Redis 更强大,更流行,更好的支持。Memcached 仅能完成 Redis 所有功能中的一小部分。即使对于其特性重叠的部分,Redis 也更为优秀。

对于新项目,请使用 Redis。

Memcached vs Redis: 直接比较

作为缓存,两个工作都是强大,快速,有用的内存数据存储。两者都可以通过缓存数据库结果,HTML片段或是任何其他生成较为昂贵的内容有助于加速你的应用。

考虑点

当用于相同的目的时,下面是就原始问题的 ”考虑点“,他们如何比较。

  • 读写速度:两者都非常快。虽然不同版本或者不同负载等因素都对速度有影响,但是总的来说,redis几乎和memcached一样快。我推荐redis的原因并不是因为memcached速度慢,memcached也是很快的。
  • 内存占用:Redis更优。
    • memcached: 你可以指定缓存大小,不过当插入数据时,守护进程会马上增加一点缓存的大小。如果不重启memcached,那么增加的这一点缓存不会被释放。当所有key都过期,然后你flush数据库以后,你会发现memcached仍然占用一整块你分配给它的RAM。
    • redis:分配多大的内存都由你决定。Redis永远不会占用比规划的空间更多的内存,而且在不再用时,会释放内存。
    • 我做过这样的测试,存储随机的大小为100,000~2KB的字符串(共200MB)到两者中。memcached占用RAM最多225MB,redis占用最多228MB。清空数据之后,redis内存占用掉到29MB,而memcached仍然在225MB。它们在存储数据方面都很高效,不过只有一个能释放不再用的内存。
  • dump数据到硬盘:redis显然更胜一筹,因为redis自带导出dump的功能,并且可以灵活配置持久化。memcached如果没有第三方库不能dump数据。
  • 使用规模:两者都可以在处理大量数据时使用。不过redis有辅助工具可以指导你,memcached没有。

memcached

Memcached 是一个简单的可变缓存服务器。它允许你存储键/值对,而且其值被限制为至多 1MB 的字符串。

它擅长于此,而这也是它的全部工作。你可以以极高的速度通过键访问这些值,经常使得可用网络甚至是内存带宽得到饱和。

当你重启 memcached 时你的数据会丢失。这对于缓存是可以的。你不应该在那里存储任何重要的内容。

如果你需要高性或高可用性,有一些第三方工作,产品与服务可供选择。

redis

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

redis也可以用来做缓存服务,它也可以存储键值对,存储大小甚至可以到512MB。

你可以不用持久化,redis也会在重启后丢失数据。你也可以在重启之后仍然有数据,这是redis的默认功能。

redis的存取也很快,常常受限于网络或者内存。

如果单实例的redis/memcached对于你来说性能不佳,redis集群是个更好的选择。redis包括对集群的支持,并且有现成的高可用工具(redis-sentinel)。在过去的几年里,redis在第三方支持库里是领军地位。一些公司,比如 Redis Labs、Amazon 提供了许多有用的redis工具和服务。redis的生态系统更大。redis的使用范围比memcached广得多。

Redis  超集

Redis 不止是一个 cache。它是一个内存数据结构服务器。接下去你可以快速了解, redis除了能像memcached一样作为键值缓存之外,还能干些什么。大部分redis的功能是memcached不具备的

文档

Redis的文档比memcached更好。虽然这可能有点主观,但似乎越来越正确。

redis.io 是个非常容易导航的文档资源。能让你在浏览器中试用redis,甚至还给文档中的每个命令都提供了实时交互示例。

目前,stackoverflow上的帖子数或Google的结果数量,redis都是memcached的2倍。更多可访问的语言示例,更积极的发展,更积极的客户端开发。这些指标也许并不意味着什么, 但综合起来可以明显看出, redis的支持力度更大且文档更新。

持久化

Redis默认使用一种被称为“快照“的机制来持久化数据。在机器有足够的内存的情况下,它可以把所有的数据都写入到磁盘,并且几乎不引起性能的下降。使用该机制的成本几乎为零。

在快照模式下,一次服务的崩溃可能会引起少量的数据丢失。如果你不能接受任何数据丢失,也不用担心,Redis还提供了AOF(追加文件)模式。在这种模式下,数据可以实时的被同步到磁盘上。这样会使Redis写数据的速度降到磁盘写数据的速度水平,但是这样也还是很快的。

如果需要,可以有许多配置选项来调优持久性,但默认值非常合理。这些选项可以很容易地安装Redis作为一种安全、存储数据冗余的地方。它是一个真实的数据库。

更多的数据类型

memcached是有限的字符串,但redis是一个数据结构,服务器可以提供许多不同的数据类型。它还提供了使用这些数据类型所需的命令。

字符串(命令)

简单的文本或二进制值可以到512 MB。这是唯一的数据类型复述和memcached份额,尽管memcached字符串仅限于1 MB。

Redis 通过使用命令,如位操作、位级操作、浮点递增/递减支持、范围查询和多键操作,为您提供了更多的工具来使用这种数据类型。 memcached 不支持以上命令。

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

Hashes (命令)

Hashes 有点像键值存储中的键值存储。 他们映射字符串字段和字符串值。 使用 hash 的字段 - >值映射比使用常规字符串的键 - >值映射稍微多一点空间效率。

命名空间或是当你想要有逻辑地把许多键分组时,哈希表就是很有效的。使用哈希表,您可以高效地把握住所有部分,将所有失效的部分聚在一起,一起删除这些部分等。这个方法非常适用于任何需要分组的多个键/值所对应的用例。

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

列表 (命令)

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

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

列表使持久性、原子性、队列变得非常重要。这些对于工作队列、日志、缓冲区和许多其他用例非常有用。

集合 (命令)

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

这尤其适用于访问控制列表,唯一的访问跟踪等其他类似场景。大多数编程语言都有类似的东西(通常称为 Set)。 只不过 Redis 可以是分布式的。

Redis 提供了一些 命令 来操作集合。常用的有添加、删除、检查集合是否存在。不常用的有移除或获取集合中的一个随机元素,以及与其他集合进行交集或并集的操作。

有序集合 (命令)

有序集合也是不允许有重复值的集合。顾名思义,这些集合中的成员是有序的。他们首先按照分数排序,然后再按照字典序排序。

这种数据类型的优化目的是通过分数做快速查询。获取最大值,最小值或任何范围的值的速度是非常快的.

如果你将用户及其对应的最高分添加到一个有序集合(sorted set), 你将拥有一个完美的排行榜。 新的高分数进来,只需再一次添加进集合中,排行榜会重新进行排序。这对于跟踪用户上一次访问的时间以及当前活跃的用户也非常有用。

同样的分数的值将使用字母排序 (think alphabetically). 这对于自动补齐提示等特性很有用。

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

Geo

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

严格来说,redis 中的地理位置是存储在有序集合中,因此它并不是真正独立的数据类型。 它更像是有序集合的扩展。

Bitmap 和 HyperLogLog

与 geo 一样,它们都不是完全独立的数据类型。 这些命令允许您将字符串数据视为 bitmap 或 hyperloglog。

bitmap 指的是我在 Strings 小节下提到的位级操作符。 这种数据类型是reddit 近期合作艺术项目 r/Place 的基本构建模块。

HyperLogLog 允许您使用固定的极少量空间来以令人震惊的准确度计算几乎无限的唯一值。 只使用大约 16KB,您可以高效地统计您网站的唯一访问者的数量,即使该数字是数百万。
 

事务和原子性

redis 中的命令是原子的,这意味着您可以确保只要向 redis 写入值,该值对连接到 redis 的所有客户端都可见。 没有值传播延时。 严格来说,memcached 也是原子的,但是比起 redis 添加的所有这些功能,这并不值得一提。令人印象深刻的是,所有这些额外的数据类型和特性也是原子的。

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

管道

Redis 提供了一种称为“管道(pipelining)”的功能。 如果你想要执行多个 redis 命令,你可以使用管道将它们一次发送到 redis,而不是一次发送一个。

通常,当您执行 redis 或 memcached 命令时,每个命令都是一个单独的请求/响应循环。 借助管道技术,redis 可以缓存多个命令并一次执行所有命令,并在单个回复中响应所有命令的所有响应。

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

发布/订阅

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

Redis拥有几乎任何工具都有的发布/订阅。 像RabbitMQ这样的专用消息代理可能在某些方面有优势,但事实上同一台服务器,也可以为你的发布/订阅负载,尽可能的提供持久的持久队列和其他数据结构,为此Redis通常会被证明是跑任务最好,最简单的工具。

Lua 脚本

你可以认为 lua scripts 是redis自己的SQL或存储过程。可能不太准确,但大致类似。

也许你有复杂的计算需要redis执行。也许你不能承受事务回滚,需要保证一个复杂的过程原子化执行。它们都可以通过Lua脚本解决。

整个脚本是原子化执行的,所以如果你能将你的逻辑通过Lua脚本实现,通常可以避免被乐观锁事务干扰。

扩展性

前面提到过,redis有对集群的内建支持,也有自己的高可用工具,redis-sentinel。

结论

毫无疑问,对于任何新项目或者没有在用memcached的老项目,我更推荐redis。

这篇文章可能让人觉得我不喜欢memcached。事实上我很喜欢memcached,因为它是一个简洁、稳定、成熟的工具。有些时候它甚至要比redis还要快。虽然我喜欢memcached,但它的应用前景确实不够好。

其实Redis几乎能做到memcached能做到的一切,甚至更好。memcached的所有性能优势都不明显,而且需要在特定的业务场景下。在一些业务场景下redis会更快,还有更多的业务场景下redis可以做到memcached做不到的性能。对于巨大的功能差异,以及两种工具都非常快也非常有效率,这些微小的性能差异几乎可以忽略,它们很可能是您的基础架构的最后一部分,您其实不必过多担心使用哪个的问题。

只有在一种场景memcached是更适用的:已经使用memcached来作缓存了。 如果你已经用memcached作缓存了,而且它也正好满足你的需求,那么就继续使用它。 如果你只是使用redis来缓存,那么移值到redis可能不那么值得,它可能没有那么多值得你花时间的优点。 如果memcached并不能满足你的需求,那么你应该转向使用redis。 无论您需要在memcached上扩展还是需要别的功能,情况都是如此。