Redis 的 3 种集群方案对比,写得很是好!

做者:Kaito

来源:kaito-kidd.com/2020/07/07/redis-cluster-codis-twemproxyjava

以前咱们提到,为了保证Redis的高可用,主要须要如下几个方面:面试

  • 数据持久化
  • 主从复制
  • 自动故障恢复
  • 集群化

咱们简单理一下这几个方案的特色,以及它们之间的联系。redis

数据持久化本质上是为了作数据备份,有了数据持久化,当Redis宕机时,咱们能够把数据从磁盘上恢复回来,但在数据恢复以前,服务是不可用的,并且数据恢复的时间取决于实例的大小,数据量越大,恢复起来越慢。算法

而主从复制则是部署多个副本节点,多个副本节点实时复制主节点的数据,当主节点宕机时,咱们有完整的副本节点可使用。另外一方面,若是咱们业务的读请求量很大,主节点没法承受全部的读请求,多个副本节点能够分担读请求,实现读写分离,这样能够提升Redis的访问性能。spring

但有个问题是,当主节点宕机时,咱们虽然有完整的副本节点,但须要手动操做把从节点提高为主节点继续提供服务,若是每次主节点故障,都须要人工操做,这个过程既耗时耗力,也没法保证及时性,高可用的程度将大打折扣。如何优化呢?数据库

有了数据持久化、主从复制、故障自动恢复这些功能,咱们在使用Redis时是否是就能够高枕无忧了?架构

答案是否认的,若是咱们的业务大部分都是读请求,可使用读写分离提高性能。但若是写请求量也很大呢?如今是大数据时代,像阿里、腾讯这些大致量的公司,每时每刻都拥有很是大的写入量,此时若是只有一个主节点是没法承受的,那如何处理呢?intellij-idea

这就须要集群化!简单来讲实现方式就是,多个主从节点构成一个集群,每一个节点存储一部分数据,这样写请求也能够分散到多个主节点上,解决写压力大的问题。同时,集群化能够在节点容量不足和性能不够时,动态增长新的节点,对进群进行扩容,提高性能。运维

从这篇文章开始,咱们就开始介绍Redis的集群化方案。固然,集群化也意味着Redis部署架构更复杂,管理和维护起来成本也更高。并且在使用过程当中,也会遇到不少问题,这也衍生出了不一样的集群化解决方案,它们的侧重点各不相同。异步

集群化方案

要想实现集群化,就必须部署多个主节点,每一个主节点还有可能有多个从节点,以这样的部署结构组成的集群,才能更好地承担更大的流量请求和存储更多的数据。

能够承担更大的流量是集群最基础的功能,通常集群化方案还包括了上面提到了数据持久化、数据复制、故障自动恢复功能,利用这些技术,来保证集群的高性能和高可用。

另外,优秀的集群化方案还实现了在线水平扩容功能,当节点数量不够时,能够动态增长新的节点来提高整个集群的性能,并且这个过程是在线完成的,业务无感知。

业界主流的Redis集群化方案主要包括如下几个:

  • 客户端分片
  • Codis
  • Twemproxy
  • Redis Cluster

它们还能够用是否中心化来划分,其中客户端分片、Redis Cluster属于无中心化的集群方案,Codis、Tweproxy属于中心化的集群方案。

是否中心化是指客户端访问多个Redis节点时,是直接访问仍是经过一个中间层Proxy来进行操做,直接访问的就属于无中心化的方案,经过中间层Proxy访问的就属于中心化的方案,它们有各自的优劣,下面分别来介绍。

客户端分片

客户端分片主要是说,咱们只须要部署多个Redis节点,具体如何使用这些节点,主要工做在客户端。

客户端经过固定的Hash算法,针对不一样的key计算对应的Hash值,而后对不一样的Redis节点进行读写。

客户端分片集群模式

客户端分片须要业务开发人员事先评估业务的请求量和数据量,而后让DBA部署足够的节点交给开发人员使用便可。

这个方案的优势是部署很是方便,业务须要多少个节点DBA直接部署交付便可,剩下的事情就须要业务开发人员根据节点数量来编写key的请求路由逻辑,制定一个规则,通常采用固定的Hash算法,把不一样的key写入到不一样的节点上,而后再根据这个规则进行数据读取。

可见,它的缺点是业务开发人员使用Redis的成本较高,须要编写路由规则的代码来使用多个节点,并且若是事先对业务的数据量评估不许确,后期的扩容和迁移成本很是高,由于节点数量发生变动后,Hash算法对应的节点也就再也不是以前的节点了。

因此后来又衍生出了一致性哈希算法,就是为了解决当节点数量变动时,尽可能减小数据的迁移和性能问题。

这种客户端分片的方案通常用于业务数据量比较稳定,后期不会有大幅度增加的业务场景下使用,只须要前期评估好业务数据量便可。

Codis

随着业务和技术的发展,人们愈加以为,当我须要使用Redis时,咱们不想关心集群后面有多少个节点,咱们但愿咱们使用的Redis是一个大集群,当咱们的业务量增长时,这个大集群能够增长新的节点来解决容量不够用和性能问题

这种方式就是服务端分片方案,客户端不须要关心集群后面有多少个Redis节点,只须要像使用一个Redis的方式去操做这个集群,这种方案将大大下降开发人员的使用成本,开发人员能够只须要关注业务逻辑便可,不须要关心Redis的资源问题。

多个节点组成的集群,如何让开发人员像操做一个Redis时那样来使用呢?这就涉及到多个节点是如何组织起来提供服务的,通常咱们会在客户端和服务端中间增长一个代理层,客户端只须要操做这个代理层,代理层实现了具体的请求转发规则,而后转发请求到后面的多个节点上,所以这种方式也叫作中心化方式的集群方案,Codis就是以这种方式实现的集群化方案。

Proxy集群模式

Codis架构图

Codis是由国人前豌豆荚大神开发的,采用中心化方式的集群方案。由于须要代理层Proxy来进行全部请求的转发,因此对Proxy的性能要求很高,Codis采用Go语言开发,兼容了开发效率和性能。

Codis包含了多个组件:

  • codis-proxy:主要负责对请求的读写进行转发
  • codis-dashbaord:统一的控制中心,整合了数据转发规则、故障自动恢复、数据在线迁移、节点扩容缩容、自动化运维API等功能
  • codis-group:基于Redis 3.2.8版本二次开发的Redis Server,增长了异步数据迁移功能
  • codis-fe:管理多个集群的UI界面

可见Codis的组件仍是挺多的,它的功能很是全,除了请求转发功能以外,还实现了在线数据迁移、节点扩容缩容、故障自动恢复等功能

Codis的Proxy就是负责请求转发的组件,它内部维护了请求转发的具体规则,Codis把整个集群划分为1024个槽位,在处理读写请求时,采用crc32Hash算法计算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

Twemproxy是由Twitter开源的集群化方案,它既能够作Redis Proxy,还能够作Memcached Proxy。

它的功能比较单一,只实现了请求路由转发,没有像Codis那么全面有在线扩容的功能,它解决的重点就是把客户端分片的逻辑统一放到了Proxy层而已,其余功能没有作任何处理。

Twemproxy架构图

Tweproxy推出的时间最久,在早期没有好的服务端分片集群方案时,应用范围很广,并且性能也极其稳定。

但它的痛点就是没法在线扩容、缩容,这就致使运维很是不方便,并且也没有友好的运维UI可使用。Codis就是由于在这种背景下才衍生出来的。

Redis Cluster

采用中间加一层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个槽位进行路由规则的转发。

ClusterRedis

没有了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 正式发布,全新颠覆性版本!

5.《Java开发手册(嵩山版)》最新发布,速速下载!

以为不错,别忘了随手点赞+转发哦!

相关文章
相关标签/搜索