Codis Twemproxy redis集群

Redis本身仅支持单实例,内存一般最多10~20GB。这无法支撑大型线上业务系统的需求。而且也造成资源的利用率过低——毕竟现在服务器内存动辄100~200GB。
1.1 客户端分片
这种方案将分片工作放在业务程序端,程序代码根据预先设置的路由规则,直接对多个Redis实例进行分布式访问。这样的好处是,不依赖于第三方分布式中间件,实现方法和代码都自己掌控,可随时调整,不用担心踩到坑。
这实际上是一种静态分片技术。Redis实例的增减,都得手工调整分片程序。基于此分片机制的开源产品,现在仍不多见。
这种分片机制的性能比代理式更好(少了一个中间分发环节)。但缺点是升级麻烦,对研发人员的个人依赖性强——需要有较强的程序开发能力做后盾。如果主力程序员离职,可能新的负责人,会选择重写一遍。
所以,这种方式下,可运维性较差。出现故障,定位和解决都得研发和运维配合着解决,故障时间变长。
这种方案,难以进行标准化运维,不太适合中小公司(除非有足够的DevOPS)。
1.2 代理分片
这种方案,将分片工作交给专门的代理程序来做。代理程序接收到来自业务程序的数据请求,根据路由规则,将这些请求分发给正确的Redis实例并返回给业务程序。
这种机制下,一般会选用第三方代理程序(而不是自己研发),因为后端有多个Redis实例,所以这类程序又称为分布式中间件。
这样的好处是,业务程序不用关心后端Redis实例,运维起来也方便。虽然会因此带来些性能损耗,但对于Redis这种内存读写型应用,相对而言是能容忍的。
这是我们推荐的集群实现方案。像基于该机制的开源产品Twemproxy,便是其中代表之一,应用非常广泛。
1.3 Redis Cluster
在这种机制下,没有中心节点(和代理模式的重要不同之处)。所以,一切开心和不开心的事情,都将基于此而展开。
Redis Cluster将所有Key映射到16384个Slot中,集群中每个Redis实例负责一部分,业务程序通过集成的Redis Cluster客户端进行操作。客户端可以向任一实例发出请求,如果所需数据不在该实例中,则该实例引导客户端自动去对应实例读写数据。
Redis Cluster的成员管理(节点名称、IP、端口、状态、角色)等,都通过节点之间两两通讯,定期交换并更新。
由此可见,这是一种非常“重”的方案。已经不是Redis单实例的“简单、可依赖”了。可能这也是延期多年之后,才近期发布的原因之一。
这令人想起一段历史。因为Memcache不支持持久化,所以有人写了一个Membase,后来改名叫Couchbase,说是支持Auto Rebalance,好几年了,至今都没多少家公司在使用。
这是个令人忧心忡忡的方案。为解决仲裁等集群管理的问题,Oracle RAC还会使用存储设备的一块空间。而Redis Cluster,是一种完全的去中心化……
本方案目前不推荐使用,从了解的情况来看,线上业务的实际应用也并不多见。



  1. Twemproxy及不足之处
    Twemproxy是一种代理分片机制,由Twitter开源。Twemproxy作为代理,可接受来自多个程序的访问,按照路由规则,转发给后台的各个Redis服务器,再原路返回。
    这个方案顺理成章地解决了单个Redis实例承载能力的问题。当然,Twemproxy本身也是单点,需要用Keepalived做高可用方案。
    我想很多人都应该感谢Twemproxy,这么些年来,应用范围最广、稳定性最高、最久经考验的分布式中间件,应该就是它了。只是,他还有诸多不方便之处。
    Twemproxy最大的痛点在于,无法平滑地扩容/缩容。
    这样导致运维同学非常痛苦:业务量突增,需增加Redis服务器;业务量萎缩,需要减少Redis服务器。但对Twemproxy而言,基本上都很难操作(那是一种锥心的、纠结的痛……)。
    或者说,Twemproxy更加像服务器端静态sharding。有时为了规避业务量突增导致的扩容需求,甚至被迫新开一个基于Twemproxy的Redis集群。
    Twemproxy另一个痛点是,运维不友好,甚至没有控制面板。
    Codis刚好击中Twemproxy的这两大痛点,并且提供诸多其他令人激赏的特性。



2.1. Twemproxy 的特性
Twemproxy 搭建 redis 集群有以下的优势:



快速 – 据测试,直连 twenproxy 和直连 redis 相比几乎没有性能损失,读写分离后更是能够极大地提高集群响应能力
轻量级 – Twemproxy 通过透明连接池、内存零拷贝以及 epoll 模型实现了足够的快速和轻量化,源码较为简洁精炼
降低负载 – 透明连接池保持前端的连接数,减少后端的连接数,让后端的 redis 节点负载大为降低
分片 – Twemproxy 通过一致性 hash 算法将数据进行分片,从而实现 redis 集群的高速缓存,降低负载
多协议 – 同时支持 redis 与 memcache 集群的搭建
多算法 – 支持多种算法实现一致性哈希分片,包括crc32,crc16,MD5等
配置简单
监控报警丰富 – 虽然他提供的原生监控功能一般较少使用,但其提供的统计信息,如发送了多少读写命令还是有很大的价值的
2.2. Twemproxy 的缺点
Twemproxy 也有着明显的缺点:



单点 – Twemproxy 只实现了静态分片的功能,本身不具备集群功能,但可以通过 keepalive 来解决
运维不友好 – 没有提供控制面板
无法平滑地扩容/缩容 – 这是一个非常大的缺陷,虽然我们可以通过技术手段和方案来尽量避免,但对于运维人员来说仍然是有很大压力的




  1. Codis实践
    Codis由豌豆荚于2014年11月开源,基于Go和C开发,是近期涌现的、国人开发的优秀开源软件之一。性能更是改善很多,最初比Twemproxy慢20%;现在比Twemproxy快近100%(条件:多实例,一般Value长度)。
    3.1 体系架构
    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信息,并提供分布式锁等服务

    第三种 redis 原生的 redis-cluster 同时具备了前两种的特性,既能够实现主备也能够实现故障时的自动选举和切换,因此通常在生产环境中会直接使用 redis-cluster 的方案。
    但是原生的 redis-cluster 存在 MOVED 和 ASK 转向。
    MOVED 转向与 ASK 转向必须由客户端进行处理,而为了增加系统性能,客户端必须维护路由表,这无疑增加了客户端的开发难度。
    业务中也需要考虑使用非集群客户端还是使用支持集群功能的客户端,这对业务开发来说也在很大程度上增加了复杂度,尤其是在不同环境需要切换非集群与集群的场景下,这都是业务开发不愿意面对的。
    而另一方面,MOVED 转向与 ASK 转向的存在意味着,集群中的每个节点都必须暴露给客户端,这通常不是我们希望看到的。
    同时,redis-cluster 还限制我们只能使用 0 号数据库


Category storage