redis学习(4)--集群原理与搭建

目录

1.redis集群简介

1.1 简介

1.2 redis集群实现方案

1.3 redis集群原理

2.redis集群安装

2.1 环境准备

2.2 ruby安装

2.3 创建集群

2.4 验证集群信息

2.5 节点增、删操作


1.redis集群简介

1.1 简介

redis 集群是3.0之后才引入的,在3.0之前,使用哨兵(sentinel)机制(本文将不做介绍,大家可另行查阅)来监控各个节点之间的状态。也可通过代理实现(下文介绍)。Redis 集群可谓是让很多人久等了。

redis 集群是一组能进行数据共享的 redis 实例(服务或者节点)的设施,集群可以使用的功能是普通单机 redis 所能使用的功能的一个子集;redis 集群通常具有高可用、可扩展性、分布式、容错等特性。了解redis的集群后,这些晦涩的概念可结合redis的主从、集群分区和集群运维等角度理解体会。

1.2 redis集群实现方案

  • Twitter开发的twemproxy

  • 豌豆荚开发的codis

  • redis官方的redis-cluster

简单说明:

twemproxy架构简单,就是用proxy对后端redis server进行代理,但是由于代理层的消耗性能很低,而且通常涉及多个key的操作都是不支持的,而且本身不支持动态扩容和透明的数据迁移,而且也失去维护,Twitter内部已经不使用了。

codis使用的也是proxy思路,但是做的比较好,是这两种之间的一个中间级,而且支持redis命令是最多的,有图形化GUI管理和监控工具,运维友好,有兴趣可以去研究。

1.3 redis集群原理

Redis 集群键分布算法使用数据分片(sharding)而非一致性哈希(consistency hashing)来实现: 一个 Redis 集群包含 16384 个哈希槽(hash slot), 它们的编号为0、1、2、3……16382、16383,这个槽是一个逻辑意义上的槽,实际上并不存在。redis中的每个key都属于这 16384 个哈希槽的其中一个,存取key时都要进行key->slot的映射计算。它们任何两个master节点之间都是相互连通的(ping-pong。客户端可以与任何一个节点相连接,然后就可以访问集群中的任何一个节点,对其进行存取和其他操作。且每个master可有多个slaver,当master挂掉后slaver可以迅速顶替master,保证集群高可用性。

键-槽映射算法:

HASH_SLOT(key)= CRC16(key) % 16384

其中 CRC16(key) 语句用于计算键 key 的 CRC16 校验和 。key经过公式计算后得到所对应的哈希槽,而哈希槽被某个主节点管理,从而确定key在哪个主节点上存取,这也是redis将数据均匀分布到各个节点上的基础。

集群分区好处:

无论是memcached的一致性哈希算法,还是redis的集群分区,最主要的目的都是在移除、添加一个节点时对已经存在的缓存数据的定位影响尽可能的降到最小。redis将哈希槽分布到不同节点的做法使得用户可以很容易地向集群中添加或者删除节点, 比如说:

1.如果用户将新节点 D 添加到集群中, 那么集群只需要将节点 A 、B 、 C 中的某些槽移动到节点 D 就可以了。

2.与此类似, 如果用户要从集群中移除节点 A , 那么集群只需要将节点 A 中的所有哈希槽移动到节点 B 和节点 C , 然后再移除空白(不包含任何哈希槽)的节点 A 就可以了。

因为将一个哈希槽从一个节点移动到另一个节点不会造成节点阻塞, 所以无论是添加新节点还是移除已存在节点, 又或者改变某个节点包含的哈希槽数量, 都不会造成集群下线,从而保证集群的可用性。

故障分析: 

1.当一台 master 节点掉线时(半数以上master节点与master节点通信超时(cluster-node-timeout),认为当前master节点挂掉),集群中其他的 master 节点将会通过投票的形式在掉线 master 结点的 slave 结点中选举一个节点来代替原先的主节点,并更改其他 slave 节点的主节点指向。

2.如果集群任意挂掉,且当前 master 节点没有 slave 节点。集群进入 fail 状态,也可以理解成集群的 slot 映射[0-16383]不完整时进入fail状态。

3.如果集群超过半数以上 master 挂掉,无论是否有 slave,集群进入 fail 状态。

注: cluster-require-full-coverage:默认关闭,打开集群兼容部分失败。

2.redis集群安装

实验环境:CentOS 7

192.168.179.110:6380   192.168.179.110:6381

192.168.179.113:6380   192.168.179.113:6381

192.168.179.114:6380   192.168.179.114:6381

本次实验使用了3台虚拟机进行,也可只是用一台,开启6个实例即可,以下只演示192.168.179.110机器的操作。

2.1 环境准备

[root@redis ~]# mkdir -p redis/638{0..1}/{conf,db,log}
[root@redis ~]# mv /usr/local/redis/etc/redis.conf redis/6380/conf/   #将redis.conf移到conf目录
[root@redis ~]# mv /usr/local/redis/etc/redis.conf redis/6381/conf/
[root@redis ~]# vim redis/6380/conf/redis.conf
61   bind 192.168.179.110
84   port 6380
128  daemonize yes
150  pidfile /root/redis/6380/db/redis_6380.pid
163  logfile /root/redis/6380/log/redis_6380.log
247  dir /root/redis/6380/db/
721  cluster-enabled yes
729  cluster-config-file nodes-6380.conf
735  cluster-node-timeout 5000

2.2 ruby安装

由于Redis 集群客户端实现很少,redis集群的启动需要用到ruby实现的redis-trib.rb,所以我们需要先安装ruby。

[root@redis ~]# yum install -y ruby rubygems
[root@redis ~]# gem install redis
Fetching: redis-4.0.2.gem (100%)
ERROR:  Error installing redis:
        redis requires Ruby version >= 2.2.2.

注:Gem是一个管理Ruby库和程序的标准包,它通过Ruby Gem(如 http://rubygems.org/ )源来查找、安装、升级和卸载软件包,非常的便捷。

从报错可知,yum安装的ruby版本低于2.2.2,所以我们需要升级ruby。

[root@redis ~]# curl -L get.rvm.io | bash -s stable
# 有报错根据提示执行下面命令,然后重新执行上面命令即可。
[root@redis ~]# gpg2 --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
[root@localhost ~]# source /usr/local/rvm/scripts/rvm
[root@localhost ~]# rvm list known
# MRI Rubies
[ruby-]1.8.6[-p420]
[ruby-]1.8.7[-head] # security released on head
[ruby-]1.9.1[-p431]
[ruby-]1.9.2[-p330]
[ruby-]1.9.3[-p551]
[ruby-]2.0.0[-p648]
[ruby-]2.1[.10]
[ruby-]2.2[.10]
[ruby-]2.3[.7]
[ruby-]2.4[.4]
[ruby-]2.5[.1]
[ruby-]2.6[.0-preview2]
ruby-head
...

 注:RVM 是一个命令行工具,可以提供一个便捷的多版本 Ruby 环境的管理和切换。

[root@redis ~]# rvm install 2.4.0   #安装ruby2.4.0
[root@redis ~]# rvm use 2.4.0       #使用ruby2.4.0
[root@redis ~]# rvm remove 2.0.0    #移除ruby2.0.0  yum版本
[root@redis ~]# ruby --version      #查看当前版本
ruby 2.4.0p0 (2016-12-24 revision 57164) [x86_64-linux]
[root@redis ~]# gem install redis
Fetching: redis-4.0.2.gem (100%)
Successfully installed redis-4.0.2
Parsing documentation for redis-4.0.2
Installing ri documentation for redis-4.0.2
Done installing documentation for redis after 0 seconds
1 gem installed

 2.3 创建集群

 启动redis服务:

[root@redis ~]# redis-server redis/6380/conf/redis.conf
...
[root@redis ~]# netstat -lnpt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 192.168.179.110:16380   0.0.0.0:*               LISTEN      15901/redis-server  
tcp        0      0 192.168.179.110:16381   0.0.0.0:*               LISTEN      15897/redis-server  
tcp        0      0 192.168.179.110:6380    0.0.0.0:*               LISTEN      15901/redis-server  
tcp        0      0 192.168.179.110:6381    0.0.0.0:*               LISTEN      15897/redis-server  

注:每个Redis集群中的节点都需要打开两个TCP连接。一个连接用于正常的给Client提供服务,比如6379,还有一个额外的端口(通过在这个端口号上加10000)作为数据端口,比如16379。第二个端口(本例中就是16379)用于集群总线,这是一个用二进制协议的点对点通信信道。这个集群总线(Cluster bus)用于节点的失败侦测、配置更新、故障转移授权,等等。客户端从来都不应该尝试和这些集群总线端口通信,它们只应该和正常的Redis命令端口进行通信。注意,确保在你的防火墙中开放着两个端口,否则,Redis集群节点之间将无法通信。

 创建集群:

[root@redis ~]# redis-trib.rb create --replicas 1 192.168.179.110:6380 192.168.179.110:6381  192.168.179.113:6380 192.168.179.113:6381 192.168.179.114:6380 192.168.179.114:6381
>>> Creating cluster
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
192.168.179.110:6380    
192.168.179.113:6380
192.168.179.114:6380
Adding replica 192.168.179.113:6381 to 192.168.179.110:6380
Adding replica 192.168.179.110:6381 to 192.168.179.113:6380
Adding replica 192.168.179.114:6381 to 192.168.179.114:6380
...
[OK] All 16384 slots covered.

 注:若连接失败,检查防火墙是否允许等。

参数解析:

create: 创建一个新集群

--replicas 1:表示为每个master创建一个slave

2.4 验证集群信息

查看节点状态:

[root@redis ~]# redis-cli -h 192.168.179.110 -p 6380 cluster nodes

查看节点信息:

[root@redis ~]# redis-cli -h 192.168.179.110 -p 6380 cluster info

关闭节点:

[root@redis ~]# redis-cli -h 192.168.179.110 -p 6380 shutdown

注:交互登录需要加 -c 参数。

思考:

如上图搭建的集群,若192.168.179.114挂掉,岂不是我的集群就over了,这就有一个单点故障问题。对于这个问题,可以先创建3个master节点,在将slave节点逐个添加入集群,指定每个slave节点指向的master节点。

2.5 节点增、删操作

删除节点:

[root@redis ~]# redis-trib.rb del-node 192.168.179.114:6381 353618ef3beb7be9347827980060bcae1a8cfa95

>>> Removing node 353618ef3beb7be9347827980060bcae1a8cfa95 from cluster 192.168.179.114:6381
>>> Sending CLUSTER FORGET messages to the cluster...
>>> SHUTDOWN the node.

注:若要删除master节点必须将数据转移清空,否则会报错。

增加节点:

增加一个从节点:

[root@redis ~]# redis-cli -h 192.168.179.110 -p 6380 cluster nodes 
3ba28c8dd7257afeb50700631794d8b5fde6ac65 192.168.179.110:6380 myself,master - 0 0 1 connected 0-5460
e2c20d82ee90d92dd1e140bad42a7e28e7fc3343 192.168.179.110:6381 master - 0 1538745253710 8 connected 5461-10922
6aa57e5c085cb09403d5ace197a1a5dc9560eb6b 192.168.179.113:6380 slave e2c20d82ee90d92dd1e140bad42a7e28e7fc3343 0 1538745252702 8 connected
5004c4780535c1d5ea6ab14f2ac3ad9d2da42ede 192.168.179.114:6380 master - 0 1538745253710 5 connected 10923-16383
321729d10c9e2abe03f6e131a2b82459bec09078 192.168.179.113:6381 slave 3ba28c8dd7257afeb50700631794d8b5fde6ac65 0 1538745253710 4 connected

给192.168.179.114:6380 master节点添加一个从节点:

redis-trib.rb  add-node  --slave  --master-id  arg  slave_ip:slave_port  master_ip:master_port

redis-trib.rb add-node --slave --master-id 5004c4780535c1d5ea6ab14f2ac3ad9d2da42ede 192.168.179.114:6381 192.168.179.114:6380

注:要先将新添加的slave节点中的数据文件删除掉,运行起来,再进行添加操作。

添加一个主节点:

添加一个节点并加入集群:

redis-trib.rb add-node new_ip:new_port  cluster_ip:cluster_port

[root@redis ~]# cp redis/6380/ redis/6382 -a
[root@redis ~]# rm -rf redis/6382/db/*
[root@redis ~]# rm -rf redis/6382/log/*
[root@redis ~]# sed -i "s/6380/6382/" redis/6382/conf/redis.conf 
[root@redis ~]# redis-server redis/6382/conf/redis.conf 
[root@redis ~]# redis-trib.rb add-node 192.168.179.110:6382 192.168.179.110:6380

分配槽位:

[root@redis ~]# redis-trib.rb reshard 192.168.179.110:6382
...
How many slots do you want to move (from 1 to 16384)? 1024
What is the receiving node ID?3b0f152b25621d47872879a4a708542f6845f511
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

输入分配的槽位多少,以及分配给的master id,all表示随机分配,凑够1024个槽位。然后yes完成分配。

可见0-340,5461-5802,10923-11263,这几个槽位分配给了新的master,刚好1024个槽位。

指定从节点:

可以新添加从节点(上面的添加方法),也可以将已有的从节点给新的master。

登录到从节点主机

[root@redis ~]# redis-cli -c -h 192.168.179.114 -p 6381
192.168.179.114:6381> cluster replicate 3b0f152b25621d47872879a4a708542f6845f511
OK

可见已经添加成功。

到此,redis的集群搭建、分区原理、集群增加节点以及删除节点的主要内容已经简要介绍完毕。

参考博客:https://blog.csdn.net/dc_726/article/details/48552531

猜你喜欢

转载自blog.csdn.net/rightlzc/article/details/82863027