couchbase 和redis 比较

Redis 和Couchbase都是基于内存的数据存储系统。在它们各自的官方描述中,Couchbase是高性能,高伸缩性和高可用的分布式缓存系统;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会是不错的选择。(下文会在关于数据存储模型来证明这一点)


● 性能对比
由于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等复杂问题。

couchbase 和redis 比较_第1张图片


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

couchbase 和redis 比较_第2张图片

▲数据存储于Redis中

couchbase 和redis 比较_第3张图片

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 和redis 比较_第4张图片

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


从以上过程我们可以看出Couchbase的内存管理制效率高,而且不会造成内存碎片,但是它最大的缺点就是会导致空间浪费。因为每个Chunk都分配了特定长度的内存空间,所以变长数据无法充分利用这些空间。如图 所示,将100个字节的数据缓存到128个字节的Chunk中,剩余的28个字节就浪费掉了(这就是内部碎片,但相比外部碎片是可控的,也是可再利用的)。
couchbase 和redis 比较_第5张图片

▲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 和redis 比较_第6张图片


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

couchbase 和redis 比较_第7张图片


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

couchbase 和redis 比较_第8张图片

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

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

下图是Redis Cluster的分布式存储架构:
couchbase 和redis 比较_第9张图片

其中节点与节点之间通过二进制协议进行通信,节点与客户端之间通过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 和redis 比较_第10张图片


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


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


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


Redis&Conchbase的缓存系统选型:

couchbase 和redis 比较_第11张图片

couchbase 和redis 比较_第12张图片






此文转自: http://rdc.hundsun.com/portal/article/736.html


http://blog.jiguang.cn/couchbase_distributed_storage/

你可能感兴趣的:(redis,couchbase)