Linux下redis集群方案之redis cluster的搭建部署(redis版本:redis-5.0.3)

 

对于Redis集群方案有好多种,基本常用的就是twemproxy,codis,redis  cluster这三种解决方案。

 

本博文介绍redis  cluster

 

上篇博文实现redis的高可用,针对的主要是master宕机的情况,我们发现所有节点的数据都是一样的,那么一旦数据量过大,redis也会存在效率下降的问题,redis3.0版本正式推出后,有效地解决了redis分布式方面的需求,当遇到单机内存,并发,流量等瓶颈时,可以采用Cluster架构方法达到负载均衡的目的。

 

一.redis  cluster集群的介绍

 

1.redis使用中遇到的瓶颈

 

我们日常在对于redis的使用中,经常会遇到一些问题

  1、容量问题,单实例redis内存无法无限扩充,达到32G后就进入了64位世界,性能下降。

  2、并发性能问题,redis号称单实例10万并发,但也是有尽头的。

 

2.redis-cluster的优势  

 

1、官方推荐,毋庸置疑。

2、去中心化,集群最大可增加1000个节点,性能随节点增加而线性扩展。

3、管理方便,后续可自行增加或摘除节点,移动分槽等等。

4、简单,易上手。

 

3.redis-cluster名词介绍

 

1、master  主节点、

2、slave   从节点

3、slot    槽,一共有16384数据分槽,分布在集群的所有主节点中。

 

4.redis-cluster的设计

Redis集群搭建的方式有多种,例如使用zookeeper等,但从redis 3.0之后版本支持redis-cluster集群,Redis-Cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有 节点连接。其redis-cluster架构图如下:

redis-cluster

图中描述的是六个redis实例构成的集群

6379端口为客户端通讯端口

16379端口为集群总线端口

集群内部划分为16384个数据分槽,分布在三个主redis中。

从redis中没有分槽,不会参与集群投票,也不会帮忙加快读取数据,仅仅作为主机的备份。

三个主节点中平均分布着16384数据分槽的三分之一,每个节点中不会存有有重复数据,仅仅有自己的从机帮忙冗余。

 

其结构特点:

     1、所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。
     2、节点的fail是通过集群中超过半数的节点检测失效时才生效。
     3、客户端与redis节点直连,不需要中间proxy层。客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
     4、redis-cluster把所有的物理节点映射到[0-16383]slot上,cluster 负责维护node<->slot<->value。

     5、Redis集群预分好16384个桶,当需要在 Redis 集群中放置一个 key-value 时,根据 CRC16(key) mod 16384的值,决定将一个key放到哪个桶中。

 

 5.redis cluster节点分配

 

        假设我们现在有三个主节点,分别是:A, B, C 三个节点,它们可以是一台机器上的三个端口,也可以是三台不同的服务器。那么,采用哈希槽 (hash slot)的方式来分配16384个slot 的话,它们三个节点分别承担的slot 区间是:


      节点A覆盖0-5460;
      节点B覆盖5461-10922;
      节点C覆盖10923-16383。

    

     获取数据:

        如果存入一个值,按照redis cluster哈希槽的算法: CRC16('key')%16384 = 6782。 那么就会把这个key 的存储分配到 B 上了。同样,当我连接(A,B,C)任何一个节点想获取'key'这个key时,也会这样的算法,然后内部跳转到B节点上获取数据。

    

     新增一个主节点:

        新增一个节点D,redis cluster的这种做法是从各个节点的前面各拿取一部分slot到D上,我会在接下来的实践中实验。大致就会变成这样:
  

    节点A覆盖1365-5460
    节点B覆盖6827-10922
    节点C覆盖12288-16383
    节点D覆盖0-1364,5461-6826,10923-12287


     同样删除一个节点也是类似,移动完成后就可以删除这个节点了。

 

6.Redis Cluster主从模式

          redis cluster 为了保证数据的高可用性,加入了主从模式,一个主节点对应一个或多个从节点,主节点提供数据存取,从节点则是从主节点拉取数据备份,当这个主节点挂掉后,就会有这个从节点选取一个来充当主节点,从而保证集群不会挂掉。

      上面那个例子里,集群有ABC三个主节点,,如果这3个节点都没有加入从节点,如果B挂掉了,我们就无法访问整个集群了。A和C的slot也无法访问。

     所以我们在集群建立的时候,一定要为每个主节点都添加了从节点, 比如像这样,,集群包含主节点A、B、C,,以及从节点A1、B1、C1,那么即使B挂掉系统也可以继续正确工作。

     B1节点替代了B节点,所以Redis集群将会选择B1节点作为新的主节点,集群将会继续正确地提供服务。 当B重新开启后,它就会变成B1的从节点。

    不过需要注意,如果节点B和B1同时挂了,Redis集群就无法继续正确地提供服务了。

 

二.实验环境

 

1.selinux和firewalld状态为disabled

2.各主机信息如下:

主机 ip
server1 172.25.83.1

3.节点准备(官方推荐三主三从的配置方式。

redis3.0及以上版本实现,集群中至少应该有奇数个节点,所以至少有三个节点,每个节点至少有一个备份节点,所以下面使用6节点(主节点、备份节点由redis-cluster集群确定)。

172.25.83.1:7001,172.25.83.1:7002,172.25.83.1:7003,172.25.83.1:7004,172.25.83.1:7005,172.25.83.1:7006搭建初始集群。

172.25.83.1:7007,172.25.83.1:7008扩容时用到。

 

三.redis  cluster集群的部署

 

配置server1:(因为server1之前是做过主从切换的,所以redis已经安装好。

 

1.停掉redis服务(redis服务本身监听的端口是6379端口)

 

[root@server1 ~]# /etc/init.d/redis_6379 stop

 

 

2.创建目录,用于存放redis  Cluster对应的节点配置文件

 

[root@server1 ~]# mkdir /usr/local/rediscluster
[root@server1 ~]# cd /usr/local/rediscluster/
[root@server1 rediscluster]# mkdir 700{1..6}
[root@server1 rediscluster]# ls
7001  7002  7003  7004  7005  7006

 

3.编写redis Cluster对应的节点的配置文件,并启动redis  Cluster对应的所有节点

 

(1)编辑配置文件,下面给出的是一个节点7001的配置文件(其余节点(7002-7006)的配置文件跟这个配置文件类似,只需要将其中的7001改为对应的节点即可

[root@server1 rediscluster]# cd 7001/
[root@server1 7001]# vim redis.conf
port 7001                #端口
cluster-enabled yes      #如果是yes,表示启用集群,否则以单例模式启动
cluster-config-file nodes.conf     #请注意,尽管有此选项的名称,但这不是用户可编辑的配置文件,而是Redis群集节点每次发生更改时自动保留群集配置(基本上为状态)的文件,以便能够 在启动时重新读取它。 该文件列出了群集中其他节点,它们的状态,持久变量等等。 由于某些消息的接收,通常会将此文件重写并刷新到磁盘上。
cluster-node-timeout 5000     #Redis群集节点超过不可用的最长时间,而会将其视为失败。 如果主节点超过指定的时间不可达,它将由其从属设备进行故障切换。 此参数控制Redis群集中的其他重要事项。 值得注意的是,每个无法在指定时间内到达大多数主节点的节点将停止接受查询。
appendonly yes     #是否开启appendonlylog,开启的话每次写操作会记一条log,这会提高数据抗风险能力,但影响效率。
pidfile "/usr/local/rediscluster/7001/redis.pid"      #pid文件存放的位置
logfile "/usr/local/rediscluster/7001/redis.log"      #日志文件存放的位置 
daemonize yes        #打入后台
dir "/usr/local/rediscluster/7001"    #该节点所在目录

 

Linux下redis集群方案之redis cluster的搭建部署(redis版本:redis-5.0.3)_第1张图片

 

(2)启动节点,下面给出的是7001节点的启动方法(其余节点(7002-7006)的启动方法,类似。只需要把7001改为对应的节点即可

[root@server1 7001]# redis-server redis.conf   #启动7001节点 
[root@server1 7001]# netstat -antulpe     #查看端口,是否有7001端口,以确保7001端口已经启动

 

Linux下redis集群方案之redis cluster的搭建部署(redis版本:redis-5.0.3)_第2张图片

 

4.创建集群(集群中的主从节点是随机的

redis3版本利用redis-trib.rb命令来创建集群,如下所示:

节点全部启动后,每个节点目前只能识别出自己的节点信息,彼此之间并不知道对方的存在;

采用redis-trib.rb来实现集群的快速搭建,redis-trib.rb是采用Rudy实现的集群管理工具,内部通过Cluster相关命令帮我们实现简化集群创建,检查,槽迁移和均衡等常见的运维操作。

 

(1)安装redis-trib所需的 ruby环境

 

[root@server1 ~]# yum install ruby -y

 

(2)将redis-trib.rb对应的脚本文件放到/usr/local/bin目录下,以便直接敲击redis-trib.rb命令

 

[root@server1 ~]# cd redis-5.0.3/src/
[root@server1 src]# cp redis-trib.rb /usr/local/bin/

 

 

(3)使用redis-trib.rb创建集群

 

Linux下redis集群方案之redis cluster的搭建部署(redis版本:redis-5.0.3)_第3张图片

 

 

 

既然redis-trib.rb命令用不了,那么/usr/local/bin目录下的redis-trib.rb脚本就可以删除了。

 

 

但是redis5版本,不再使用redis-trib.rb来命令来创建集群了,从上面的提示,我们可以看出,需要使用redis-cluster来创建集群,过程如下:


 

[root@server1 ~]# redis-cli --cluster help    #在使用redis-cli --cluster命令之前,可以先查看下redis-cli --cluster命令的帮助
  create         host1:port1 ... hostN:portN
                 --cluster-replicas 
[root@server1 ~]# redis-cli --cluster create --cluster-replicas 1 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006   #输入yes
# 使用create命令 --replicas 1 参数表示为每个主节点创建一个从节点,其他参数是实例的地址集合。

 

创建过程中会给出主从节点角色分配的计划,如下图所示

Linux下redis集群方案之redis cluster的搭建部署(redis版本:redis-5.0.3)_第4张图片

为什么172.25.83.1:7001,172.25.83.1:7002,172.25.83.1:7003是主节点,请看上图,当我们同意这份计划之后,输入yes,redis-cli  --cluster开始执行节点握手和槽分配操作,输出如下:

 

Linux下redis集群方案之redis cluster的搭建部署(redis版本:redis-5.0.3)_第5张图片

最终可以看到:(当然下面的信息,也可以登录每个节点(例如:redis-cli  -p  7001),查看每个节点的info replication,来获取)

(1)主节点:7001;对应的从节点为:7005

(2)主节点:7002;对应的从节点为:7006

(3)主节点:7003;对应的从节点为:7004

 

此时可以利用下面的命令来查看该集群的信息以查看该集群的主节点:

[root@server1 bin]# redis-cli --cluster info 127.0.0.1:7001    #节点7001,可以换为任何一个节点,看到的结果都是一样的

 

Linux下redis集群方案之redis cluster的搭建部署(redis版本:redis-5.0.3)_第6张图片

 

redis集群的测试:测试存取值

 

客户端连接集群redis-cli需要带上 -c ,redis-cli -c -p 端口号

Linux下redis集群方案之redis cluster的搭建部署(redis版本:redis-5.0.3)_第7张图片

 

根据redis-cluster的key值分配,name应该分配到节点7002[5461-10922]上,上面显示redis cluster自动从7001跳转到了7002节点。

我们可以测试一下7004从节点获取name值

 

 

结论:

7006位7003的从节点,从上面也是自动跳转至7002获取值,这也是redis cluster的特点,它是去中心化,每个节点都是对等的,连接哪个节点都可以获取和设置数据。

 

四.redis  cluster集群的故障迁移

 

(1)查看7002节点上的所有key,并手动将7002节点挂掉

 

 

此时看到进程中已经没有7002节点对应的进程了

Linux下redis集群方案之redis cluster的搭建部署(redis版本:redis-5.0.3)_第8张图片

 

(2)再次查看集群的信息,可以看到7006节点(之前7002节点的从节点)已经成为主节点。查看7006节点的所有key,可以看出7006节点承担着7002节点的角色。对外提供的服务不受影响

 

Linux下redis集群方案之redis cluster的搭建部署(redis版本:redis-5.0.3)_第9张图片

 

但是此时,如果将7006节点也手动down掉,那么该集群也就费了。

Linux下redis集群方案之redis cluster的搭建部署(redis版本:redis-5.0.3)_第10张图片

 

五.redis  cluster集群的扩容

 

配置过程

 

新增节点:172.25.83.1:7007,172.25.83.1:7008。配置文件与之前的基本一致

1.创建目录

 

[root@server1 rediscluster]# mkdir 700{7,8}
[root@server1 rediscluster]# ls
7001  7002  7003  7004  7005  7006  7007  7008

 

2.编辑配置文件

 

[root@server1 7007]# vim redis.conf

Linux下redis集群方案之redis cluster的搭建部署(redis版本:redis-5.0.3)_第11张图片

 

[root@server1 7008]# vim redis.conf

Linux下redis集群方案之redis cluster的搭建部署(redis版本:redis-5.0.3)_第12张图片

 

3.启动7007和7008节点

 

[root@server1 7007]# redis-server redis.conf
[root@server1 7008]# redis-server redis.conf
[root@server1 7008]# ps ax

 

Linux下redis集群方案之redis cluster的搭建部署(redis版本:redis-5.0.3)_第13张图片

 

4.加入集群

 

(1)新增主节点

[root@server1 7008]# redis-cli --cluster help
add-node       new_host:new_port existing_host:existing_port
               --cluster-slave
               --cluster-master-id 
#existing_port——这个是必传参数,用来从一个节点获取整个集群信息,相当于获取集群信息的入口。
check          host:port
               --cluster-search-multiple-owners
#host:port——这个是必传参数,用来从一个节点获取整个集群信息,相当于获取集群信息的入口。
[root@server1 7008]# redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7001  
#往集群中添加端口7007,
#存在的端口可以写7001-7006中的任意一个
[root@server1 7008]# redis-cli --cluster check 127.0.0.1:7001   
#检测节点,以查看7007节点的id号,以便将7008加入集群,作为7007的从节点。
#端口可以写7001-7007中的任意一个

 

Linux下redis集群方案之redis cluster的搭建部署(redis版本:redis-5.0.3)_第14张图片

 

(2)新增从节点

[root@server1 7008]# redis-cli --cluster add-node 127.0.0.1:7008 127.0.0.1:7007 --cluster-slave --cluster-master-id "239b6e3dfa0d35fb64ed7b3c839ec99129107a90"  
#将7008节点添加成7007的从节点
#这里的239b6e3dfa0d35fb64ed7b3c839ec99129107a90为节点7007的id号
#这里的第二个节点,必须写7007,不能写别的节点。因为这步是要将节点7008添加称为7007的节点
[root@server1 7008]# redis-cli --cluster check 127.0.0.1:7001   
#检测节点,以查看7007节点和7008节点是否添加成功,并查看槽的分配情况

 

Linux下redis集群方案之redis cluster的搭建部署(redis版本:redis-5.0.3)_第15张图片

 

至此,集群的添加也就完成了。

 

5.迁移槽和数据

 

[root@server1 7008]# redis-cli --cluster help
 reshard        host:port
                --cluster-from 
                --cluster-to 
                --cluster-slots 
                --cluster-yes
                --cluster-timeout 
                --cluster-pipeline 
                --cluster-replace
#host:port——这个是必传参数,用来从一个节点获取整个集群信息,相当于获取集群信息的入口。
[root@server1 7008]# redis-cli --cluster reshard 127.0.0.1:7007 --cluster-from all --cluster-to "239b6e3dfa0d35fb64ed7b3c839ec99129107a90" --cluster-slots 300 --cluster-yes       
#从所有节点迁移300个槽给127.0.0.1:7007,这里的"239b6e3dfa0d35fb64ed7b3c839ec99129107a90"为节点7007的id号;
#这里的节点7007可以写7001-7008中的任意一个节点任意的一个节点,因为帮助中没有表明是已经存在的节点,还是新节点,所以都可以。

#这里也可以写4096个槽,如果这里写4096(13684/4=4096),那么槽就得到了平均分配,也就不需要下一步的平均分配槽的操作了。

 

Linux下redis集群方案之redis cluster的搭建部署(redis版本:redis-5.0.3)_第16张图片

 

6.执行命令使得槽平均分配

 

[root@server1 7008]# redis-cli --cluster help
rebalance      host:port
               --cluster-weight 
               --cluster-use-empty-masters
               --cluster-timeout 
               --cluster-simulate
               --cluster-pipeline 
               --cluster-threshold 
               --cluster-replace
host:port:这个是必传参数,用来从一个节点获取整个集群信息,相当于获取集群信息的入口。
--weight :节点的权重,格式为node_id=weight,如果需要为多个节点分配权重的话,需要添加多个--weight 参数,即--weight b31e3a2e=5 --weight 60b8e3a1=5,node_id可为节点名称的前缀,只要保证前缀位数能唯一区分该节点即可。没有传递–weight的节点的权重默认为1。
--auto-weights:这个参数在rebalance流程中并未用到。
--threshold :只有节点需要迁移的slot阈值超过threshold,才会执行rebalance操作。具体计算方法可以参考下面的rebalance命令流程的第四步。
--use-empty-masters:rebalance是否考虑没有节点的master,默认没有分配slot节点的master是不参与rebalance的,设置--use-empty-masters可以让没有分配slot的节点参与rebalance。
--timeout :设置migrate命令的超时时间。
--simulate:设置该参数,可以模拟rebalance操作,提示用户会迁移哪些slots,而不会真正执行迁移操作。
--pipeline :与reshar的pipeline参数一样,定义cluster getkeysinslot命令一次取出的key数量,不传的话使用默认值为10。
[root@server1 7008]# redis-cli --cluster rebalance 127.0.0.1:7008 --cluster-threshold 1 --cluster-use-empty-masters   #平衡集群节点slot数量
[root@server1 7008]# redis-cli --cluster check 127.0.0.1:7008  #检测节点,查看slot的分配情况,以查看是否平衡成功

 

Linux下redis集群方案之redis cluster的搭建部署(redis版本:redis-5.0.3)_第17张图片

 

看到每个主节点的solt数量都是4096(solt的区间为:0-1364;5461-6826;10923-12287),表示solt数量平衡成功。

 

测试过程:

 

测试一下7007主节点和7008从节点获取name值

 


Linux下redis集群方案之redis cluster的搭建部署(redis版本:redis-5.0.3)_第18张图片

 

结论:

节点7007和7008可以得到name的值,表示redis cluster集群的扩容配置成功。值的注意的是:当7008节点获取name值时,自动跳转到了7007节点,而不是之前的7002节点。这是因为:之前redis  cluster在扩容时。将存储name值的slot(5798)转移到7007主节点上了

 

六.redis  cluster集群的收缩

 

我们下线7007和7008节点

 

(1)通过集群节点信息,我们之道7007主节点负责的solt为:0-1364;5461-6826;10923-12287。现在我们把0-1364迁移到7001;5461-6826迁移到7002;10923-12287迁移到7003。

 

[root@server1 7008]# redis-cli --cluster reshard 127.0.0.1:7007
How many slots do you want to move (from 1 to 16384)? 1365   #1365个slot,第一次默认是0-1364
What is the receiving node ID? 14a0f59768d46879c929afc62018421db53a5efd   #7001节点的id
Please enter all the source node IDs.
  Type 'all' to use all the nodes as source nodes for the hash slots.
  Type 'done' once you entered all the source nodes IDs.
Source node #1: 239b6e3dfa0d35fb64ed7b3c839ec99129107a90    #70007节点的id
Source node #2: done
Do you want to proceed with the proposed reshard plan (yes/no)? yes

 

[root@server1 7008]# redis-cli --cluster reshard 127.0.0.1:7007
How many slots do you want to move (from 1 to 16384)? 1366   #移1366个slot,第二次默认是5461-6826
What is the receiving node ID? d93240e95225c62eb00072b378d6956c1a1ac8c8   #7002节点的id
Please enter all the source node IDs.
  Type 'all' to use all the nodes as source nodes for the hash slots.
  Type 'done' once you entered all the source nodes IDs.
Source node #1: 239b6e3dfa0d35fb64ed7b3c839ec99129107a90    #7007节点的id
Source node #2: done 
Do you want to proceed with the proposed reshard plan (yes/no)? yes

 

[root@server1 7008]# redis-cli --cluster reshard 127.0.0.1:7007
How many slots do you want to move (from 1 to 16384)? 1365   #1365个slot,第三次默认是10923-12287
What is the receiving node ID? 6444903d022f2707db089ba53b76ea9170df06b5   #7003的id
Please enter all the source node IDs.
  Type 'all' to use all the nodes as source nodes for the hash slots.
  Type 'done' once you entered all the source nodes IDs.
Source node #1: 239b6e3dfa0d35fb64ed7b3c839ec99129107a90  #7007的id
Source node #2: done    
Do you want to proceed with the proposed reshard plan (yes/no)? yes

 

槽节点迁移完之后,查看集群的信息,发现7007已经没有分配槽了

 

Linux下redis集群方案之redis cluster的搭建部署(redis版本:redis-5.0.3)_第19张图片

 

(2)忘记节点:

由于集群内的节点不停地通过Gossip消息彼此交换节点信息,因此需要通过一种健壮的机制让集群内所有节点忘记下线的节点。也就是说让其他节点不再与要下线的节点进行Gossip消息交换。

 

利用redis-cli  --cluster  del-node命令实现节点下线,先下线从节点再下线主节点,避免不必要的全量复制。命令如下:

 

[root@server1 7008]# redis-cli --cluster help
del-node       host:port node_id
[root@server1 7008]# redis-cli --cluster del-node 127.0.0.1:7008 7fe1e1e925a1a7219d014255278a1a3a9b2cab18    
#下线从节点7008
#该id是7008的id,并且节点必须写7008。不能随便写个节点
[root@server1 7008]# redis-cli --cluster del-node 127.0.0.1:7007 239b6e3dfa0d35fb64ed7b3c839ec99129107a90
#下线主节点7007
#该id是7007的id,并且节点必须写7008。不能随便写个节点

 

Linux下redis集群方案之redis cluster的搭建部署(redis版本:redis-5.0.3)_第20张图片

 

此时查看集群的信息,发现7007和7008节点已经不存在,其进程也已被杀死

 

Linux下redis集群方案之redis cluster的搭建部署(redis版本:redis-5.0.3)_第21张图片

 

Linux下redis集群方案之redis cluster的搭建部署(redis版本:redis-5.0.3)_第22张图片

 

结论:

集群信息中已经没有节点7007和7008,表名redis cluster集群的收缩配置成功。

你可能感兴趣的:(Linux下redis集群方案之redis cluster的搭建部署(redis版本:redis-5.0.3))