博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Redis详解(十)------ 集群模式详解
阅读量:734 次
发布时间:2019-03-22

本文共 7390 字,大约阅读时间需要 24 分钟。

  在上一篇博客我们介绍了------,哨兵模式主要是解决高可用问题,在master节点宕机时,slave节点能够自动切换成为master节点

  本篇博客我们来介绍Redis的另外一种模式------集群模式.

  PS:我这里搭建演示的版本是redis-5.0.5,这个版本对于集群搭建会有很大的简化,比如最常用的redis-trib.rb脚本功能已经集成到redis-cli工具中了,具体下面会详细介绍。

1、为什么需要集群?

  ①、并发量

  通常来说,单台Redis能够执行10万/秒的命令,这个并发基本上能够满足我们所有需求了,但有时候比如做离线计算,为了更快的得出结果,有时候我们希望超过这个并发,那这个时候单机就不满足我们需求了,就需要集群了.

  ②、数据量

  通常来说,单台服务器的内存大概在16G-256G之间,前面我们说Redis数据量都是存在内存中的,那如果实际业务要保存在Redis的数据量超过了单台机器的内存,这个时候最简单的方法是增加服务器内存,但是单台服务器内存不可能无限制的增加,纵向扩展不了了,便想到如何进行横向扩展.这时候我们就会想将这些业务数据分散存储在多台Redis服务器中,但是要保证多台Redis服务器能够无障碍的进行内存数据沟通,这也就是Redis集群.

2、数据分区方式

  对于集群来说,如何将原来单台机器上的数据拆分,然后尽量均匀的分布到多台机器上,这是我们创建集群首先要考虑的一个问题,通常来说,有如下两种数据分区方式.

  ①、顺序分布

  比如我们有100W条数据,有3台服务器,我们可以将100W/3的结果分别存储到三台服务器上,如下所示:

   

  特点:键值业务相关;数据分散,但是容易造成访问倾斜;支持顺序访问;支持批量操作

  ②、哈希分布

  同样是100W条数据,有3台服务器,通过自定义一个哈希函数,比如节点取余的方法,余数为0的存在第一台服务器,余数为1的存在第二台服务器,余数为2的存储在第三台服务器.如下所示:

  

  特点:数据分散度高;键值分布与业务无关;不支持顺序访问;支持批量操作。

3、一致性哈希分布

  问题:对于上面介绍的哈希分布,大家可以想一下,如果向集群中增加节点,或者集群中有节点宕机,这个时候应该怎么处理?

  ①、增加节点

  

 

   如上图所示,总共10个数据通过节点取余hash(key)%/3 的方式分布到3个节点,这时候由于访问量变大,要进行扩容,由 3 个节点变为 4 个节点。

  我们发现,如图所示,数据除了标红的1 2 没有进行迁移,别的数据都要进行变动,达到了80%,如果这时候并发很高,80%的数据都要从下层节点(比如数据库)获取,会给下层节点造成很大的访问压力,这是不能接受的。

  即使我们进行翻倍扩容,从3个节点增加到6个节点,其数据迁移也在50%左右。

  ②、删除节点

  

  上图其实不管是哪一个节点宕机,其数据迁移量都会超过50%。基本上也是我们所不能接受的。

  那么如何使得集群中新增节点或者删除节点时,数据迁移量最少?——一致性哈希算法诞生。

  PS:关于一致性哈希算法,我会另外写一篇博客进行详细介绍,这里只是大概介绍一下。

  

 

   假设有一个哈希环,从0到2的32次方,均匀的分成三份,中间存放三个节点,沿着顺时针旋转,从Node1到Node2之间的数据,存放在Node2节点上;从Node2到Node3之间的数据,存放在Node3节点上,依次类推。

  假设Node1节点宕机,那么原来Node3到Node1之间的数据这时候改为存放到Node2节点上,Node2到Node3之间数据保持不变,原来Node1到Node2之间的数据还是存放在Node2上,也就是只影响三分之一的数据,节点越多,影响数据越少。

  

  同理,假设增加一个节点,影响的数据甚至更少。

  

 

   当然,实际业务中并不是你节点均匀分布,访问就会很平均,这时候容易造成访问倾斜的问题,这里就会引出虚拟节点的定义。我这里就不做详解了。

4、Redis Cluster虚拟槽分区

  Redis集群数据分布没有使用一致性哈希分布,而是使用虚拟槽分区概念。

  Redis内部内置了序号 0-16383 个槽位,每个槽位可以用来存储一个数据集合,将这些槽位按顺序分配到集群中的各个节点。每次新的数据到来,会通过哈希函数 CRC16(key) 算出将要存储的槽位下标,然后通过该下标找到前面分配的Redis节点,最后将数据存储到该节点中。

  具体情况如下图:(以集群有3个节点为例)

  

   至于为什么Redis不使用一致性哈希分布,而是虚拟槽分区。因为虚拟槽分区虽然没有一致性哈希那么灵活,但是CRC16(key)%16384 已经分布很均匀了,并且对于后面节点增删操作起来也很方便。

5、原生搭建 Redis Cluster

  集群以三主三从的模式来搭建。

①、服务器列表

  

 

②、配置各个节点参数

#配置端口port ${port}#以守护进程模式启动daemonize yes#pid的存放文件pidfile /var/run/redis_${port}.pid#日志文件名logfile "redis_${port}.log"#存放备份文件以及日志等文件的目录dir "/opt/redis/data"  #rdb备份文件名dbfilename "dump_${port}.rdb"#开启集群功能cluster-enabled yes#集群配置文件,节点自动维护cluster-config-file nodes-${port}.conf#集群能够运行不需要集群中所有节点都是成功的cluster-require-full-coverage no

  配置完成后,通过 redis-server redis.conf 命令启动这六个节点。

  启动之后,进程后面会有 cluster 的字样:

  

③、建立各个节点通信

   这里有 6 个节点,我们只需要拉通 1 个节点和另外 5 个节点之间通信,那么每两个节点就能够通信了。命令如下:

redis-cli -h -p ${port1} -a ${password} cluster meet ${ip2}  ${port2}

  这里的 -a 参数表示该Redis节点有密码,如果没有可以不用加此参数。

  实例中的 6 个节点,分别进行如下命令:

redis-cli -p 6379 -a 123 cluster meet 192.168.14.101 6382redis-cli -p 6379 -a 123 cluster meet 192.168.14.102 6380redis-cli -p 6379 -a 123 cluster meet 192.168.14.102 6383redis-cli -p 6379 -a 123 cluster meet 192.168.14.103 6381redis-cli -p 6379 -a 123 cluster meet 192.168.14.103 6384

  执行完毕后,可以查看节点通信信息:

redis-cli -p 6379 -a 123 cluster nodes

  结果如下:

  

 

   或者执行如下命令:

redis-cli -p 6379 -a 123 cluster info

  结果如下:

  

④、分配槽位

  由于我们是三主三从的架构,所以只需要对主服务器分配槽位即可。三个节点,分配序号为 0-16383 ,总共16384 个槽位。

Node1:0~5460Node2:5461~10922Node3:10923~16383

  分配槽位的命令如下:

redis-cli -p ${port} -a ${password} cluster addslots {${startSlot}..${endSlot}}

  比如,对于Node1主节点,我们执行命令如下:

redis-cli -p 6379 -a 123 cluster addslots {0..5462}

  另外两个节点对于上面的命令更改一下槽位数,然后查看集群信息:  

  查看Node1节点信息:

  

⑤、主从配置

  命令如下:

redis-cli -p ${port} -a {password} cluster replicate ${nodeId}

  前面的${port} 表示从节点的端口,这里的nodeId表示主节点的nodeId,如下:

  

 

   如果弄反了,会报如下错误:

(error) ERR To set a master the node must be empty and without assigned slots.

  执行三条命令完毕后,查看节点信息:

  

   这时候,集群状态是成功了。

⑥、测试

  经过如上几步操作,集群搭建成功,我们通过如下命令进入客户端:

redis-cli -c -p ${port} -a {password}

  注意:必须要加 -c 参数,否则进行键值对操作时会报如下错误:

  

   正确进入后,可以正确存值和取值。

  

6、脚本搭建Redis Cluster

   上面原生命令安装Redis Cluster 走下来其实挺费劲的,在实际生产环境中,如果集群数量比较大,操作还是容易出错的。

  不过Redis官方提供了一个安装集群的脚本,在Redis安装目录的src目录下——redis-trib.rb,使用该脚本可以快速搭建Redis Cluster集群。

  注意:redis版本在5之前的集群运行该脚本需要安装ruby环境,而redis5.0之后已经将redis-trib.rb 脚本的功能全部集成到redis-cli之中了,所以如果当前版本是Redis5,那么可以不用安装ruby环境。

  下面我分别介绍这两种方法。

①、Redis5之前使用redis-trib.rb脚本搭建

  redis-trib.rb脚本使用ruby语言编写,所以想要运行次脚本,我们必须安装Ruby环境。安装命令如下:

yum -y install centos-release-scl-rhyum -y install rh-ruby23  scl enable rh-ruby23 bashgem install redis

  安装完成后,我们可以使用 ruby -v 查看版本信息。

  

   Ruby环境安装完成后。运行如下命令:

redis-trib.rb create --replicas 1 192.168.14.101:6379 192.168.14.102:6380 192.168.14.103:6381 192.168.14.101:6382 192.168.14.102:6383 192.168.14.103:6384

  关于这个命令的解释下面会一起介绍。

②、Redis5版本集群搭建 

  前面我们就说过,redis5.0之后已经将redis-trib.rb 脚本的功能全部集成到redis-cli中了,所以我们直接使用如下命令即可:

redis-cli -a ${password} --cluster create 192.168.14.101:6379 192.168.14.102:6380 192.168.14.103:6381 192.168.14.101:6382 192.168.14.102:6383 192.168.14.103:6384 --cluster-replicas 1

  ①、${password} 表示连接Redis的密码,通常整个集群我们要么不设置密码,要么设置成一样的。

  ②、后面的六个ip:port,按照顺序,前面三个是主节点,后面三个是从节点,顺序不能错。

  ③、最后数字 1 表示一个主节点只有一个从节点。和前面的配置相对应。

7、集群扩容

  这里新增两个端口分别是 6390、6391的节点。其中6391节点是6390节点的从节点。

①、配置新增节点文件

  比如,我们将6379节点的配置文件redis.conf 拷贝两份,然后将里面的配置文件里面的字符串 6379 分别替换成 6390 和 6391。

  :%s/6379/6390/g,:%s/6379/6391/g

  替换完成之后,分别启动这两个节点。

  这时候这两个节点都不在集群当中,是两个孤儿节点。

②、将新增主节点加入到集群中

  命令如下:

redis-cli -p existing_port -a ${password} --cluster add-node new_host:new_port existing_host:existing_port

  我这里是将新增的主节点 6390 添加到原来的集群中。

redis-cli -p 6379 -a 123 --cluster add-node 192.168.14.101:6390 192.168.14.101:6379

  添加完毕后,这时候查看集群状态

 

   6390节点已经存在集群中了,但是还没有分配槽位。

③、为新增主节点分配槽位

  分配命令如下:

redis-cli -p existing_port -a ${password} --cluster reshard existing_host:existing_port

  后面的existing_host:existing_port表示原来集群中的任意一个节点,这个命令表示将源节点的一部分槽位分配个新增的节点。

  在分配过程中,会出现如下几个提示:

#后面的2000表示分配2000个槽位给新增节点How many slots do you want to move (from 1 to 16384)? 2000#表示接受节点的NodeId,填新增节点6390的What is the receiving node ID? 64a0779c7baef78c8fd0f2bb6e73f29375e00133d#这里填槽的来源,要么填all,表示所有master节点都拿出一部分槽位分配给新增节点;#要么填某个原有NodeId,表示这个节点拿出一部分槽位给新增节点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: all

  分配成功后,我们查看节点信息:

   我们发现已经给该节点分配了槽位。

④、将新增的从节点添加到集群中

redis-cli -p 6379 -a 123 --cluster add-node 192.168.14.101:6391 192.168.14.101:6379

⑤、建立新增节点的主从关系

  命令如下:

redis-cli -p ${port} -a {password} cluster replicate ${nodeId}

  前面的${port} 表示从节点的端口,这里的nodeId表示主节点的nodeId。

⑥、测试

  查看节点信息,发现4主4从。

   在6379节点新增一个字符串 (k4,v4),然后到6390节点查看:

  

   自此,大功告成。

8、集群收缩

  这里我们将上一步添加的主从节点6390和6391从集群中移除。

①、迁移待移除节点的槽位

  移除之前的节点信息:

redis-cli -p existing_port -a {Redis登录密码} --cluster reshard --cluster-from {待移除的NodeId} --cluster-to {接受移除节点的NodeId} --cluster-slots {移除的槽位个数} existing_host:existing_port

  比如,我这里要移除主节点 6390 的所有槽位,给6379节点。

redis-cli -p 6379 -a 123 --cluster reshard --cluster-from 4a0779c7baef78c8fd0f2bb6e73f29375e00133d --cluster-to 001a22b1edae6ea1699b753d193871824723f375 --cluster-slots 2000 192.168.14.101:6379

  移除完后,查看节点信息,发现6390已经没有槽位了。

 

 ②、移除待删除主从节点

  注意:要首先移除从节点,然后再移除主节点,因为如果你先移除主节点,会触发集群的故障转移。

  所以,我们应该先移除 6391 从节点,然后在移除 6390 主节点。移除命令如下:

redis-cli -p existing_port -a {Redis登录密码} --cluster del-node host:port {待删除的NodeId}

  删除 6391 从节点:

redis-cli -p 6379 -a 123 --cluster del-node 192.168.14.101:6379 3622ec34956b624358722e6f4a2b762574d35bf0

  删除 6390 主节点:

redis-cli -p 6379 -a 123 --cluster del-node 192.168.14.101:6379 4a0779c7baef78c8fd0f2bb6e73f29375e00133d

  

 

转载地址:http://swfwk.baihongyu.com/

你可能感兴趣的文章