一、Redis Cluster(Redis集群)简介
1、redis是一个开源的key value存储系统,受到了广大互联网公司的青睐。redis3.0版本之前只支持单例模式,在3.0版本及以后才支持集群,我这里用的是redis3.0.0版本;
2、所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。redis集群采用P2P模式,是完全去中心化的,不存在中心节点或者代理节点;
3、redis集群是没有统一的入口的,客户端(client)连接集群的时候连接集群中的任意节点(node)即可,集群内部的节点是相互通信的(PING-PONG机制),每个节点都是一个redis实例;
4、为了实现集群的高可用,即判断节点是否健康(能否正常使用),redis-cluster有这么一个投票容错机制:如果集群中超过半数的节点投票认为某个节点挂了,那么这个节点就挂了(fail)。这是判断节点是否挂了的方法;
5、那么如何判断集群是否挂了呢? -> 如果集群中任意一个节点挂了,而且该节点没有从节点(备份节点),那么这个集群就挂了。这是判断集群是否挂了的方法;
那么为什么任意一个节点挂了(没有从节点)这个集群就挂了呢? -> 因为集群内置了16384个slot(哈希槽),并且把所有的物理节点映射到了这16384[0-16383]个slot上,或者说把这些slot均等的分配给了各个节点。当需要在Redis集群存放一个数据(key-value)时,redis会先对这个key进行crc16算法,然后得到一个结果。再把这个结果对16384进行求余,这个余数会对应[0-16383]其中一个槽,进而决定key-value存储到哪个节点中。所以一旦某个节点挂了,该节点对应的slot就无法使用,那么就会导致集群无法正常工作。
如果集群超过半数以上master挂掉,无论是否有slave,集群进入fail状态.
综上所述,每个Redis集群理论上最多可以有16384个节点。
关于redis的集群化方案 目前有三种:
(1)Twitter开发的twemproxy
简介:twemproxy架构简单就是用proxy对后端redis server进行代理 但是由于代理层的消耗性能很低 而且通常涉及多个key的操作都是不支持的 而且本身不支持动态扩容和透明的数据迁移 而且也失去维护 Twitter内部已经不使用了
(2)豌豆荚开发的codis
codis使用的也是proxy思路,但是做的比较好,是这两种之间的一个中间级,而且支持redis命令是最多的,有图形化GUI管理和监控工具。
(3)redis官方的redis-cluster
redis-cluster是三个里性能最强大的。因为他使用去中心化的思想,使用hash slot方式,将16348个hash slot 覆盖到所有节点上,对于存储的每个key值 使用CRC16(KEY)&16348=slot 得到他对应的hash slot 并在访问key时就去找他的hash slot在哪一个节点上 然后由当前访问节点从实际被分配了这个hash slot的节点去取数据 节点之间使用轻量协议通信,减少带宽占用,性能很高,自动实现负载均衡与高可用,自动实现failover。并且支持动态扩展,官方已经玩到可以1000个节点 实现的复杂度低,是全新的思路。
但是它也有一些不足。例如官方没有提供图形化管理工具,运维体验差,全手工数据迁移 ,且自己对自己本身的redis命令支持也不完全等
二、集群搭建需要的环境
Redis集群至少需要3个节点,因为投票容错机制要求超过半数节点认为某个节点挂了该节点才是挂了,所以2个节点无法构成集群。
要保证集群的高可用,需要每个节点都有从节点,也就是备份节点,所以Redis集群至少需要6台服务器。
1、安装ruby
创建集群集群脚本是ruby写的
yum -y install ruby
yum -y install rubygems
gem install redis #安装Redis和ruby的接口
[root@localhost redis]# gem install redis
ERROR: Error installing redis:
redis requires Ruby version >= 2.2.2.
yum库中ruby的版本支持到 2.0.0,可gem 安装redis需要最低是2.2.2。解决办法是采用rvm来更新ruby
安装yum install curl
按照rvm.io提示执行gpg2 –recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
curl: (35) SSL connectgpg2 –recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
gpg: requesting key D39DC0E3 from hkp server keys.gnupg.net
gpg: requesting key 39499BDB from hkp server keys.gnupg.net
gpg: key D39DC0E3: “Michal Papis (RVM signing) mpapis@gmail.com“ not changed
gpg: key D39DC0E3: “Totally Legit Signing Key mallory@example.org“ not changed
gpg: key 39499BDB: “Piotr Kuczynski piotr.kuczynski@gmail.com“ not changed
gpg: Total number processed: 3
gpg: unchanged: 3
不通过,下一步的\curl -sSL https://get.rvm.io | bash -s stable
或curl -L get.rvm.io | bash -s stable
也就不行。
寻找了很多招办法都不行,只能通过手动下载ruby高版本手动安装,或者通过另外一个工具rbenv安装
手动下载高版本rub安装
解压
[root@localhost tmp]# tar -zxvf ruby-2.6.1.tar.gz -C ../ruby-2.6
[root@localhost tmp]# ./configure --prefix=/usr/local/ruby -prefix是将ruby安装到指定目录,也可以自定义
[root@localhost tmp]# make && make install
安装完成
[root@localhost ruby]# bin/ruby -v
ruby 2.6.1p33 (2019-01-30 revision 66950) [x86_64-linux]
把ruby加入环境变量
[root@localhost ruby]# vim /etc/profile
[root@localhost ruby]# source /etc/profile
[root@localhost ruby]# echo $PATH
/usr/local/ruby/bin:/usr/local/jdk8/bin:/usr/local/jdk8/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
其中设置PATH路径,把安装的ruby放在系统PATH前面,避免调用操作系统自带的ruby
这回执行gem install redis #安装Redis和ruby的接口
成功
2、配置集群
由于没有这么多Linux,就在同一台上模拟配置6个Redis实例作为六个节点。
在/usr/local/下新建redis_cluster文件,里边新建六个目录node6001~node6006当做六个节点
拷贝创建集群的脚本文件redis-trib.rb到redis_cluster
在分别拷贝配置文件Redis.conf到这些目录下,并且依次修改为自己对应的节点信息。
依次修改信息如下:
port 6001
bind 192.168.18.140 #默认ip为127.0.0.1 需要改为其他节点机器可访问的ip 否则创建集群时无法访问对应的端口,无法创建集群
daemonize yes #redis后台运行
pidfile /var/run/redis_6001.pid #PID
cluster-enabled yes #开启集群 把注释#去掉
cluster-config-file nodes-6001.conf #集群的配置 配置文件首次启动自动生成6001/6002...
cluster-node-timeout 15000 #请求超时 默认15秒,可自行设置
appendonly yes #aof日志开启 有需要就开启,它会每次写操作都记录一条日志
dir /usr/local/redis-cluster/node6001/ #默认是./,分别修改为当前节点下
启动并检查六个节点是否启动
编写脚本\start-all.sh
#start 6 redis
/usr/local/redis/bin/redis-server /usr/local/redis-cluster/node6001/redis.conf
/usr/local/redis/bin/redis-server /usr/local/redis-cluster/node6002/redis.conf
/usr/local/redis/bin/redis-server /usr/local/redis-cluster/node6003/redis.conf
/usr/local/redis/bin/redis-server /usr/local/redis-cluster/node6004/redis.conf
/usr/local/redis/bin/redis-server /usr/local/redis-cluster/node6005/redis.conf
/usr/local/redis/bin/redis-server /usr/local/redis-cluster/node6006/redis.conf
stop-all.sh
#stop 6 redis
/usr/local/redis/bin/redis-cli -h 192.168.18.140 -p 6001 shutdown
/usr/local/redis/bin/redis-cli -h 192.168.18.140 -p 6002 shutdown
/usr/local/redis/bin/redis-cli -h 192.168.18.140 -p 6003 shutdown
/usr/local/redis/bin/redis-cli -h 192.168.18.140 -p 6004 shutdown
/usr/local/redis/bin/redis-cli -h 192.168.18.140 -p 6005 shutdown
/usr/local/redis/bin/redis-cli -h 192.168.18.140 -p 6006 shutdown
赋权:chmod 777 start-all.sh stop-all.sh
执行启动脚本,并检查:
1 |
|
一切没问题。
查看集群包括各个节点文件得到如下,文件结构没有问题:
../redis-cluster/
├── node6001
│ ├── appendonly.aof
│ ├── dump.rdb
│ ├── nodes-6001.conf
│ └── redis.conf
├── node6002
│ ├── appendonly.aof
│ ├── dump.rdb
│ ├── nodes-6002.conf
│ └── redis.conf
├── node6003
│ ├── appendonly.aof
│ ├── dump.rdb
│ ├── nodes-6003.conf
│ └── redis.conf
├── node6004
│ ├── appendonly.aof
│ ├── dump.rdb
│ ├── nodes-6004.conf
│ └── redis.conf
├── node6005
│ ├── appendonly.aof
│ ├── dump.rdb
│ ├── nodes-6005.conf
│ └── redis.conf
├── node6006
│ ├── appendonly.aof
│ ├── dump.rdb
│ ├── nodes-6006.conf
│ └── redis.conf
├── redis-trib.rb
├── start-all.sh
└── stop-all.sh
检查都没有问题,继续下一步。
nodes-*.conf这个文件代表集群文件
3、创建集群
执行创建脚本
1 | [root@localhost redis-cluster]# ./redis-trib.rb create --replicas 1 192.168.18.140:6001 192.168.18.140:6002 192.168.18.140:6003 192.168.18.140:6004 192.168.18.140:6005 192.168.18.140:6006 |
以上信息说明了集群配置OK,master和salve都分配好,是否确认创建集群。yes
1 | Can I set the above configuration? (type 'yes' to accept): yes |
集群创建成功!
验证、登录
1 | redis-cli -c -h 192.168.37.131 -p 7001 ,其中-c表示以集群方式连接redis,-h指定ip地址,-p指定端口号 |
4、新添加主节点
准备好Redis节点192.168.18.140:6007并启动起来,执行添加节点命令如下:
./redis-trib.rb add-node 192.168.18.140:6007 192.168.18.140:6001
添加后的节点设置主节点或从节点
hash槽重新分配
添加完主节点需要对主节点进行hash槽分配这样该主节才可以存数据,就成为主节点。
redis集群有16384个槽,集群中的每个master结点分配一些槽,通过查看集群结点可以看到槽占用情况。
./redis-trib.rb reshard 192.168.18.140:6001
提示移动多少槽,输入值1000。
之后提示移动到那个节点,输入节点ID
之后提示我们指定转移哪几个几点的哈希槽,输入all 表示从所有的主节点中随机转移,凑够1000个哈希槽
然后再输入yes,redis集群就开始分配哈希槽了。
分配完成后这个节点也就成为主节点。
如果是把这个节点变成从节点,比如让新节点成为6001的从节点:
redis-cli -c -p 6007 cluster replicate 0b00721a509444db793d28448d8
命令后面的ID就是6001的ID
使用下面命令来确认一下6007是否已经成为6001的从节点
redis-cli -p 6001 cluster nodes | grep slave | grep 6001ID
5、删除节点
如果删除主节点:该节点有100个哈希槽,首先把节点的哈希槽转移到其他主节点,命令:
./redis-trib.rb reshard 192.168.18.140:6001
系统会提示我们要移动多少哈希槽,这里移动1000个,因为新节点有1000个哈希槽
然后系统提示我们输入要接收这些哈希槽的节点的ID
然后要我们选择从那些节点中转出哈希槽,这里一定要输入6007这个节点的ID,最后输入 done 表示输入完毕
最后使用命令删除节点
./redis-trib.rb del-node 192.168.18.140:6001 需要删除的节点ID
如果节点是从节点,直接使用删除命令即可。
redis-trib.rb具有以下功能:
create:创建集群 --replicas可以指定从节点个数
check:检查集群
info:查看集群信息
fix:修复集群
reshard:在线迁移slot
rebalance:平衡集群节点slot数量
add-node:将新节点加入集群
del-node:从集群中删除节点
set-timeout:设置集群节点间心跳连接的超时时间
call:在集群全部节点上执行命令
import:将外部redis数据导入集群
以集群方式登录任意节点,即可以使用这些命令
测试
1 |
|