Redis集群

Redis3.0 开始支持集群 Clusterredis cluster集群,要求至少3个master,去组成一个高可用,健壮的分布式的集群,每个master都建议至少给一个slave,3个master,3个slave
正式环境下,建议都是说在6台机器上去搭建,这样可以保证master死了,它的slave可以掌管大权。

  1. 所有 redis 节点内部使用二进制协议传送数据,通过 ping-pong 机制,判断节点是否存活
  2. 每个节点的宕机是通过集群中超过半数的节点检查失效时才生效
  3. 可客户端与 redis 节点直接连接,不需要通过代理层,客户端连接集群中任意一个可用节点即可
  4. Redis-cluster 把所有的物理节点映射到[ 0-16383 ]slot 插槽上,cluster 负责维护 node <-> slot <-> value

修改配置文件

准备3台虚拟机,我们需要3个master和3个slave,将redis.conf配置文件分别改成7001.conf,7002.conf,7003.conf,7004.conf,7005.conf,7006.conf,端口分别是7001、7002、7003、7004、7005、7006
3台虚拟机:

192.168.1.10 对应 7001.conf,7002.conf
192.168.1.11 对应 7003.conf,7004.conf
192.168.1.12 对应 7005.conf,7006.conf

创建文件夹:

mkdir -p /etc/redis-cluster
mkdir -p /var/log/redis
mkdir -p /var/redis/7001

修改配置文件的内容:一定不要设置密码

port 7001
cluster-enabled yes
# 每个conf配置与自己的端口一致
cluster-config-file /etc/redis-cluster/node-7001.conf
cluster-node-timeout 15000
daemonize	yes							
pidfile		/var/run/redis_7001.pid 						
dir 		/var/redis/7001		
logfile /var/log/redis/7001.log
bind 192.168.1.10	
appendonly yes

创建集群关系

    创建集群关系需要用 redis-trib.rb,而这个东西是 ruby 语言编写的,因此需要安装 ruby 环境。

yum -y install zlib ruby rubygems
gem install redis

    如果执行 gem install redis 出现 redis requires Ruby version >= 2.2.2 的错误,那是因为Centos 默认支持 ruby2.0.0,可gem 安装 redis 需要最低是2.2.2。
解决方法:

curl -sSL https://rvm.io/mpapis.asc | gpg2 --import -
curl -sSL https://get.rvm.io | bash -s stable
rvm list known
source /etc/profile.d/rvm.sh
rvm install 2.3.3
rvm use 2.3.3
rvm remove 2.0.0
ruby --version
gem install redis

    创建集群前,需要将所有的服务启动,然后进入 redissrc 目录下,执行:

# 例如下面这个,配置了六个redis,replicas的值为1,那么在创建集群时,会自动的将这6个redis分组,一个master对应一个slave
# 注意:master和slave的对应关系是随机的
./redis-trib.rb create --replicas 1 192.168.1.10:7001 192.168.1.10:7002 192.168.1.11:7003 192.168.1.11:7004 192.168.1.12:7005 192.168.1.12:7006
# 验证集群是否可用
./redis-trib.rb check 192.168.1.12:7006

注意:命令中的 ip 不要使用 127.0.01,否则 jedis 客户端无法连接;配置文件中一定不要配置密码。

Redis集群_第1张图片
Redis集群_第2张图片
Redis集群_第3张图片

设置密码(本博客没有配置密码)

    我们没有在配置文件中指定密码是因为创建集群的 redis-trib.rb 命令没有密码的参数,如果配置了密码,会出现:
这里写图片描述

    在客户端中配置认证密码:

redis-cli -c -p 6379
config set masterauth 111111
config set requirepass 111111
config rewrite 
exit
redis-cli -c -p 6379 -a 111111
ping

    每个客户端都需要配置密码,并且各个节点密码都必须一致,否则在插入数据时,Redirected 就会失败, 推荐这种方式,这种方式会把密码写入到 redis.conf 里面去,且不用重启。

测试(没有配置密码)

我们搭建的集群,7003和7002是一对master和slave,如果7003挂掉的话,7002会自动变成master,7003重启后会变成slave挂在7002名下,这个实验不做了。

# 必须要加上 -c 这个选项,否则redis在计算hash值后会出现问题
redis-cli -c -h 192.168.1.10 -p 7001
  • 不加 -c出现的问题

    不加 -c 选项会出现如下问题,可以看到提示我们要在192.168.1.11的7003端口的客户端上执行,这是因为集群搭建时,master和slave是随机配对的,而我们又知道读写分离,slave只能读。
    Redis集群_第4张图片
    搭建集群时的截图中,redis自动配对master和slave,我的7003端口是master,它对应的slave是7002,在7003上info replication查看主从信息
    Redis集群_第5张图片
    我们在7003的客户端上写入数据,然后可以获取数据,但是在其他的客户端上都会出现问题,并且它的slave上也会出现这个问题,但是在它的slave的客户端使用readonly之后就可以获取数据,其他客户端使用这个命令无效
    Redis集群_第6张图片
    这里写图片描述
    Redis集群_第7张图片

  • 加上 -c选项不会出现上述问题

key 与插槽 slot 的关系

    数据要存在哪个节点上是根据 key 的有效部分计算的哈希值,再将哈希值对 16384 (0~16383)取余,得到插槽值。
key 的有效部分:
    1)如果 key 中包含一对花括号,并且花括号之间至少有一个字符,那么这个花括号中的值就是 key 的有效部分,例如:key 的值是 {hello}_world,有效部分是 hello ,它的插槽值与单独一个 hello 得插槽值是一样的。
    2)如果不满足条件1,那么整个 key 都是有效部分

新增节点

  新增节点:

./redis-trib.rb add-node 192.168.2.100:6382 192.168.168.2.100:6379 add-node

命令中的第一个 ip:port 是新增的节点的 ip 和 port,第二个 ip:port 是集群中已经存在的任意一个节点的 ip 和 port

  分配插槽:

./redis-trib.rb reshard 192.168.2.100:6382

    此命令运行过程中,需要执行一些操作:
    1、 要从其他节点抽取多少个插槽给新增的节点
    2、 新增的节点的id
    3、 all:要从其他所有节点中抽取插槽
    4、 要抽取插槽的其他节点的id+回车,换行后可以再选择另外的节点的id+回车(此处省略你想抽取的另外的一些节点的id+回车),输入done表示开始抽取
    5、 3和4任选其一
    6、 3和4步后输入yes表示完成
Redis集群_第8张图片

删除节点

  转移要删除的节点的插槽,以删除6380节点为例:

./redis-trib reshard 192.168.2.100:6380

    1)输入转移插槽的数量
    2)输入转移的节点的 id
    3)输入 done 开始转移
Redis集群_第9张图片
Redis集群_第10张图片

  删除节点:

./redis-trib.rb del-node 192.168.56.102:6380 4a9b8886ba5261e82597f5590fcdb49ea47c4c6c

Redis集群_第11张图片

故障转移

  故障机制:
    1)集群中的每个节点会定期 ping 其他节点,通过有没有 pong 判断目标节点是否下线
    2)集群中每一秒就会随机选择 5 个节点,选择其中最久没有响应的节点 进行 ping
    3)当集群中节点超过半数人为目标节点疑似下线,那么节点被标记为下线
    4)当集群中任何一个节点下线,导致插槽有空档、不完整,那么集群将不可用
  解决方案:
    1)使用主从模式实现各个节点的高可用
    2)当某个节点(master)宕机后,集群会将该节点的 slave 变为 master 继续完成集群服务

集群中需要注意的问题

    1)集群中如果用 mset 和 mget 等多键命令时,如果每个 key 都位于一个节点,则可以正常支持,否则会提示错误
    2)集群中的节点只能使用 0 号库,如果执行 select 切换数据库会提示错误

./redis-trib.rb 命令用法

Usage: redis-trib   

  create          host1:port1 ... hostN:portN
                  --replicas 
  check           host:port
  info            host:port
  fix             host:port
                  --timeout 
  reshard         host:port
                  --from 
                  --to 
                  --slots 
                  --yes
                  --timeout 
                  --pipeline 
  rebalance       host:port
                  --weight 
                  --auto-weights
                  --use-empty-masters
                  --timeout 
                  --simulate
                  --pipeline 
                  --threshold 
  add-node        new_host:new_port existing_host:existing_port
                  --slave
                  --master-id 
  del-node        host:port node_id
  set-timeout     host:port milliseconds
  call            host:port command arg arg .. arg
  import          host:port
                  --from 
                  --copy
                  --replace
  help            (show this help)

你可能感兴趣的:(redis)