Memcached 和 Redis 作为两种 Inmemory 的 key-value 数据库,在设计和思想方面有着很多共通的地方,功能和应用方面在很多场合下 ( 作为分布式缓存服务器使用等 ) 也很相似,在这里把两者放在一起做一下对比的介绍
基本架构和思想
首先简单介绍一下两者的架构和设计思路
Memcached
Memcached是以LiveJurnal旗下Danga Interactive公司的Bard Fitzpatric为首开发的高性能分布式内存缓存服务器。其本质上就是一个内存key-value数据库,但是不支持数据的持久化,服务器关闭之后数据全部丢失。 Memcached使用C语言开发,在大多数像Linux、BSD和Solaris等POSIX系统上,只要安装了libevent即可使 用。在Windows下,它也有一个可用的非官方版本(http://code.jellycan.com/memcached/)。 Memcached 的客户端软件实现非常多,包括C/C++, PHP, Java, Python, Ruby, Perl, Erlang, Lua等。当前Memcached使用广泛,除了LiveJournal以外还有Wikipedia、Flickr、Twitter、Youtube和 WordPress等。
在Linux等系统下,我们首先需要安装libevent,然后从获取源码,make && make install即可。默认情况下,Memcached的服务器启动程序会安装到/usr/local/bin目录下。在启动Memcached时,我们可以为其配置不同的启动参数。
Memcached 采用客户端 - 服务器的架构,客户端和服务器端的通讯使用自定义的协议标准,只要满足协议格式要求,客户端 Library 可以用任何语言实现。
从用户的角度来说,服务器维护了一个键 - 值关系的数据表,服务器之间相互独立,互相之间不共享数据也不做任何通讯操作。客户端需要知道所有的服务器,并自行负责管理数据在各个服务器间的分配。
在服务器端,内部的数据存储,使用基于 Slab 的内存管理方式,有利于减少内存碎片和频繁分配销毁内存所带来的开销。各个 Slab 按需动态分配一个 page 的内存(和 4K page 的概念不同,这里默认 page 为 1M ), page 内部按照不同 slab class 的尺寸再划分为内存 chunk 供服务器存储 KV 键值对使用
Memcached 的基本应用模型如下图所示
Redis
Redis是一个开源的key-value存储系统。与Memcached类似,Redis将大部分数据存储在内存中,支持的数据类型包括:字符串、哈希 表、链表、集合、有序集合以及基于这些数据类型的相关操作。Redis使用C语言开发,在大多数像Linux、BSD和Solaris等POSIX系统上无需任何外部依赖就可以使用。 Redis支持的客户端语言也非常丰富,常用的计算机语言如C、C#、C++、Object-C、PHP、Python、 Java、Perl、Lua、Erlang等均有可用的客户端来访问Redis服务器。当前Redis的应用已经非常广泛,国内像新浪、淘宝,国外像 Flickr、Github等均在使用Redis的缓存服务。
Redis的安装非常方便,只需从http://redis.io/download获取源码,然后make && make install即可。默认情况下,Redis的服务器启动程序和客户端程序会安装到/usr/local/bin目录下。在启动Redis服务器时,我们需要为其指定一个配置文件,缺省情况下配置文件在Redis的源码目录下,文件名为redis.conf。
Redis的基本应用模式和上图memcached的基本相似,不难发现网上到处都是关于redis是否可以完全替代memcached使用的问题
Redis 内部的数据结构最终也会落实到 key-Value 对应的形式,不过从暴露给用户的数据结构来看,要比 memcached 丰富,除了标准的通常意义的键值对, Redis 还支持 List , Set , Hashes , Sorted Set 等数据结构
基本命令
Memcached 的命令或者说通讯协议非常简单, Server 所支持的命令基本就是对特定 key 的添加,删除,替换,原子更新,读取等,具体包括 Set, Get, Add, Replace, Append, Inc/Dec 等等
Memcached 的通讯协议包括文本格式和二进制格式,用于满足简单网络客户端工具(如 telnet )和对性能要求更高的客户端的不同需求
Redis 的命令在 KV ( String 类型)上提供与 Memcached 类似的基本操作,在其它数据结构上也支持基本类似的操作(当然还有这些数据结构所特有的操作,如 Set 的 union , List 的 pop 等)而支持更多的数据结构,在一定程度上也就意味着更加广泛的应用场合
除了多种数据结构的支持, Redis 相比 Memcached 还提供了许多额外的特性,比如 Subscribe/publish 命令,以支持发布 / 订阅模式这样的通知机制等等,这些额外的特性同样有助于拓展它的应用场景
Redis 的客户端 - 服务器通讯协议完全采用文本格式(在将来可能的服务器间通讯会采用二进制格式)
事务
redis 通过 Multi / Watch /Exec 等命令可以支持事务的概念,原子性的执行一批命令。在 2.6 以后的版本中由于添加了对 Script 脚本的支持,而脚本固有的是以 transaction 事务的方式执行的,并且更加易于使用,所以不排除将来取消 Multi 等命令接口的可能性
Memcached 的应用模式中,除了 increment/decrement 这样的原子操作命令,不存在对事务的支持
数据备份,有效性,持久化等
memcached 不保证存储的数据的有效性, Slab 内部基于 LRU 也会自动淘汰旧数据,客户端不能假设数据在服务器端的当前状态,这应该说是 Memcached 的 Feature 设定,用户不必太多关心或者自己管理数据的淘汰更新工作,当然是否适合你的应用,取决于具体的需求,它也可能成为你需要精确自行控制 Cache 生命周期的一个障碍
Memcached 也不做数据的持久化工作,但是有许多基于 memcached 协议的项目实现了数据的持久化,例如 memcacheDB 使用BerkeleyDB进行数据存储,但本质上它已经不是一个 Cache Server ,而只是一个兼容 Memcached 的协议 key-valueData Store 了
Redis 可以以 master-slave 的方式配置服务器, Slave 节点对数据进行 replica 备份, Slave 节点也可以充当 Read only 的节点分担数据读取的工作
Redis 内建 支持两种持久化方案, snapshot 快照和 AOF 增量 Log 方式。快照顾名思义就是隔一段时间将完整的数据 Dump 下来存储在文件中。 AOF 增量 Log 则是记录对数据的修改操作(实际上记录的就是每个对数据产生修改的命令本身),两种方案可以并存,也各有优缺点,具体参见 http://redis.io/topics/persistence
以上 Redis 的数据备份持久化方案等,如果不需要,为了提高性能,也完全可以 Disable
性能
性能方面,两者都有一些自己考虑和实现
Memcached
memcached 自身并不主动定期检查和标记哪些数据需要被淘汰,只有当再次读取相关数据时才检查时间戳,或者当内存不够使用需要主动淘汰数据时进一步检查 LRU 数据
Redis
Redis 为了减少大量小数据 CMD 操作的网络通讯时间开销 RTT (Round Trip Time),支持 pipeline 和 script 技术
所谓的 pipeline 就是支持在一次通讯中,发送多个命令给服务器批量执行,带来的代价是服务器端需要更多的内存来缓存查询结果。
Redis 内嵌了 LUA 解析器,可以执行 lua 脚本,脚本可以通过 eval 等命令直接执行,也可以使用 script load 等方式上传到服务器端的 script cache 中重复使用
这两种方式都可以有效地减少网络通讯开销,增加数据吞吐率
对于 KV 的操作, Memcached 和 Redis 都支持 Multiple 的 Get 和 Set 命令( Memcached 的 Multiple Set 命令貌似只在二进制的协议中支持),这同样有利于性能的提升
实际性能方面,网上有很多测试比较,给出的结果各不相同,这无疑和各种测试的测试用例,测试环境,和测试时具体使用的客户端 Library 实现有关。但是总体看下来,比较靠谱的结论是在 kv 类操作上,两者的性能接近, Memcached 的结构更加简单,理论上应该会略微快一些。
集群
memcached 的服务器端互相完全独立,客户端通常通过对键值应用 Hash 算法决定数据的分区,为了减少服务器的增减对 Hash 结果的影响,导致大面积的缓存失效,多数客户端实现了一致性 hash 算法
Redis 计划在服务器端内建对集群的支持,但是目前代码还处于 alpha 阶段(貌似已经 Design 了两三年了?)在此之前,同样可以认为每个 Redis 服务器实例相互之间是完全独立的,需要依靠客户端处理分区算法和可用服务器列表管理的工作。
Redis 官方推荐的用于 Sharding 的客户端程序库是 Twitter 的开源项目 Twemproxy, Twemproxy 同时支持 Memcached 和 Redis 的文本通讯协议。
需要注意的是, Redis 的许多命令在集群环境下是不能正确运行的,例如 set 的交集,以及跨节点的事务操作等等,因为目前的 Redis 集群设计,根本目标也就是服务器之间互相汇报一下存活状态,以及对数据做荣誉备份平衡负载等而已,本质上对数据的跨节点操作并不提供任何额外支持,所以在数据服务的层面上来说,各个服务器依旧是完全独立的。
这些操作如果一定要实现,当然可以通过客户端代码来实现(效率有多高且不说),类似的问题 memcached 集群当然也会遇上,但是原本 memcached 就不支持复杂的操作和数据类型,许多运算逻辑原本就是由客户端代码或应用程序自己处理的。
MR 类批处理应用
提供指定范围的遍历操作,是支持类似 MapReduce 这样的批处理应用逻辑的关键之一,但是要在基于 hash 方式存储的数据结构的基础上提供这样的支持并不容易(或者说要实现高效的范围或遍历操作并不容易)
Redis 支持 Scan 操作用于遍历数据集,这一操作基于其内部数据结构及实现的限制,可以保证在 Scan 开始时的所有数据都能被获取到,但是不能保证不返回重复的数据,这需要由客户端来检查,或者客户端对此无所谓。 Scan 操作还支持 Match 条件用来过滤键值,虽然存在一定的局限性,例如 match 条件的比较是在获取数据之后再执行的,效率是一个问题,更明显的问题是不能保证每次 scan 的 iterate 过程都能返回同样数量的有效数据。
对于范围操作, Redis 的 Ordered Set 支持在插入时指定数据的分数( Score )用于排序,而后支持在指定 Score 范围内的各种操作,虽然由于不支持基于字符串的或自定义的基准的 Range 操作,这样的范围操作应用起来有很大的局限性(或者说需要满足特定的应用模式),但是还是比没有好了
Memcached 核心协议本身不支持任何范围类的操作,也没有对遍历操作的支持,甚至不存在官方合法的列举所有 Key 的操作,这当然很大程度上源于其设计思想和精简的架构
不过还是有一些兼容 memcached 协议的服务器实现了范围类操作,具体格式可以参考 https://code.google.com/p/memcached/wiki/RangeOps 所建议的标准
此外 Redis 的 Hashes 数据结构,在一定程度上可以满足获取特定子集数据的应用逻辑需求。
综上来说,如果要实现类似 HBase 支持的 scan 操作,不论是 Redis 还是 memcached 都无法做到,但是对于 Redis 来说,能否用于批处理类应用,不能一概而论,取决于具体的数据的格式逻辑和使用方式。通过适当的调整应用程序使用数据的方式,还是有可能在一定程度上实现对 MR 类批处理,或范围查询类应用逻辑的支持的。而对于键值分布在一个较大的连续空间,数量不确定,同时又无法很好的映射为数值进而使用 ordered set 来处理的这样一些数据结构,应该还是很难高效的分区遍历的。
关于Redis和memcache的对比:
1. Redis中,并不是所有的数据都一直存储在内存中的,这是和Memcached相比一个最大的区别。
2. Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,hash等数据结构的存储。
3. Redis支持数据的备份,即master-slave模式的数据备份。
4. Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
Redis在很多方面具备数据库的特征,或者说就是一个数据库系统,而Memcached只是简单的K/V缓存
来看下Redis作者对比redis和memcache
来源:《Is memcached a dinosaur in comparison to Redis?》(相比Redis,Memcached真的过时了吗?)
You should not care too much about performances. Redis is faster per core with small values, but memcached is able to use multiple cores with a single executable and TCP port without help from the client. Also memcached is faster with big values in the order of 100k. Redis recently improved a lot about big values (unstable branch) but still memcached is faster in this use case. The point here is: nor one or the other will likely going to be your bottleneck for the query-per-second they can deliver.
没 有必要过多的关心性能,因为二者的性能都已经足够高了。由于Redis只使用单核,而Memcached可以使用多核,所以在比较上,平均每一个核上 Redis在存储小数据时Memcached性能更高。而在100k以上的数据中,Memcached性能要高于Redis,虽然Redis最近也在存储 大数据的性能上进行优化,但是比起Memcached,还是稍有逊色。说了这么多,结论是,无论你使用哪一个,每秒处理请求的次数都不会成为瓶颈。(比如 瓶颈可能会在网卡)
You should care about memory usage. For simple key-value pairs memcached is more memory efficient. If you use Redis hashes, Redis is more memory efficient. Depends on the use case.
如果要说内存使用效率,使用简单的key-value存储的话,Memcached的内存利用率更高,而如果Redis采用hash结构来做key-value存储,由于其组合式的压缩,其内存利用率会高于Memcached。当然,这和你的应用场景和数据特性有关。
You should care about persistence and replication, two features only available in Redis. Even if your goal is to build a cache it helps that after an upgrade or a reboot your data are still there.
如果你对数据持久化和数据同步有所要求,那么推荐你选择Redis,因为这两个特性Memcached都不具备。即使你只是希望在升级或者重启系统后缓存数据不会丢失,选择Redis也是明智的。
You should care about the kind of operations you need. In Redis there are a lot of complex operations, even just considering the caching use case, you often can do a lot more in a single operation, without requiring data to be processed client side (a lot of I/O is sometimes needed). This operations are often as fast as plain GET and SET. So if you don't need just GET/SET but more complex things Redis can help a lot (think at timeline caching).
当 然,最后还得说到你的具体应用需求。Redis相比Memcached来说,拥有更多的数据结构和并支持更丰富的数据操作,通常在Memcached里, 你需要将数据拿到客户端来进行类似的修改再set回去。这大大增加了网络IO的次数和数据体积。在Redis中,这些复杂的操作通常和一般的 GET/SET一样高效。所以,如果你需要缓存能够支持更复杂的结构和操作,那么Redis会是不错的选择。
1、 Redis和Memcache都是将数据存放在内存中,都是内存数据库。不过memcache还可用于缓存其他东西,例如图片、视频等等。2、Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,hash等数据结构的存储。3、虚拟内存--Redis当物理内存用完时,可以将一些很久没用到的value 交换到磁盘4、过期策略--memcache在set时就指定,例如set key1 0 0 8,即永不过期。Redis可以通过例如expire 设定,例如expire name 105、分布式--设定memcache集群,利用magent做一主多从;redis可以做一主多从。都可以一主一从6、存储数据安全--memcache挂掉后,数据没了;redis可以定期保存到磁盘(持久化)7、灾难恢复--memcache挂掉后,数据不可恢复; redis数据丢失后可以通过aof恢复8、Redis支持数据的备份,即master-slave模式的数据备份。
版权声明:本文为博主原创文章,未经博主允许不得转载。
运维网声明
1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网 享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com