Couchbase vs Redis,究竟哪一个更胜一筹?

Redis 和Couchbase都是基于内存的数据存储系统。在它们各自的官方描述中,Couchbase是高性能,高伸缩性和高可用的分布式缓存系统;Redis是一个开源的内存数据结构存储系统。web

 

【权威比较】redis

Redis的做者Salvatore Sanfilippo曾经对这两种基于内存的数据存储系统进行过比较:算法

 

● Redis支持服务器端的数据操做
Redis相比Couchbase来讲,拥有更多的数据结构和并支持更丰富的数据操做,一般在Couchbase里,你须要将数据拿到客户端来进行相似的修改再set回去(你须要先先经过get方法从服务器读取数据文档,并将文档反序列化为json对象,以后修改json对象对应属性,再经过set方法将数据写入服务器,序列化后进行存储)。这大大增长了网络IO的次数和传输中的数据体积。在Redis中,这些复杂的操做一般和通常的GET/SET同样高效。数据库


● 内存使用效率对比
使用简单的key-value存储的话,Couchbase的内存利用率更高,而Redis采用hash结构来作key-value存储,因为其组合式的压缩,其内存利用率会高于Couchbase。因此,若是须要缓存可以支持更复杂的数据结构和更频繁数据的部分更新操做,那么Redis会是不错的选择。(下文会在关于数据存储模型来证实这一点)json


● 性能对比
因为Redis只使用单核,而Couchbase可使用多核,因此平均每个核上Redis在存储小数据时比Couchbase性能更高。而在100k以上的数据中,Couchbase性能要高于Redis,虽然Redis最近也在存储大数据的性能上进行优化,可是比起Couchbase,仍是稍有逊色。后端

 

其实不管是在大块数据仍是大数据量的处理上,Couchbase都要优于Redis,不少平台都是采用Couchbase来管理数千万热数据。因此,若是缓存大多数状况下仅仅须要提供数据新增和查询操做,那Couchbase基于文档类型的存储结构可以始终如一地为提供亚毫秒的查询体验,对于预约义的数据类型你还能够经过建立索引进一步优化性能,这种状况下,Couchbase无疑是你更好的选择。
(原话中比较的是Memcached,Couchbase做为Memcached的增强版,继承了其技术实现)数组

 

【Redis的优点】缓存

一.丰富的数据结构安全

Redis支持字符串、哈希表、列表、集合、有序集合,位图,hyperloglogs等数据类型。而Couchbase仅仅支持json格式。若是有粉丝列表,排行榜,消息队列等功能需求,选择Redis能给你带来很大的便利,由于它丰富的数据结构可以简化开发和交互步骤。服务器

 

为了证实Redis的优点,咱们简单举个实例对比,来描述下Hash的应用场景。

 

▲数据存储于Couchbase

包含如下信息:用户ID为查找的key,存储的value用户对象包含姓名,年龄,生日等信息,若是用普通的key/value结构来存储,在Couchbase中有如下2种存储方式。

▪ 第一种方式将用户ID做为查找key,把其余信息封装成一个对象以序列化的方式存储,这种方式的缺点是,增长了序列化/反序列化的开销,而且在须要修改其中一项信息时,须要把整个对象取回,而且修改操做须要对并发进行保护,引入CAS等复杂问题。

 

▪ 第二种方法是用户信息对象有多少成员就存成多少个key-value对,用户ID+对应属性的名称做为惟一标识来取得对应属性的值,虽然省去了序列化开销和并发问题,可是用户ID为重复存储,若是存在大量这样的数据,内存浪费仍是很是可观的。

▲数据存储于Redis中

Key仍然是用户ID, value是一个Map,这个Map的key是成员的属性名,value是属性值,这样对数据的修改和存取均可以直接经过其内部Map的Key(Redis里称内部Map的key为field), 也就是经过 key(用户ID) + field(属性标签) 就能够操做对应属性数据了,既不须要重复存储数据,也不会带来序列化和并发修改控制的问题。这也就是Redis做者高内存利用率的论据。


所以,若是有大量大有复杂结构的数据须要缓存,redis是更好的选择,它不只能简化你的存储设计,还能帮你避免更新操做时繁琐的序列号和反序列化。像twitter的关注列表,粉丝列表等就是选用了redis的list,Agora Games的排行榜就是选用了redis的有序集合。


二. counter--计数器

redis和couchbase都提供了counter这一特殊数据类型,不少平台都是以counter为基础实现的流控和计数功能。但counter不一样于其余数据,它对实时性的要求很是高,所以十分考验缓存系统的主键失效策略。这里简单提一下,大多数缓存系统都提供了积极失效和消极失效两种策略保证失效数据清理。


▪ 积极策略采用定时定比例抽样清理策略
▪ 消极策略则属于请求触发式的,这里咱们主要对消极策略展开叙述。


Redis 2.6以后的版本采用毫秒为单位存储过时时间,每次数据访问操做都须要进行过时检验,由此保证毫秒级别的过时精度。而couchbase的过时精度是秒级别的,也就是说若是你选择了couchbase且没有在counter上作特殊处理,你的流控将变得极不许确,更危险的是这个问题是由底层机制引起的,你几乎不可能经过业务代码来修复bug。好比你限制一个客户每秒只能访问500次,但实际状况是客户平均下来每秒只能访问不到300次,这就是计数器延迟失效引起的问题。


所以,若是选择Couchbase,要实现准确的流控和计数可能要手动为每个计数器的key添加时间戳,并经过取余操做限制counter的峰值数量,固然若是你难以保证全部服务器时钟同步,你能够指定服务器的时间,这也算是Couchbase方案的灵活性吧。


总而言之,若是你有高精度的流控和计数类需求,又不想对原生的counter二次封装,请选择redis。


三.事务

相比Couchbase,Redis提供了事务的功能,能够保证一串命令的原子性,中间不会被任何操做打断,主要命令包括主要命令包括 MULTI、EXEC、WATCH 命令。若是对事务有所要求,redis是个更好的选择。


四. 开源社区的繁荣

Redis在国内大热,爱好者们不只翻译了官网,更为其量身定作了不少优化方案,各类中文技术文档也是包罗万象。相比而言,Couchbase的商业版和社区版差异巨大,更趋近于闭源,网上中文资料少得可怜,全部技术文档都须要翻阅英文官网。


所以,若是你的开发团队缺乏很好的英文阅读能力,redis是更好的选择。


五.丰富的使用场景

Redis能够适配丰富的场景,有如下五种为最为常见:


▲会话缓存(Session Cache)

这是最经常使用的一种使用Redis的情景。


▲全页缓存(FPC)

除基本的会话token以外,Redis还提供很简便的FPC平台。以Magento为例,Magento提供一个插件来使用Redis做为全页缓存后端。


▲队列

Reids在内存存储引擎领域的一大优势是提供 list 和 set 操做,这使得Redis能做为一个很好的消息队列平台来使用。Redis做为队列使用的操做,就相似于本地程序语言(如Python)对 list 的 push/pop 操做。
例如,Celery有一个后台就是使用Redis做为broker。


▲排行榜/计数器

Redis在内存中对数字进行递增或递减的操做实现的很是好。集合(Set)和有序集合(Sorted Set)也使得咱们在执行这些操做的时候变的很是简单,Redis只是正好提供了这两种数据结构。

因此,咱们要从排序集合中获取到排名最靠前的10个用户–咱们称之为“user_scores”,咱们只须要像下面同样执行便可。固然,这是假定是根据用户的分数作递增的排序。若是想返回用户及用户的分数,你须要这样执行:
ZRANGE user_scores 0 10 WITHSCORES
Agora Games就是一个很好的例子,用Ruby实现的,它的排行榜就是使用Redis来存储数据的。


▲发布/订阅

发布/订阅的使用场景确实很是多。不只在社交网络链接中使用,还可做为基于发布/订阅的脚本触发器,甚至用Redis的发布/订阅功能来创建聊天系统。

 

【Couchbase的优点】

一.web界面

Couchbase提供了良好的管理界面,集配置,管理,监控和告警于一身。Couchbase的web界面提供了版本提醒,ssl证书配置,用户管理,邮件告警等一系列丰富的功能,大大简化了运维的工做;也web界面能够直观的观测OPS,磁盘写入队列,内存数据量,Compaction和Ejection实时情况,为开发和测试提供了直观的数据参考。对性能测试相当重要。而redis就仅有第三方提供的一些简单客户端产品,用于观测数据存储状况,配置优化相关的工做也须要在配置文件中操做。

 

若是考虑到后期性能测试以及运维的可操做性,couchbase是更好的选择。


二. 三高

这里的三高指的是高性能,高可用性和高伸缩性。


Redis从一开始就是单点解决方案,直到Redis3.0后才出来官方的集群方案,并且仍存在一些架构上的问题,其高可用性目前尚未在线上被证实,第三方的集群方案像豌豆荚的Codi又缺乏官方的后续支持。


相比而言,Couchbase从一开始就内建集群系统,即便是节点重启,数据未彻底载入内存,也能照常提供服务,这得益于每份数据的metedata,其中包含近期的操做信息,Couchbase借此来区分热数据,只要热数据加载到最低水位便可当即提供服务。


若是出现节点失效,集群可在指定的时间里自动发现并启动failover,这里不一样Redis的哨兵系统,Couchbase采用激活失效节点备份将请求分摊给幸存节点的方案,恢复时间更快;若是节点新增,Couchbase会将内存数据复制,一份用于提供服务,一份用于重分配并时刻保证数据一致性,即集群扩容不会致使任何业务中断。此外,couchbase的异步持久化和备份同步(经过维护一个持久化队列)也要优于redis的RDB快照和AOF日志方案。所以,从三高的角度来看,高可用性和高伸缩性上Couchbase显然是更加可靠的。


Couchbase的集群方案相比Redis,对用户屏蔽了更多细节,集群更具弹性,且通过多年的生产线上验证。所以,若是高可用和弹性是重要考虑因素,那Couchbase无疑是更稳妥的方案。

两款产品直观的优点如上,你们能够根据本文结合实际业务场景进行选择。有兴趣的同窗推荐阅读《Seven Databases in Seven Weeks》。

 

【Redis vs Couchbase内存管理分析】

对于像Redis和Couchbase基于内存的数据库系统来讲,内存管理的效率高低是影响系统性能的关键因素。

 

Couchbase内存管理分析

Couchbase默认使用Slab Allocation机制管理内存,其主要思想是按照预先规定的大小,将分配的内存分割成特定长度的块以存储相应长度的key-value数据记录,以彻底解决内存碎片问题。(实际上是把外部碎片转化为了内部碎片)Slab Allocation机制只为存储外部数据而设计,也就是说全部的key-value数据都存储在Slab Allocation系统里,而Couchbase的其它内存请求则经过普通的malloc/free来申请,由于这些请求的数量和频率决定了它们不会对整个系统的性能形成影响。

 

Slab Allocation的原理至关简单。 如图所示,它首先从操做系统申请一大块内存,并将其分割成各类尺寸的块Chunk,并把尺寸相同的块分红组Slab Class。其中,Chunk就是用来存储key-value数据的最小单位。每一个Slab Class的大小,能够在Couchbase启动的时候经过制定Growth Factor来控制。假定图中Growth Factor的取值为1.25,若是第一组Chunk的大小为88个字节,第二组Chunk的大小就为110个字节,依此类推。 

当Couchbase接收到客户端发送过来的数据时首先会根据收到数据的大小选择一个最合适的Slab Class,而后经过查询Couchbase保存着的该Slab Class内空闲Chunk的列表就能够找到一个可用于存储数据的Chunk。当一条数据库过时或者丢弃时,该记录所占用的Chunk就能够回收,从新添加到空闲列表中。


从以上过程咱们能够看出Couchbase的内存管理制效率高,并且不会形成内存碎片,可是它最大的缺点就是会致使空间浪费。由于每一个Chunk都分配了特定长度的内存空间,因此变长数据没法充分利用这些空间。如图 所示,将100个字节的数据缓存到128个字节的Chunk中,剩余的28个字节就浪费掉了(这就是内部碎片,但相比外部碎片是可控的,也是可再利用的)。

▲Redis内存管理分析

Redis的内存管理主要经过源码中zmalloc.h和zmalloc.c两个文件来实现的。Redis为了方便内存的管理,在分配一块内存以后,会将这块内存的大小存入内存块的头部。

 

如图所示,real_ptr是Redis调用malloc后返回的指针。Redis将内存块的大小size存入头部,size所占据的内存大小是已知的,为size_t类型的长度,而后返回ret_ptr。当须要释放内存的时候,ret_ptr被传给内存管理程序。经过ret_ptr,程序能够很容易的算出real_ptr的值,而后将real_ptr传给free释放内存。

Redis经过定义一个数组来记录全部的内存分配状况,这个数组的长度为ZMALLOC_MAX_ALLOC_STAT。数组的每个元素表明当前程序所分配的内存块的个数,且内存块的大小为该元素的下标。在源码中,这个数组为zmalloc_allocations。zmalloc_allocations[16]表明已经分配的长度为16bytes的内存块的个数。zmalloc.c中有一个静态变量used_memory用来记录当前分配的内存总大小。因此,总的来看,Redis采用的是包装的mallc/free,相较于Couchbase的内存管理方法来讲,要简单不少。


总的来讲,Couchbase的内存管理机制以每次分配冗余空间为代价,避免了内存碎片。若是程序须要频繁短时效的百字节以上的内存空间,好比动态令牌,Couchbase显然是更好的选择;若是仅仅使用长效的计数器或几个字节的标识字段,那么使用Couchbase反而形成内存浪费,Redis倒是更好的选择。

 

【集群管理】

一. Couchbase集群管理

Couchbase自己并不支持分布式,所以只能在客户端经过像一致性哈希这样的分布式算法来实现Couchbase的分布式存储,Couchbase会经过在集群内部和客户端直接共享vbucket和节点映射关系,客户端每次操做前须要对数据的key进行计算,以肯定数据落入的vbucket编号,再根据映射表肯定数据所在节点,而后直接与指定节点通讯,不须要Redis的节点重定位方案,对于集群变动对外也只须要更新vbucket和节点映射关系便可。下图是Couchbase的分布式存储实现架构。

 

如今咱们模拟一下Couchbase的失效备援方案,假设当前客户端的vbucket和节点映射关系以下:

 

那么当D节点失效后,集群只须要激活ABC上D节点的数据副本,而后更新vbucket和节点映射关系以下:

此后全部的数据请求就被分摊到了ABC之上,即便客户端的配置文件里还存在节点D的地址,也不会再产生交互了。

二. Redis集群管理
相较于Couchbase只能采用客户端实现分布式存储,Redis更偏向于在服务器端构建分布式存储。最新版本的Redis已经支持了分布式存储功能。Redis Cluster是一个实现了分布式且容许单点故障的Redis高级版本,它没有中心节点,具备线性可伸缩的功能。

下图是Redis Cluster的分布式存储架构:

其中节点与节点之间经过二进制协议进行通讯,节点与客户端之间经过ascii协议进行通讯。在数据的放置策略上,Redis Cluster将整个key的数值域分红4096个哈希槽,每一个节点上能够存储一个或多个哈希槽,也就是说当前Redis Cluster支持的最大节点数就是4096。Redis Cluster使用的分布式算法也很简单:crc16( key ) % HASH_SLOTS_NUMBER。

 

为了保证单点故障下的数据可用性,Redis Cluster引入了Master节点和Slave节点。在Redis Cluster中,每一个Master节点都会有对应的两个用于冗余的Slave节点。这样在整个集群中,任意两个节点的宕机都不会致使数据的不可用。当Master节点退出后,集群会自动选择一个Slave节点成为新的Master节点。

 

总而言之,Couchbase把数据分布计算分摊给客户端执行,节省了缓存服务器的CPU,而且客户端直接和数据所在节点通讯节省了带宽并缩短了响应时间。且相比Redis至少须要6个实例才能组成集群的限制,Couchbase的集群方案更加灵活(但Redis能够一机多个实例,Couchbase单机只能部署一个)。

 

所以,若是机器资源充足,Couchbase能够提供更好的服务体验(因为客户端分摊计算成本,这里的机器不须要过多CPU),若是只有机器资源紧张,redis是部署上的轻量级方案,但前面提到的,当访问量爆发时,可能会考验缓存服务器的CPU。

 

【该怎么选择】

在我看来,Conchbase和Redis本就是定位不一样的两款产品。Redis的亮点在于业务契合度高,Couchbase的亮点在于高可用。若是不是二选一的场景,它们是能够相辅相成的,Redis的定位是一个带有丰富数据结构的内存数据库,充分利用其数据结构能够简化许多业务场景下的开发,如利用队列实现消息队列,利用有序集合实现排行榜;而Couchbase的定位是一个专业的分布式缓存系统,将一些业务关键信息,如鉴权信息和会话信息存储其中,能最大限度保证业务的安全性和高可用性。

 

Redis&Conchbase的缓存系统选型:

相关文章
相关标签/搜索