Memcached与Redis?

我们正在使用一个Ruby Web应用程序与Redis服务器进行caching。 有没有点testingMemcached呢?

什么会给我们更好的performance? Redis和Memcached之间有什么优点或缺点?

要考虑的要点:

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

总结(TL; DR)

2017年6月3日更新

Redis比memcached更强大,更受欢迎,支持更好。 Memcached只能完成Redis能做的一小部分事情。 Redis甚至在function重叠的地方也更好。

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

Memcached vs Redis:直接比较

这两个工具都是function强大,快速的内存数据存储,可用作caching。 两者都可以通过caching数据库结果,HTML片段或其他任何可能成本高昂的代码来帮助加快应用程序的速度。

要考虑的事项

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

  • 读/写速度 :两者都非常快。 基准因工作负载,版本和许多其他因素而异,但一般显示redis与memcached一样快或几乎一样快。 我build议redis,但不是因为memcached速度慢。 不是。
  • 内存使用情况 :Redis更好。
    • memcached:你可以指定caching的大小,当你插入物品时,守护进程会快速增长到超过这个大小。 从来没有真正的方法来回收任何空间,重启memcached。 所有的密钥都可能过期,你可以刷新数据库,它仍然会使用你configuration的全部RAM。
    • redis:设置最大尺寸取决于您。 Redis将永远不会使用超过它的内存,并会给你回忆它不再使用的内存。
    • 我把100,000〜2KB的string(〜200MB)的随机句存入两者。 Memcached内存使用增长到〜225MB。 Redis的内存使用量增长到了228MB。 冲洗之后,redis下降到29MB,memcached停留在〜225MB。 它们在存储数据的方式上也是同样高效的,但只有一个能够回收。
  • 磁盘I / O转储 :Redis明确的胜利,因为默认情况下,它具有非常可configuration的持久性。 Memcached没有第三方工具转储磁盘的机制。
  • 扩展 :在你需要多于一个实例作为caching之前,两者都会给你提供很大的空间。 Redis包含的工具可以帮助你超越memcached而不是memcached。

memcached的

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

这很好,但是就是这样。 您可以通过密钥以极高的速度访问这些值,经常使可用networking甚至内存带宽饱和。

当你重新启动memcached你的数据不见了。 这对caching很好。 你不应该存储那里重要的东西。

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

Redis的

Redis可以和memcached做同样的工作,并且可以做得更好。

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

你可以closures持久性,它也会很高兴地在重新启动时丢失你的数据。 如果你想让你的caching重新启动,它可以让你做到这一点。 事实上,这是默认的。

它也是超快的,往往受networking或内存带宽的限制。

如果redis / memcached的一个实例对于您的工作负载来说性能不足,那么redis是明确的select。 Redis包含集群支持,并在“框中”右侧附带高可用性工具( redis-sentinel )。 在过去的几年里,Redis也成为第三方工具领域的领导者。 像Redis实验室,亚马逊等公司提供了许多有用的Redis工具和服务。 redis周围的生态系统要大得多。 大规模部署的数量现在可能大于memcached。

Redis Superset

Redis不仅仅是一个caching。 这是一个内存数据结构服务器。 下面你会发现Redis可以做的事情,不仅仅是像memcached这样简单的键/值caching。 redis的大部分function都是memcached无法做到的。

文档

Redis比memcached有更好的文档logging。 虽然这可能是主观的,但似乎一直是越来越真实。

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

现在redis的memcached的stackoverflow结果是2x的两倍。 两倍的谷歌结果。 更多的语言更易于访问的例子。 更积极的发展。 更积极的客户端开发。 这些测量可能没有多less意义,但是结合起来,他们可以清楚地看出,redis的支持和文档更新且更新。

坚持

默认情况下,redis使用称为快照的机制将数据保存到磁盘。 如果有足够的内存,就可以将所有数据写入磁盘,而性能几乎没有下降。 这几乎是免费的!

在快照模式下,突然崩溃可能会导致less量数据丢失。 如果你绝对需要确保没有数据丢失,不要担心,redis也有你的背部AOF(追加文件)模式。 在这种持久性模式下,数据可以在写入时同步到磁盘。 这可以减less最大的写入吞吐量,但是速度却可以让磁盘写得更快,但是速度应该还是相当快的。

如果需要,有许多configuration选项可以微调持久性,但默认值是非常明智的。 这些选项使安装redis成为一个安全,冗余的地方来存储数据变得非常容易。 这是一个真正的数据库。

许多数据types

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

string( 命令 )

简单的文本或二进制值,最大可达512MB。 这是redis和memcached共享的唯一数据types,尽pipememcachedstring被限制为1MB。

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

string对于各种用例都是有用的,这就是为什么memcached对于这种数据types非常有用的原因。

哈希( 命令 )

散列有点像一个关键值存储中的关键值存储。 他们映射string字段和string值之间。 使用散列的字段 – >值映射比使用常规string的键 – >值映射稍微更节省空间。

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

散列的一个示例用于存储应用程序之间的用户configuration文件。 以用户ID作为密钥存储的redis散列将允许您根据需要存储关于用户的尽可能多的数据位,同时将它们保存在单个密钥下。 使用散列而不是序列化configuration文件到string的好处是,您可以让不同的应用程序在用户configuration文件中读取/写入不同的字段,而不必担心一个应用程序会覆盖其他人所做的更改(这可能会在您将序列化数据)。

列表( 命令 )

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

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

列表使得持久的,primefaces的,队列。 这些工作适用于作业队列,日志,缓冲区和其他许多用例。

设置( 命令 )

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

这些对于访问控制列表,独特的访问者跟踪器以及许多其他事物来说都是非常好的。 大多数编程语言都有类似的东西(通常称为Set)。 这就是这样,只分发。

Redis提供了几个命令来pipe理集合。 存在明显的增加,删除和检查设置。 所以不太明显的命令,比如popup/读取一个随机项目以及执行联合和与其他组的交集的命令。

sorting集( 命令 )

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

此数据types已针对按分数进行快速查找进行了优化。 获取最高,最低或其中任何值的范围是非常快的。

如果您将用户添加到有序的集合中,并获得高分,则您拥有一个完美的排行榜。 随着新的高分进入,只需再次将他们添加到高分,并将重新sorting您的排行榜。 对于logging上次访问的用户以及在您的应用程序中活跃的用户也非常有用。

用相同的分数存储数值使得它们按照字典顺序排列(按字母顺序排列)。 这可以用于诸如自动完成function之类的function。

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

地理

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

技术上,redis中的地理数据存储在有序集合中,所以这不是一个真正独立的数据types。 它更多的是在有序集合之上的扩展。

位图和HyperLogLog

像geo一样,这些并不是完全独立的数据types。 这些命令允许您将string数据视为位图或超级日志。

位图是我在Strings下引用的位级操作符。 这个数据types是reddit最近的协作艺术项目的基本构build块: r / Place 。

HyperLogLog允许您使用恒定的极小的空间来以惊人的准确度计算几乎无限的唯一值。 只使用〜16KB,您可以高效地统计网站的唯一身份访问者数量,即使这个数字是百万。

交易和primefaces

redis中的命令是primefaces的,这意味着您可以确保只要向redis写入值,该值对连接到redis的所有客户端都可见。 没有等待这个价值传播。 技术上memcached也是primefaces的,但是redis在memcached之外增加了所有这些function,值得注意的是,所有这些额外的数据types和特性也是primefaces性的。

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

stream水线

Redis提供了一个称为“ stream水线 ”的function。 如果你想要执行很多的redis命令,你可以使用stream水线将它们一次发送到redis,而不是一次一个。

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

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

发布/订阅

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

Redis的pub / sub以及几乎所有的工具。 像RabbitMQ这样的专用消息代理可能在某些领域有优势,但是同一台服务器也可以为您提供持久的持久队列和其他数据结构,这是Redis常常被certificate是最好,最简单的工具为了工作。

Lua脚本

你可以考虑像redis自己的SQL或存储过程的lua脚本 。 这不仅仅是这个,而是比喻大部分的作品。

也许你想要redis执行复杂的计算。 也许你不能让你的交易回滚,需要保证一个复杂的过程的每一步都会自动发生。 这些问题和更多可以用lua脚本来解决。

整个脚本是以primefaces方式执行的,所以如果你可以把你的逻辑放到lua脚本中,你通常可以避免使用乐观locking事务。

缩放

如上所述,redis包含内置的对集群的支持,并捆绑了自己的称为redis-sentinel的高可用性工具。

结论

毫不犹豫,我会build议redis通过memcached任何新的项目,或现有的项目,还没有使用memcached。

以上可能听起来像我不喜欢memcached。 相反,它是一个强大的,简单的,稳定的,成熟的,强硬的工​​具。 甚至有一些使用情况比Redis快一点。 我喜欢memcached。 我不认为今后的发展很有意义。

Redis做memcached的一切,通常更好。 memcached的任何性能优势都是轻微的,并且是特定工作负载。 还有一些工作负载会使redis速度更快,redis可以执行的工作负载更多,哪些memcached根本无法工作。 面对巨大的function差异,以及这两种工具如此之快而且高效的事实,这些微小的性能差异似乎微不足道,它们很可能是您的基础架构的最后一部分,您将不得不担心缩放。

memcached只有一种情况:memcached已经被用作caching。 如果你已经caching了memcached,那么继续使用它,如果它满足你的需求。 转移到redis可能是不值得的,如果你只是使用redis来caching,它可能不会提供足够的好处值得你花时间。 如果memcached不能满足你的需求,那么你应该转向redis。 无论您需要扩展超过memcached还是需要其他function,情况都是如此。

使用Redis if

  1. 您需要select性地删除/过期caching中的项目。 (你需要这个)

  2. 您需要能够查询特定types的键。 EQ。 'blog1:posts:*','blog2:categories:xyz:posts:*'。 哦耶! 这个非常重要。 使用此选项来使特定types的caching项目无效。 您也可以使用它来使分段caching,页面caching,只有给定types的AR对象失效等。

  3. 持久性(你也需要这样做,除非你对caching在每次重启之后必须预热,对于很less改变的对象来说非常重要)

使用memcached if

  1. Memcached让你头疼!
  2. 呃…集群? MEH。 如果你要走这么远,使用Varnish和Redis来caching片段和AR对象。

根据我的经验,使用Redis的稳定性要好于Memcached

Memcached是multithreading和快速的。

Redis有很多function,速度非常快,但是完全局限于一个内核,因为它基于事件循环。

我们使用两个。 Memcached用于caching对象,主要用于减less数据库的读取负载。 Redis用于像分类集合这样的东西,这些集合对于时间序列数据的滚动是非常方便的。

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

还有一件事要考虑的是,你是否期望在你的caching实例上有一个硬性的高端内存限制。

由于redis是一个拥有大量function的nosql数据库,caching只能用于其中一个选项,因此它会根据需要分配内存 – 放入的对象越多,使用的内存就越多。 maxmemory选项不会严格执行上限内存限制使用。 在使用caching时,密钥被逐出并过期; 机会是你的密钥不是全部相同的大小,所以发生内部内存碎片。

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

memcached更适合上述场景,因为它以完全不同的方式pipe理内存。 memcached分配一大块内存 – 它将需要的一切 – 然后使用自己实现的slab分配器自行pipe理这个内存。 此外,memcached试图尽量保持内部碎片低,因为它实际上使用每平板LRUalgorithm ,当LRU驱逐完成考虑的对象大小。

就这点而言,memcached在环境中仍然占有一席之地,在这种环境下,内存使用必须被强制执行和/或是可预测的。 我们试图使用最新的稳定redis(2.8.19)作为一个基于LRU的非embedded式memcachedreplace,工作量为10-15k op / s,并且泄漏了内存A LOT; 由于相同的原因,相同的工作负载在一天左右的时间内会使Amazon的ElastiCache redis实例崩溃。

Memcached善于成为一个简单的键/值存储,擅长做key => STRING。 这使会话存储真的很好。

Redis擅长做key => SOME_OBJECT。

这真的取决于你将会在那里。 我的理解是,在性能方面,他们甚至相当。

也祝你find任何客观的基准,如果你find一些好心的发送他们的方式。

如果你不介意一种粗俗的写作风格,在Systoilet博客上的Redis vs Memcached值得从可用性的angular度来阅读,但是一定要在评论中来回阅读,然后才能得出有关性能的结论。 有一些方法上的问题(单线程忙碌循环testing),Redis也做了一些改进。

没有基准链接是完整的,没有混淆的事情一点点,所以也检查了Dormondo的LiveJournal和Antirez博客一些相互矛盾的基准。

编辑 – 正如Antirez所指出的,Systoilet分析是相当糟糕的。 即使在单线程的不足之外,这些基准testing中的性能差异大部分可以归因于客户端库,而不是服务器吞吐量。 Antirez博客的基准确实呈现出更多苹果(相同口)的比较。

我有机会在caching代理中使用memcached和redis在一起,让我分享你在哪里我已经使用了什么和背后的原因….

Redis>

1)用于索引集群中的caching内容。 我有超过十亿个密钥分布在redis集群上,redis的响应时间相当不稳定。

2)基本上,它是一个关键/价值的商店,所以在你的应用程序中,你有类似的东西,可以使用redis的困扰很多。

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

Memcache>

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

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

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

如果您要求整体体验,Redis非常绿色,因为它很容易configuration,而且非常灵活,具有稳定强大的function。

此外,这个环节还有一个基准testing结果,下面几个是相同的,

在这里输入图像说明

在这里输入图像说明

希望这可以帮助!!

另一个好处是可以非常清楚memcache是​​如何在caching场景中运行的,而redis通常用作持久性数据存储,虽然它可以configuration为像memcached一样运行,也就是在达到max时驱逐Least最近使用的项目容量。

我所使用的一些应用程序只是为了明确我们打算如何处理数据 – 在memcache中的东西,我们编写代码来处理它不在那里的情况 – 在redis中的东西,我们依靠它在那里。

除此之外,Redis通常被认为是优于大多数function丰富且灵活的用例。

testing。 运行一些简单的基准。 很长一段时间,我认为自己是一个老犀牛,因为我主要使用memcached,认为Redis是新的孩子。

与我目前的公司Redis被用作主要caching。 当我挖掘出一些性能统计信息并简单地开始testing时,就性能而言,Redis与MySQL相比是相当的或者是最低的。

Memcached尽pipe简单化,却完全把Redis 彻底甩掉了。 它的规模好得多:

  • 为更大的价值(需要改变板坯大小,但工作)
  • 用于多个并发请求

另外,在我看来,memcached驱逐策略更好地实现,从而在处理更多数据的同时,平均响应时间总体上比caching可以处理的更加稳定。

一些基准testing显示,在我们的例子中,Redis的performance非常糟糕。 我相信这与许多变数有关:

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

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

这里没有指出的一个主要区别是Memcache在任何时候都有一个较高的内存限制,而Redis不是默认的(但是可以configuration)。 如果你总是喜欢在一定的时间内存储一个键/值(并且从不会因为内存不足而退出),那么你需要使用Redis。 当然,你也冒着内存不足的问题。

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

我们认为Redis是我们在工作中项目的负载起飞。 我们认为通过在nginx中使用一个名为HttpRedis2Module的模块或类似的东西,我们会有很棒的速度,但是当用AB-test进行testing时,我们被certificate是错误的。

也许模块是坏的或我们的布局,但这是一个非常简单的任务,它是更快的采取PHP的数据,然后将其填充到MongoDB。 我们使用APC作为caching系统,并使用该PHP和MongoDB。 那么Nginx的Redis模块要快得多。

我的build议是自己testing一下,这样做会显示你的环境结果。 我们决定在我们的项目中使用Redis是没有必要的,因为它没有任何意义。

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

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

如果您要设置一个专用的Redis实例作为LRU实例来避免这种特殊情况,那么在Memcached上使用Redis并没有任何强制性的理由。

如果你需要一个可靠的“永不停息”的LRUcaching…… Memcached将适合这个账单,因为它不可能通过devise耗尽内存,而专门的function阻止了开发人员试图使其变得危险。 简单的分离关注。

Redis更好Redis的优点在于,

 1.It has a lot of data storage options such as string , sets , sorted sets , hashes , bitmaps 2.Disk Persistence of records 3.Stored Procedure (LUA acripting) support 4.Can act as a Message Broker using PUB/SUB 

而Memcache是​​内存中的键值cachingtypes系统。

  1. 不支持像列表一样的各种数据types存储,如redis中的设置。
  2. 主要的缺点是Memcache没有磁盘持久性。

一个非常简单的testing,设置和得到100k独特的键和值对redis-2.2.2和memcached。 两者都运行在Linux VM(CentOS)上,我的客户端代码(粘贴在下面)在Windows桌面上运行。

Redis的

  • 存储100000个值的时间是= 18954ms

  • 加载100000个值的时间是= 18328ms

Memcached的

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

  • 检索100000个值的时间是= 38984毫秒


 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"); 

我会说redis,因为它比memcached快得多,即使它运行在一台机器的一个核心上,并且memcached可以并行运行,但是如果configuration正确,需要很多处理来达到redis的上限

那么我主要是用我的应用程序,Memcache用于caching会话和redis for doctrine / orm查询对象。 在性能方面,两者几乎相同。