转 Redis集群技术及Codis实践html
转自 :http://blog.51cto.com/navyaijm/1637688git
codis开源地址:https://github.com/CodisLabs/codis程序员
redis是分布式缓存的一种实现,分布式缓存存在的前提在于提升服务器响应能力,原理嘛就在于,直接与io外设存储设备如硬盘,磁带读写属于非高速io,而cpu与内存读写属于高速io因此直接提高了响应能力。github
redis的除了服务器高并发能力以外在于内存的容量,内存容量越高缓存数据量越大,所以须要借助集群化来实现容量扩展,可是集群会丢失单点数据库特性能力,如事务,垮点集合计算。在redis领域集群也叫作分区redis
相应的须要分区算法,来达到合理的负载均衡和读写路由,因此集群也就是分区的关键在于key的分配上,hash算法是实现key合理分配的一个很是适合且广泛的算法算法
“高效运维最佳实践”是InfoQ在2015年推出的精品专栏,由触控科技运维总监萧田国撰写,InfoQ总编辑崔康策划。数据库
诚如开篇文章所言,高效运维包括管理的专业化和技术的专业化。前两篇咱们主要在说些管理相关的内容,本篇说一下技术专业化。但愿读者朋友们能适应这个转换,谢谢。后端
互联网早在几年前就已进入Web 2.0时代,对后台支撑能力的要求,提升了几十倍甚至几百倍。在这个演化过程当中,缓存系统扮演了举足轻重的角色。缓存
运维进化到今天,已经不是重复造轮子的时代。因此,咱们在架构优化和自动化运维中,能够尽量地选用优秀的开源产品,而不是本身彻底从头再来(各类技术geek除外)。服务器
本文主要讨论Redis集群相关技术及新发展,关于Redis运维等内容,之后另开主题讨论。
本文重点推荐Codis——豌豆荚开源的Redis分布式中间件(该项目于4个月前在GitHub开源,目前star已超过2100)。其和Twemproxy相比,有诸多激动人心的新特性,并支持从Twemproxy无缝迁移至Codis。
本文主要目录以下,对Redis比较了解的朋友,可跳过前两部分,直接欣赏Codis相关内容。
1. Redis常见集群技术
1.1 客户端分片
1.2 代理分片
1.3 Redis Cluster
2. Twemproxy及不足之处
3. Codis实践
3.1 体系架构
3.2 性能对比测试
3.3 使用技巧、注意事项
好吧咱们正式开始。
长期以来,Redis自己仅支持单实例,内存通常最多10~20GB。这没法支撑大型线上业务系统的需求。并且也形成资源的利用率太低——毕竟如今服务器内存动辄100~200GB。
为解决单机承载能力不足的问题,各大互联网企业纷纷出手,“自助式”地实现了集群机制。在这些非官方集群解决方案中,物理上把数据“分片”(sharding)存储在多个Redis实例,通常状况下,每一“片”是一个Redis实例。
包括官方近期推出的Redis Cluster,Redis集群有三种实现机制,分别介绍以下,但愿对你们选型有所帮助。
这种方案将分片工做放在业务程序端,程序代码根据预先设置的路由规则,直接对多个Redis实例进行分布式访问。这样的好处是,不依赖于第三方分布式中间件,实现方法和代码都本身掌控,可随时调整,不用担忧踩到坑。
这其实是一种静态分片技术。Redis实例的增减,都得手工调整分片程序。基于此分片机制的开源产品,如今仍很少见。
这种分片机制的性能比代理式更好(少了一个中间分发环节)。但缺点是升级麻烦,对研发人员的我的依赖性强——须要有较强的程序开发能力作后盾。若是主力程序员离职,可能新的负责人,会选择重写一遍。
因此,这种方式下,可运维性较差。出现故障,定位和解决都得研发和运维配合着解决,故障时间变长。
这种方案,难以进行标准化运维,不太适合中小公司(除非有足够的DevOPS)。
这种方案,将分片工做交给专门的代理程序来作。代理程序接收到来自业务程序的数据请求,根据路由规则,将这些请求分发给正确的Redis实例并返回给业务程序。
这种机制下,通常会选用第三方代理程序(而不是本身研发),由于后端有多个Redis实例,因此这类程序又称为分布式中间件。
这样的好处是,业务程序不用关心后端Redis实例,运维起来也方便。虽然会所以带来些性能损耗,但对于Redis这种内存读写型应用,相对而言是能容忍的。
这是咱们推荐的集群实现方案。像基于该机制的开源产品Twemproxy,即是其中表明之一,应用很是普遍。
在这种机制下,没有中心节点(和代理模式的重要不一样之处)。因此,一切开心和不开心的事情,都将基于此而展开。
Redis Cluster将全部Key映射到16384个Slot中,集群中每一个Redis实例负责一部分,业务程序经过集成的Redis Cluster客户端进行操做。客户端能够向任一实例发出请求,若是所需数据不在该实例中,则该实例引导客户端自动去对应实例读写数据。
Redis Cluster的成员管理(节点名称、IP、端口、状态、角色)等,都经过节点之间两两通信,按期交换并更新。
因而可知,这是一种很是“重”的方案。已经不是Redis单实例的“简单、可依赖”了。可能这也是延期多年以后,才近期发布的缘由之一。
这使人想起一段历史。由于Memcache不支持持久化,因此有人写了一个Membase,后来更名叫Couchbase,说是支持Auto Rebalance,好几年了,至今都没多少家公司在使用。
这是个使人忧心忡忡的方案。为解决仲裁等集群管理的问题,Oracle RAC还会使用存储设备的一块空间。而Redis Cluster,是一种彻底的去中心化……
本方案目前不推荐使用,从了解的状况来看,线上业务的实际应用也并很少见。
Twemproxy是一种代理分片机制,由Twitter开源。Twemproxy做为代理,可接受来自多个程序的访问,按照路由规则,转发给后台的各个Redis服务器,再原路返回。
这个方案瓜熟蒂落地解决了单个Redis实例承载能力的问题。固然,Twemproxy自己也是单点,须要用Keepalived作高可用方案。
我想不少人都应该感谢Twemproxy,这么些年来,应用范围最广、稳定性最高、最久经考验的分布式中间件,应该就是它了。只是,他还有诸多不方便之处。
Twemproxy最大的痛点在于,没法平滑地扩容/缩容。
这样致使运维同窗很是痛苦:业务量突增,需增长Redis服务器;业务量萎缩,须要减小Redis服务器。但对Twemproxy而言,基本上都很难操做(那是一种锥心的、纠结的痛……)。
或者说,Twemproxy更加像服务器端静态sharding。有时为了规避业务量突增致使的扩容需求,甚至被迫新开一个基于Twemproxy的Redis集群。
Twemproxy另外一个痛点是,运维不友好,甚至没有控制面板。
Codis恰好击中Twemproxy的这两大痛点,而且提供诸多其余使人激赏的特性。
Codis由豌豆荚于2014年11月开源,基于Go和C开发,是近期涌现的、国人开发的优秀开源软件之一。现已普遍用于豌豆荚的各类Redis业务场景(已获得豌豆荚@刘奇同窗的确认,呵呵)。
从3个月的各类压力测试来看,稳定性符合高效运维的要求。性能更是改善不少,最初比Twemproxy慢20%;如今比Twemproxy快近100%(条件:多实例,通常Value长度)。
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中。
ZooKeeper还维护Codis Server Group信息,并提供分布式锁等服务。
Codis目前仍被精益求精地改进中。其性能,从最初的比Twemproxy慢20%(虽然这对于内存型应用而言,并不明显),到如今远远超过Twemproxy性能(必定条件下)。
咱们进行了长达3个月的测试。测试基于redis-benchmark,分别针对Codis和Twemproxy,测试Value长度从16B~10MB时的性能和稳定性,并进行多轮测试。
一共有4台物理服务器参与测试,其中一台分别部署codis和twemproxy,另外三台分别部署codis server和redis server,以造成两个集群。
从测试结果来看,就Set操做而言,在Value长度<888B时,Codis性能优越优于Twemproxy(这在通常业务的Value长度范围以内)。
就Get操做而言,Codis性能一直优于Twemproxy。
Codis还有不少好玩的东东,从实际使用来看,有些地方也值得注意。
出品方贴心地准备了Codis-port工具。经过它,能够实时地同步 Twemproxy 底下的 Redis 数据到你的 Codis 集群。同步完成后,只需修改一下程序配置文件,将 Twemproxy 的地址改为 Codis 的地址便可。是的,只须要作这么多。
Codis提供一个Java客户端,并称之为Jodis(名字很酷,是吧?)。这样,若是单个Codis Proxy宕掉,Jodis自动发现,并自动规避之,使得业务不受影响(真的很酷!)。
Pipeline使得客户端能够发出一批请求,并一次性得到这批请求的返回结果。这提高了Codis的想象空间。
从实际测试来看,在Value长度小于888B字节时,Set性能迅猛提高;
Get性能亦复如是。
也就是说, Codis仅负责维护当前Redis Server列表,由运维人员本身去保证主从数据的一致性。
这是我最赞扬的地方之一。这样的好处是,没把Codis搞得那么重。也是咱们勇于放手在线上环境中上线的缘由之一。
好吧,粗浅地说两个。但愿Codis不要变得过重。另外,加pipeline参数后,Value长度若是较大,性能反而比Twemproxy要低一些,但愿能有改善(咱们多轮压测结果都如此)。
因篇幅有限,源码分析不在此展开。另外Codis源码、体系结构及FAQ,参见以下连接:https://github.com/wandoulabs/codis
PS:线上文档的可读性,也是至关值得称赞的地方。一句话:很走心,赞!
最后,Redis初学者请参考这个连接:http://www.gamecbg.com/bc/db/redis/13852.html,文字浅显易懂,并且比较全面。
本文获得Codis开发团队刘奇和黄东旭同窗的大力协助,并获得Tim Yang老师等朋友们在内容把控方面的指导。本文共同做者为赵文华同窗,他主要负责Codis及Twemproxy的对比测试。在此一并谢过。