学习目标:
1、了解Redis的Cluster的原理
2、掌握Redis的Cluster的搭建
学习过程:
Redis Cluster是Redis的集群实现,内置数据自动分片机制,集群内部将所有的key映射到16384个Slot中,集群中的每个Redis Instance负责其中的一部分的Slot的读写。集群客户端连接集群中任一Redis Instance即可发送命令,当Redis Instance收到自己不负责的Slot的请求时,会将负责请求Key所在Slot的Redis Instance地址返回给客户端,客户端收到后自动将原请求重新发往这个地址,对外部透明。一个Key到底属于哪个Slot由crc16(key) % 16384 决定
Redis 集群提供了以下两个好处:
将数据自动切分(split)到多个节点的能力。
当集群中的一部分节点失效或者无法进行通讯时, 仍然可以继续处理命令请求的能力。
Redis 集群使用数据分片(sharding)而非一致性哈希(consistency hashing)来实现: 一个 Redis 集群包含 16384 个哈希槽(hash slot), 数据库中的每个键都属于这 16384 个哈希槽的其中一个, 集群使用公式 CRC16(key) % 16384 来计算键 key 属于哪个槽, 其中 CRC16(key) 语句用于计算键 key 的 CRC16 校验和 。
集群中的每个节点负责处理一部分哈希槽。 举个例子, 一个集群可以有三个哈希槽, 其中:
节点 A 负责处理 0 号至 5500 号哈希槽。
节点 B 负责处理 5501 号至 11000 号哈希槽。
节点 C 负责处理 11001 号至 16384 号哈希槽。
这种将哈希槽分布到不同节点的做法使得用户可以很容易地向集群中添加或者删除节点。 比如说:
如果用户将新节点 D 添加到集群中, 那么集群只需要将节点 A 、B 、 C 中的某些槽移动到节点 D 就可以了。与此类似, 如果用户要从集群中移除节点 A , 那么集群只需要将节点 A 中的所有哈希槽移动到节点 B 和节点 C , 然后再移除空白(不包含任何哈希槽)的节点 A 就可以了。
因为将一个哈希槽从一个节点移动到另一个节点不会造成节点阻塞, 所以无论是添加新节点还是移除已存在节点, 又或者改变某个节点包含的哈希槽数量, 都不会造成集群下线。
Redis 集群中的高可用性。为了使得集群在一部分节点下线或者无法与集群的大多数(majority)节点进行通讯的情况下, 仍然可以正常运作, Redis 集群对节点使用了主从复制功能: 集群中的每个节点都有 1 个至 N 个复制品(replica), 其中一个复制品为主节点(master), 而其余的 N-1 个复制品为从节点(slave)。
在之前列举的节点 A 、B 、C 的例子中, 如果节点 B 下线了, 那么集群将无法正常运行, 因为集群找不到节点来处理 5501 号至 11000 号的哈希槽。
另一方面, 假如在创建集群的时候(或者至少在节点 B 下线之前), 我们为主节点 B 添加了从节点 B1 , 那么当主节点 B 下线的时候, 集群就会将 B1 设置为新的主节点, 并让它代替下线的主节点 B , 继续处理 5501 号至 11000 号的哈希槽, 这样集群就不会因为主节点 B 的下线而无法正常运作了。不过如果节点 B 和 B1 都下线的话, Redis 集群还是会停止运作。
二、安装
1、修改配置文件,启动多个redis实例
安装之前先做好规划,为了更好的体现reids集群的特点,决定启动六个redis实例,但是我这里只有三台服务器,所以这里我就再每一台服务器都启动两个实例,只需要修改不同的端口就可以了。规划如下:
192.168.137.101 启动两台redis实例,端口分别时:6379 、 7379。
192.168.137.102 启动两台redis实例,端口分别时:6379 、 7379。
192.168.137.103 启动两台redis实例,端口分别时:6379 、 7379。
1、先清空了原来的所有redis数据。
因为之前我们使用过redis做过很多实验,这里需要先flushdb全部清空了。
1、复制redis.conf,修改端口和日志信息,其他保留不变,再启动一台redis实例,具体操作如下:
[root@localhost etc]# cp redis.conf redis7379.conf
[root@localhost etc]# vim redis7379.conf
修改
port 7379
logfile "/usr/local/redis/logs/redis7379.logs"
保存退出,尝试是否可以启动多一个实例,命令如下:
[root@localhost etc]# redis-server /etc/redis7379.conf
[root@localhost etc]# ps -ef | grep 'redis'
root 3810 1 0 15:54 ? 00:00:03 /usr/local/redis/bin/redis-server *:6379
root 3880 1 52 16:01 ? 00:00:03 redis-server *:7379
root 3885 3739 0 16:02 pts/0 00:00:00 grep --color=auto redis
[root@localhost etc]# redis-cli -p 7379
127.0.0.1:7369> auth 123456
OK
参考前面的redis的安装, 也可以设置为开机启动和相关的启动命令,这里就不在啰嗦了,当然现在也仅仅只是完成了基本的配置。下面我们真正开始搭建redis cluster了。
redis.conf和redis7379.conf文件修改如下:
#requirepass 123456 密码先都注释了
port 6379 # 修改不通端口
appendfilename "appendonly7379.aof" # 根据不通端口修改
dbfilename dump7379.rdb # 根据不通端口修改
cluster-config-file nodes-6379.conf # 根据端口进行修改
logfile "/usr/local/redis/logs/redis7379.logs" # 根据端口进行修改
cluster-enabled yes
cluster-node-timeout 15000
其意思说明如下:
1、cluster-enabled
2、cluster-config-file
3、cluster-node-timeout
然后把这两个配置文件复制到另外两台192.168.137.102和192.168.137.103服务器中。
[root@localhost etc]# scp redis*.conf [email protected]:/etc
[root@localhost etc]# scp redis*.conf [email protected]:/etc
还有启动命令,参考签名的reids的安装,也设置为开机启动就可以了。
[root@localhost init.d]# scp redis* [email protected]:/etc/init.d/
[root@localhost init.d]# scp redis* [email protected]:/etc/init.d/
分别在三台服务器中启动就可以了
root@run1 bin]# ./redis-server /etc/redis.conf
[root@run1 bin]# ./redis-server /etc/redis7379.conf
查看是否启动成功
[root@localhost ~]# ps -ef | grep redis
root 3289 1 0 16:25 ? 00:00:00 /usr/local/redis/bin/redis-server *:7379 [cluster]
root 3290 1 0 16:25 ? 00:00:00 /usr/local/redis/bin/redis-server *:6379 [cluster]
可以看到已经做好了集群的准备了,但是还没有创建集群
2、创建集群
redis的集群安装需要依赖ruby,所以先安装 ruby和rubygems,最新版本可以不安装rubygems
[root@localhost ~]# yum install ruby rubygems -y
我们安装完 Ruby 和 Rubygems 后,还需要继续安装Redis的Ruby接口程序。
[root@localhost ~]# gem install redis
Fetching: redis-4.1.0.gem (100%)
ERROR: Error installing redis:
redis requires Ruby version >= 2.2.2.
但是报错了,原因就是CentOS7 yum库中ruby的版本是 2.0.0,可gem 安装redis需要最低是2.2.2,所以需要更新ruby,更新ruby需要先安装rvm,采用rvm来更新ruby,参考rvm官网:http://rvm.io,先安装rvm
[root@localhost ~]#gpg2 --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
[root@localhost ~]#curl -sSL https://get.rvm.io | bash -s stable
[root@localhost ~]#find / -name rvm -print
[root@localhost ~]#source /usr/local/rvm/scripts/rvm
[root@localhost ~]#rvm list known #可以看到对应的版本,这里我们安装2.3.8
[root@localhost ~]#rvm install 2.3.8 #安装对应的ruby版本
[root@localhost ~]#rvm use 2.3.8 --default 使用该ruby版本,并设置为默认值,这样就替换了原来的2.0.0版本了。
[root@localhost ~]#ruby --version 查看ruby版本。
重新执行就可以成功了。
[root@localhost ~]# gem install redis
执行建立集群命令,redis-trib.rb命令再源代码中有。
[root@localhost ~]# cd redis-4.0.13/src/
[root@localhost src]# ruby redis-trib.rb create --replicas 1 192.168.137.101:6379 192.168.137.101:7379 192.168.137.102:6379 192.168.137.102:7379 192.168.137.103:6379 192.168.137.103:7379
>>> Creating cluster
先会输出一系列的规划信息,主节点和从节点信息等。要求你确认,输入yes就可以了。
Using 3 masters:
192.168.137.101:6379
192.168.137.102:6379
192.168.137.103:6379
Adding replica 192.168.137.102:7379 to 192.168.137.101:6379
Adding replica 192.168.137.103:7379 to 192.168.137.102:6379
Adding replica 192.168.137.101:7379 to 192.168.137.103:6379
稍等一会,输出的内容比较多,主要就是主从配置,分槽信息等。会问你是否安装这种方式建立集群,输入yes然后就可以建立集群了。
M: 33f7db815b9d7219e4a46c078ed2b7f0441c78ff 192.168.137.101:6379
slots:0-5460 (5461 slots) master
1 additional replica(s)
M: 3536daf72fa8d037140c35e90f7ac0375421c476 192.168.137.102:6379
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: 09d1f418c8cebad84ae8034a56f8e4f2d5f9e400 192.168.137.102:7379
slots: (0 slots) slave
replicates 33f7db815b9d7219e4a46c078ed2b7f0441c78ff
S: 2de36d7b52cf5a3c373a83fcaf8587a31da1e4e9 192.168.137.101:7379
slots: (0 slots) slave
replicates b3e0c8dbfe867a66925df6ca59f8956b262428ec
M: b3e0c8dbfe867a66925df6ca59f8956b262428ec 192.168.137.103:6379
slots:10923-16383 (5461 slots) master
1 additional replica(s)
S: a4959f3478ff7101c635f59d35010e94ebba259e 192.168.137.103:7379
slots: (0 slots) slave
replicates 3536daf72fa8d037140c35e90f7ac0375421c476
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
看到最后一句,16384个槽已经全部建立好了。再看一下上面的每隔槽分配,看master的就可以了:
192.168.137.101:6379 是 slots:0-5460 (5461 slots)
192.168.137.102:6379 是 slots:5461-10922 (5462 slots)
192.168.137.103:6379 是 slots:10923-16383 (5461 slots)
好这样就可以成功了。
3、可能遇到的错误:
先说明一下,如果上面的安装过程有问题,需要全部清空安装记录,需要删除原来所有的集群信息,主要就是下面把文件中的*.aof、*.rdb、nodes*.conf全部删除。
[root@localhost src]# cd /usr/local/redis
[root@localhost redis]# ls
appendonly7379.aof appendonly.aof bin dump7379.rdb dump.rdb logs module nodes-6379.conf nodes-7379.conf
错误1:in `call': ERR Slot 8579 is already busy (Redis::CommandError)
错误提示是
slot插槽被占用了(这是 搭建集群前时,以前redis的旧数据和配置信息没有清理干净。)
解决方案是
用redis-cli 登录到每个节点执行 flushall 和 cluster reset 就可以了。
报错:
[root@run1 bin]# ./redis-cli -p 7000
127.0.0.1:7000> flushdb
127.0.0.1:7000> cluster reset
错误2:创建集群时一直处于"Waiting for the cluster to join...................................."的状态,原因可能有两个
1、解决方法是在redis.conf文件中把bind 127.0.0.1本地环回口改为物理接口比如我修改成为bind 192.168.8.234 等。不要写 127.0.0.1了。
2、端口没有通,redis集群不仅需要开通redis客户端连接的端口,而且需要开通集群总线端口,规则是:集群总线端口为redis客户端连接的端口 + 10000,如redis端口为6379,则集群总线端口为16379,所以还需要开通对应的端口
[root@localhost src]# firewall-cmd --zone=public --add-port=16379/tcp --permanent
[root@localhost src]# firewall-cmd --zone=public --add-port=17379/tcp --permanent
[root@localhost src]# firewall-cmd --reload
出现这个问题的原因很多
1、集群构建前不要使用密码,一会再给集群设置密码,否则会显示不能连接的错误。
2、防火墙是否有开这个端口。
[root@localhost src]# ruby redis-trib.rb create --replicas 1 192.168.137.101:6379 192.168.137.101:7379 192.168.137.102:6379 192.168.137.102:7379 192.168.137.103:6379 192.168.137.103:7379
>>> Creating cluster
[ERR] Sorry, can't connect to node 192.168.137.101:6379