做者:Kaito
来源:kaito-kidd.com/2020/07/07/redis-cluster-codis-twemproxyjava
以前咱们提到,为了保证Redis的高可用,主要须要如下几个方面:面试
咱们简单理一下这几个方案的特色,以及它们之间的联系。redis
数据持久化本质上是为了作数据备份,有了数据持久化,当Redis宕机时,咱们能够把数据从磁盘上恢复回来,但在数据恢复以前,服务是不可用的,并且数据恢复的时间取决于实例的大小,数据量越大,恢复起来越慢。算法
而主从复制则是部署多个副本节点,多个副本节点实时复制主节点的数据,当主节点宕机时,咱们有完整的副本节点可使用。另外一方面,若是咱们业务的读请求量很大,主节点没法承受全部的读请求,多个副本节点能够分担读请求,实现读写分离,这样能够提升Redis的访问性能。spring
但有个问题是,当主节点宕机时,咱们虽然有完整的副本节点,但须要手动操做把从节点提高为主节点继续提供服务,若是每次主节点故障,都须要人工操做,这个过程既耗时耗力,也没法保证及时性,高可用的程度将大打折扣。如何优化呢?数据库
有了数据持久化、主从复制、故障自动恢复这些功能,咱们在使用Redis时是否是就能够高枕无忧了?架构
答案是否认的,若是咱们的业务大部分都是读请求,可使用读写分离提高性能。但若是写请求量也很大呢?如今是大数据时代,像阿里、腾讯这些大致量的公司,每时每刻都拥有很是大的写入量,此时若是只有一个主节点是没法承受的,那如何处理呢?intellij-idea
这就须要集群化!简单来讲实现方式就是,多个主从节点构成一个集群,每一个节点存储一部分数据,这样写请求也能够分散到多个主节点上,解决写压力大的问题。同时,集群化能够在节点容量不足和性能不够时,动态增长新的节点,对进群进行扩容,提高性能。运维
从这篇文章开始,咱们就开始介绍Redis的集群化方案。固然,集群化也意味着Redis部署架构更复杂,管理和维护起来成本也更高。并且在使用过程当中,也会遇到不少问题,这也衍生出了不一样的集群化解决方案,它们的侧重点各不相同。异步
要想实现集群化,就必须部署多个主节点,每一个主节点还有可能有多个从节点,以这样的部署结构组成的集群,才能更好地承担更大的流量请求和存储更多的数据。
能够承担更大的流量是集群最基础的功能,通常集群化方案还包括了上面提到了数据持久化、数据复制、故障自动恢复功能,利用这些技术,来保证集群的高性能和高可用。
另外,优秀的集群化方案还实现了在线水平扩容功能,当节点数量不够时,能够动态增长新的节点来提高整个集群的性能,并且这个过程是在线完成的,业务无感知。
业界主流的Redis集群化方案主要包括如下几个:
它们还能够用是否中心化来划分,其中客户端分片、Redis Cluster属于无中心化的集群方案,Codis、Tweproxy属于中心化的集群方案。
是否中心化是指客户端访问多个Redis节点时,是直接访问仍是经过一个中间层Proxy来进行操做,直接访问的就属于无中心化的方案,经过中间层Proxy访问的就属于中心化的方案,它们有各自的优劣,下面分别来介绍。
客户端分片主要是说,咱们只须要部署多个Redis节点,具体如何使用这些节点,主要工做在客户端。
客户端经过固定的Hash算法,针对不一样的key计算对应的Hash值,而后对不一样的Redis节点进行读写。
客户端分片集群模式
客户端分片须要业务开发人员事先评估业务的请求量和数据量,而后让DBA部署足够的节点交给开发人员使用便可。
这个方案的优势是部署很是方便,业务须要多少个节点DBA直接部署交付便可,剩下的事情就须要业务开发人员根据节点数量来编写key的请求路由逻辑,制定一个规则,通常采用固定的Hash算法,把不一样的key写入到不一样的节点上,而后再根据这个规则进行数据读取。
可见,它的缺点是业务开发人员使用Redis的成本较高,须要编写路由规则的代码来使用多个节点,并且若是事先对业务的数据量评估不许确,后期的扩容和迁移成本很是高,由于节点数量发生变动后,Hash算法对应的节点也就再也不是以前的节点了。
因此后来又衍生出了一致性哈希算法,就是为了解决当节点数量变动时,尽可能减小数据的迁移和性能问题。
这种客户端分片的方案通常用于业务数据量比较稳定,后期不会有大幅度增加的业务场景下使用,只须要前期评估好业务数据量便可。
随着业务和技术的发展,人们愈加以为,当我须要使用Redis时,咱们不想关心集群后面有多少个节点,咱们但愿咱们使用的Redis是一个大集群,当咱们的业务量增长时,这个大集群能够增长新的节点来解决容量不够用和性能问题。
这种方式就是服务端分片方案,客户端不须要关心集群后面有多少个Redis节点,只须要像使用一个Redis的方式去操做这个集群,这种方案将大大下降开发人员的使用成本,开发人员能够只须要关注业务逻辑便可,不须要关心Redis的资源问题。
多个节点组成的集群,如何让开发人员像操做一个Redis时那样来使用呢?这就涉及到多个节点是如何组织起来提供服务的,通常咱们会在客户端和服务端中间增长一个代理层,客户端只须要操做这个代理层,代理层实现了具体的请求转发规则,而后转发请求到后面的多个节点上,所以这种方式也叫作中心化方式的集群方案,Codis就是以这种方式实现的集群化方案。
Codis是由国人前豌豆荚大神开发的,采用中心化方式的集群方案。由于须要代理层Proxy来进行全部请求的转发,因此对Proxy的性能要求很高,Codis采用Go语言开发,兼容了开发效率和性能。
Codis包含了多个组件:
可见Codis的组件仍是挺多的,它的功能很是全,除了请求转发功能以外,还实现了在线数据迁移、节点扩容缩容、故障自动恢复等功能。
Codis的Proxy就是负责请求转发的组件,它内部维护了请求转发的具体规则,Codis把整个集群划分为1024个槽位,在处理读写请求时,采用crc32
Hash算法计算key的Hash值,而后再根据Hash值对1024个槽位取模,最终找到具体的Redis节点。
Codis最大的特色就是能够在线扩容,在扩容期间不影响客户端的访问,也就是不须要停机。这对业务使用方是极大的便利,当集群性能不够时,就能够动态增长节点来提高集群的性能。
为了实如今线扩容,保证数据在迁移过程当中还有可靠的性能,Codis针对Redis进行了修改,增长了针对异步迁移数据相关命令,它基于Redis 3.2.8进行开发,上层配合Dashboard和Proxy组件,完成对业务无损的数据迁移和扩容功能。
所以,要想使用Codis,必须使用它内置的Redis,这也就意味着Codis中的Redis是否能跟上官方最新版的功能特性,可能没法获得保障,这取决于Codis的维护方,目前Codis已经再也不维护,因此使用Codis时只能使用3.2.8版的Redis,这是一个痛点。
另外,因为集群化都须要部署多个节点,所以操做集群并不能彻底像操做单个Redis同样实现全部功能,主要是对于操做多个节点可能产生问题的命令进行了禁用或限制,具体可参考Codis不支持的命令列表。
但这不影响它是一个优秀的集群化方案,因为我司使用Redis集群方案较早,那时Redis Cluster还不够成熟,因此我司使用的Redis集群方案就是Codis。
目前个人工做主要是围绕Codis展开的,咱们公司对Codis进行了定制开发,还对Redis进行了一些改造,让Codis支持了跨多个数据中心的数据同步。
Twemproxy是由Twitter开源的集群化方案,它既能够作Redis Proxy,还能够作Memcached Proxy。
它的功能比较单一,只实现了请求路由转发,没有像Codis那么全面有在线扩容的功能,它解决的重点就是把客户端分片的逻辑统一放到了Proxy层而已,其余功能没有作任何处理。
Tweproxy推出的时间最久,在早期没有好的服务端分片集群方案时,应用范围很广,并且性能也极其稳定。
但它的痛点就是没法在线扩容、缩容,这就致使运维很是不方便,并且也没有友好的运维UI可使用。Codis就是由于在这种背景下才衍生出来的。
采用中间加一层Proxy的中心化模式时,这就对Proxy的要求很高,由于它一旦出现故障,那么操做这个Proxy的全部客户端都没法处理,要想实现Proxy的高可用,还须要另外的机制来实现,例如Keepalive。
并且增长一层Proxy进行转发,必然会有必定的性能损耗,那么除了客户端分片和上面提到的中心化的方案以外,还有比较好的解决方案么?
Redis官方推出的Redis Cluster另辟蹊径,它没有采用中心化模式的Proxy方案,而是把请求转发逻辑一部分放在客户端,一部分放在了服务端,它们之间互相配合完成请求的处理。
Redis Cluster是在Redis 3.0推出的,早起的Redis Cluster因为没有通过严格的测试和生产验证,因此并无普遍推广开来。也正是在这样的背景下,业界衍生了出了上面所说的中心化集群方案:Codis和Tweproxy。
但随着Redis的版本迭代,Redis官方的Cluster也愈来愈稳定,更多人开始采用官方的集群化方案。也正是由于它是官方推出的,因此它的持续维护性能够获得保障,这就比那些第三方的开源方案更有优点。
Redis Cluster没有了中间的Proxy代理层,那么是如何进行请求的转发呢?
Redis把请求转发的逻辑放在了Smart Client中,要想使用Redis Cluster,必须升级Client SDK,这个SDK中内置了请求转发的逻辑,因此业务开发人员一样不须要本身编写转发规则,Redis Cluster采用16384个槽位进行路由规则的转发。
Redis
没有了Proxy层进行转发,客户端能够直接操做对应的Redis节点,这样就少了Proxy层转发的性能损耗。
Redis Cluster也提供了在线数据迁移、节点扩容缩容等功能,内部还内置了哨兵完成故障自动恢复功能,可见它是一个集成全部功能于一体的Cluster。所以它在部署时很是简单,不须要部署过多的组件,对于运维极其友好。
Redis Cluster在节点数据迁移、扩容缩容时,对于客户端的请求处理也作了相应的处理。当客户端访问的数据正好在迁移过程当中时,服务端与客户端制定了一些协议,来告知客户端去正确的节点上访问,帮助客户端订正本身的路由规则。
虽然Redis Cluster提供了在线数据迁移的功能,但它的迁移性能并不高,迁移过程当中遇到大key时还有可能长时间阻塞迁移的两个节点,这个功能相较于Codis来讲,Codis数据迁移性能更好。
如今愈来愈多的公司开始采用Redis Cluster,有能力的公司还在它的基础上进行了二次开发和定制,来解决Redis Cluster存在的一些问题,咱们期待Redis Cluster将来有更好的发展。
比较完了这些集群化方案,下面咱们来总结一下。
# | 客户端分片 | Codis | Tweproxy | Redis Cluster |
---|---|---|---|---|
集群模式 | 无中心化 | 中心化 | 中心化 | 无中心化 |
使用方式 | 客户端编写路由规则代码,直连Redis | 经过Proxy访问 | 经过Proxy访问 | 使用Smart Client直连Redis,Smart Client内置路由规则 |
性能 | 高 | 有性能损耗 | 有性能损耗 | 高 |
支持的数据库数量 | 多个 | 多个 | 多个 | 一个 |
Pipeline | 支持 | 支持 | 支持 | 仅支持单个节点Pipeline,不支持跨节点 |
需升级客户端SDK? | 否 | 否 | 否 | 是 |
支持在线水平扩容? | 不支持 | 支持 | 不支持 | 支持 |
Redis版本 | 支持最新版 | 仅支持3.2.8,升级困难 | 支持最新版 | 支持最新版 |
可维护性 | 运维简单,开发人员使用成本高 | 组件较多,部署复杂 | 只有Proxy组件,部署简单 | 运维简单,官方持续维护 |
故障自动恢复 | 需部署哨兵 | 需部署哨兵 | 需部署哨兵 | 内置哨兵逻辑,无需额外部署 |
业界主流的集群化方案就是以上这些,并对它们的特色和区别作了简单的介绍,咱们在开发过程当中选择本身合适的集群方案便可,但最好是理解它们的实现原理,在使用过程当中遇到问题才能够更从容地去解决。
近期热文推荐:
1.1,000+ 道 Java面试题及答案整理(2021最新版)
2.终于靠开源项目弄到 IntelliJ IDEA 激活码了,真香!
3.阿里 Mock 工具正式开源,干掉市面上全部 Mock 工具!
4.Spring Cloud 2020.0.0 正式发布,全新颠覆性版本!
以为不错,别忘了随手点赞+转发哦!