2-26 3,111 views
原文地址:http://blog.csdn.net/tantexian/article/details/49994753
分布式缓存特性:
1) 高性能:当传统数据库面临大规模数据访问时,磁盘I/O往往成为性能瓶颈,从而导致过高的响应延迟。分布式缓存将高速内存作为数据对象的存储介质,数据以key/value形式存储,理想情况下可以获得DRAM级的读写性能;
2) 动态扩展性:支持弹性扩展,通过动态增加或减少节点应对变化的数据访问负载,提供可预测的性能与扩展性;同时,最大限度地提高资源利用率;
3) 高可用性:可用性包含数据可用性与服务可用性两方面。基于冗余机制实现高可用性,无单点失效(single point of failure),支持故障的自动发现,透明地实施故障切换,不会因服务器故障而导致缓存服务中断或数据丢失。动态扩展时自动均衡数据分区,同时保障缓存服务持续可用;
4) 易用性:提供单一的数据与管理视图;API接口简单,且与拓扑结构无关;动态扩展或失效恢复时无需人工配置;自动选取备份节点;多数缓存系统提供了图形化的管理控制台,便于统一维护;
5) 分布式代码执行(distributed code execution):将任务代码转移到各数据节点并行执行,客户端聚合返回结果,从而有效避免了缓存数据的移动与传输。最新的Java数据网格规范JSR-347中加入了分布式代码执行与Map/reduce的API支持,各主流分布式缓存产品,如IBM WebSphere eXtreme Scale,VMware GemFire,GigaSpaces XAP和Red Hat Infinispan等也都支持这一新的编程模型。
分布式缓存应用场景:
1) 页面缓存。用来缓存Web页面的内容片段,包括HTML、CSS和图片等,多应用于社交网站等;
2) 应用对象缓存。缓存系统作为ORM框架的二级缓存对外提供服务,目的是减轻数据库的负载压力,加速应用访问;
3) 状态缓存。缓存包括Session会话状态及应用横向扩展时的状态数据等,这类数据一般是难以恢复的,对可用性要求较高,多应用于高可用集群(解决分布式Web部署的session同步问题);
4) 并行处理。通常涉及大量中间计算结果需要共享;
5) 事件处理。分布式缓存提供了针对事件流的连续查询(continuous query)处理技术,满足实时性需求;
6) 极限事务处理。分布式缓存为事务型应用提供高吞吐率、低延时的解决方案,支持高并发事务请求处理,多应用于铁路、金融服务和电信等领域;
7) 云计算领域提供分布式缓存服务(例如:青云、UnitedStack等);
8) 任何需要用到缓存的地方,解决本地缓存数据量太小问题。分布式缓存能有效防止本地缓存失效数据库雪崩现象。
两大开源缓存系统对比,Memcache VS Redis:
1) Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储。而Memcache只支持简单数据类型,需要客户端自己处理复杂对象。
2) Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用(PS:持久化在RDB、AOF)。Redis借助了fork命令的copy on write机制。在生成快照时,将当前进程fork出一个子进程,然后在子进程中循环所有的数据,将数据写成为RDB文件。AOF日志的全称是append only file,从名字上我们就能看出来,它是一个追加写入的日志文件。与一般数据库的binlog不同的是,AOF文件是可识别的纯文本,它的内容就是一个个的Redis标准命令。当然,并不是发送到Redis的所有命令都要记录到AOF日志里面,只有那些会导致数据发生修改的命令才会追加到AOF文件。那么每一条修改数据的命令都生成一条日志。(PS:Memcache不支持数据持久存储)。
3) 由于Memcache没有持久化机制,因此宕机所有缓存数据失效。Redis配置为持久化,宕机重启后,将自动加载宕机时刻的数据到缓存系统中。具有更好的灾备机制。
4) Memcache可以使用Magent在客户端进行一致性hash做分布式。Redis支持在服务器端做分布式(PS:Twemproxy/Codis/Redis-cluster多种分布式实现方式)
5) Memcache的简单限制就是键(key)和value的限制。最大键长为250个字符。可以接受的储存数据不能超过1MB(可修改配置文件变大),因为这是典型slab的最大值,不适合虚拟机使用。而Redis的key长度支持到512k。
6) Redis使用的是单线程模型,保证了数据按顺序提交。Memcache需要使用CAS保证数据一致性。CAS(Check and Set)是一个确保并发一致性的机制,属于“乐观锁”范畴;原理很简单:拿版本号,操作,对比版本号,如果一致就操作,不一致就放弃任何操作。
7) CPU利用。由于Redis只使用单核,而Memcache可以使用多核,所以平均每一个核上Redis在存储小数据时比Memcache性能更高。而在100k以上的数据中,Memcache性能要高于Redis。(PS:Redis可以通过开启多个实例来提高CPU利用率,Memcache默认是单线程,需要编译指定参数才能支持多线程。由于分布式缓存是IO密集型系统,所以性能很大程度受限于网络通信,Memcache使用了libevent网络库,Redis自己实现了一套通信库。线程也不是影响吞吐量的重要因素。如第一点来说,一般情况下,程序处理内存数据的速度远高于网卡接收的速度。使用线程好处是可以同时处理多条连接,在极端情况下,可能会提高响应速度。但是单线程有时候比多线程或多进程更快,不需要考虑并发、锁,也不会增加上下文切换等开销,代码更加简洁,执行效率更高。)
8) Memcache内存管理:使用Slab Allocation。原理相当简单,预先分配一系列大小固定的组,然后根据数据大小选择最合适的块存储。避免了内存碎片。(缺点:不能变长,浪费了一定空间)Memcache默认情况下下一个slab的最大值为前一个的1.25倍。
9) Redis内存管理:Redis通过定义一个数组来记录所有的内存分配情况, Redis采用的是包装的malloc/free,相较于Memcache的内存管理方法来说,要简单很多。由于malloc首先以链表的方式搜索已管理的内存中可用的空间分配,导致内存碎片比较多。
总结:
其实对于企业选型Memcache、Redis而言,更多还是应该看业务使用场景(因为Memcache、Redis两者都具有足够高的性能和稳定性)。假若业务场景需要用到持久化缓存功能、或者支持多种数据结构的缓存功能,那么Redis则是最佳选择。
(PS:Redis集群解决方式也优于Memcache,Memcache在客户端一致性hash的集群解决方案,Redis采用无中心的服务器端集群解决方案)
综上所述:为了让缓存系统能够支持更多的业务场景,选择Redis会更优。(目前也越来越多的厂商选择Redis)。
Redis三大集群解决方案对比,Twemproxy VS Codis VS Redis-Cluster
Redis集群三种常见的解决方案:
1) 客户端分片:这种方案将分片工作放在业务程序端,程序代码根据预先设置的路由规则,直接对多个Redis实例进行分布式访问。这样的好处是,不依赖于第三方分布式中间件,实现方法和代码都自己掌控,可随时调整,不用担心踩到坑。这实际上是一种静态分片技术。Redis实例的增减,都得手工调整分片程序。基于此分片机制的开源产品,现在仍不多见。这种分片机制的性能比代理式更好(少了一个中间分发环节)。但缺点是升级麻烦,对研发人员的个人依赖性强——需要有较强的程序开发能力做后盾。如果主力程序员离职,可能新的负责人,会选择重写一遍。所以,这种方式下,可运维性较差。出现故障,定位和解决都得研发和运维配合着解决,故障时间变长。因此这种方案,难以进行标准化运维,不太适合中小公司(除非有足够的DevOPS)。
2) 代理分片:这种方案,将分片工作交给专门的代理程序来做。代理程序接收到来自业务程序的数据请求,根据路由规则,将这些请求分发给正确的Redis实例并返回给业务程序。这种机制下,一般会选用第三方代理程序(而不是自己研发),因为后端有多个Redis实例,所以这类程序又称为分布式中间件。这样的好处是,业务程序不用关心后端Redis实例,运维起来也方便。虽然会因此带来些性能损耗,但对于Redis这种内存读写型应用,相对而言是能容忍的。这是我们推荐的集群实现方案。像基于该机制的开源产品Twemproxy,Codis便是其中代表,应用非常广泛。
3) 服务器端分片:建立在基于无中心分布式架构之上(没有代理节点性能瓶颈问题)。Redis-Cluster即为官方基于该架构的解决方案。Redis Cluster将所有Key映射到16384个Slot中,集群中每个Redis实例负责一部分,业务程序通过集成的Redis Cluster客户端进行操作。客户端可以向任一实例发出请求,如果所需数据不在该实例中,则该实例引导客户端自动去对应实例读写数据。Redis Cluster的成员管理(节点名称、IP、端口、状态、角色)等,都通过节点之间两两通讯,定期交换并更新。
各解决方案代表产品实现方式优缺点:
Twemproxy:
Twemproxy是一种代理分片机制,由Twitter开源。Twemproxy作为代理,可接受来自多个程序的访问,按照路由规则,转发给后台的各个Redis服务器,再原路返回。这个方案顺理成章地解决了单个Redis实例承载能力的问题。当然,Twemproxy本身也是单点,需要用Keepalived做高可用方案。这么些年来,Twemproxy是应用范围最广、稳定性最高、最久经考验的分布式中间件。只是,他还有诸多不方便之处。Twemproxy最大的痛点在于,无法平滑地扩容/缩容。这样增加了运维难度:业务量突增,需增加Redis服务器;业务量萎缩,需要减少Redis服务器。但对Twemproxy而言,基本上都很难操作。或者说,Twemproxy更加像服务器端静态sharding。有时为了规避业务量突增导致的扩容需求,甚至被迫新开一个基于Twemproxy的Redis集群。Twemproxy另一个痛点是,运维不友好,甚至没有控制面板。
Codis:
Codis由豌豆荚于2014年11月开源,基于Go和C开发,是近期涌现的、国人开发的优秀开源软件之一。现已广泛用于豌豆荚的各种Redis业务场景,从各种压力测试来看,稳定性符合高效运维的要求。性能更是改善很多,最初比Twemproxy慢20%;现在比Twemproxy快近100%(条件:多实例,一般value长度)。Codis具有可视化运维管理界面。Codis无疑是为解决Twemproxy缺点而出的新解决方案。因此综合方面会优于Twemproxy很多。目前也越来越多公司选择Codis。Codis引入了Group的概念,每个Group包括1个Redis Master及至少1个Redis Slave,这是和Twemproxy的区别之一。这样做的好处是,如果当前Master有问题,则运维人员可通过Dashboard“自助式”切换到Slave,而不需要小心翼翼地修改程序配置文件。为支持数据热迁移(Auto Rebalance),出品方修改了Redis Server源码,并称之为Codis Server。Codis采用预先分片(Pre-Sharding)机制,事先规定好了,分成1024个slots(也就是说,最多能支持后端1024个Codis Server),这些路由信息保存在ZooKeeper中。
Redis-Cluster:
Reids-Cluster在Redis3.0中推出,支持Redis分布式集群部署模式。采用无中心分布式架构。所有的Redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。节点的fail是通过集群中超过半数的节点检测失效时才生效。客户端与Redis节点直连,不需要中间proxy层。客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可,减少了代理层,大大提高了性能。Redis-Cluster把所有的物理节点映射到[0-16383]slot上,cluster负责维护node<->slot<->key之间的关系。目前Jedis已经支持Redis-Cluster。从计算架构或者性能方面无疑Redis-Cluster是最佳的选择方案。(PS:虽然Redis-Cluster从方案选型上面比较占据优势,但是由于Redis-Cluster刚推出不久,虽然官方宣传已经发布的是文档版本,但稳定性方面还有待验证)。