简介:
java
redis-cluster是redis自带的分布式集群模式,其原理是将几套redis实例的存储空间划分红总共16384个hash数据槽,而后经过crc16算法计算key的名字得出一个hash值,把数据存储到相应的数据槽上.若是数据分布足够平均,就能够充分利用每一套redis实例来分散负载,从而达到高性能的目的,相反则会出现热点区间,出现木桶短板原则限制.node
优势:搭建简单,自带高可用,性能提升明显,相比其余集群模式延时影响较低,支持redis原始命令.redis
缺点:扩容/缩容不方便,客户端链接模式须要修改,容易出现热点区间问题,至少须要3组redis实例搭建.算法
搭建:vim
首先,要搭建3组redis主从实例,由于这是redis-cluster要求的最少配置,搭建redis主备的方法就不说了,这个能够看我以前的文章,这里只强调须要额外配置的特殊配置.安全
#bind的IP必须是0.0.0.0,不能是*,否则会连不上 bind 0.0.0.0 #端口要尽可能注意区分,避免冲突 port 7001 #cluster启动开关,这里要启用,固然是yes cluster-enabled yes #节点配置文件,有别于redis-server启动文件redis.conf,须要额外存在别的地方 cluster-config-file /data/redis/data/config/rc4_7001/nodes_7001.conf #集群节点超时检测时间,若是超过这个时间没有回应,就认为对方挂了,视网络状态设定 cluster-node-timeout 15000 #不能设定密码,requirepass和masterauth都必须为空
注意:不能设置密码的缘由是由于搭建集群的redis-trib.rb脚本中链接Redis的代码里面,并未设定密码的参数,若是设定了密码,在搭建的时候会报错:[ERR] Sorry, can’t connect to node *.*.*.*:7001
ruby
因此须要密码的话就要后期搭建完毕后才能修改密码.固然,也能够修改redis-trib.rb代码来解决,不过这个不是这里重点,先忽略一下,暂时只按默认方式来搭建,修改redis-trib.rb的代码则在下面再讲解.bash
注意2:安装redis-cluster是不须要额外安装sentinel哨兵的,高可用管理方式由集群内部管理.
服务器
而后,搭建完3组redis以后,就要安装一个ruby组件,这个组件是负责把集群内部的机器互相联通,并划分16384数据槽位到对应的节点,网络
#先安装依赖环境 yum install -y ruby zlib-devel zlib #下载redis-cluster安装组件,redis-3.3.5.gem版本能够支持到redis5.0 wget http://rubygems.org/downloads/redis-3.3.5.gem #安装组件 gem install redis-3.3.5.gem
再而后,这个时候咱们就能够安装redis-cluster了,
#在3.0/3.2/4.0安装包的src目录都自带一个redis-trib.rb脚本,就是用来安装redis-cluster的,上面说了这个脚本不能带密码 /opt/redis-4.0.14/src/redis-trib.rb create --replicas 1 172.25.100.11:7001 172.25.100.11:7002 172.25.100.15:7003 172.25.100.15:7004 172.25.100.17:7005 172.25.100.17:7006 #在5.0以后,安装redis-cluster不须要那个脚本了,系统自带redis-cli就有搭建集群的功能,并且还能带密码了 redis-cli --cluster create 172.25.100.11:7001 172.25.100.11:7002 172.25.100.15:7003 172.25.100.15:7004 172.25.100.17:7005 172.25.100.17:7006 --cluster-replicas 1 -a password01!
注意:配置replicas 1的意思是有多少个从库的意思,如今我搭建的redis实例只有一个从库,因此就是1,若是是有2个从库,那就是replicas 2,如此类推.
这个时候,若是是3.0/3.2/4.0的话,由于搭建的时候不能带密码,刚安装完就确定是没有密码的状态.因此就最好设个密码(纯内网能够不用),由于不少例子证实,没密码的redis很容易被***,让服务器变肉鸡.例如我搭建的这个环境,由于一开始6台所有都没密码,因此如今所有都要手动加密码.
#先无密码登陆 redis-cli -c -h 172.25.100.11 -p 7002 #设定主密码,这个时候还能操做 config set masterauth rc_test_20210112 #设定客户端密码,这个时候就不能操做了 config set requirepass rc_test_20210112 #既然已经没法操做了,须要用新密码重新登陆 redis-cli -c -h 172.25.100.11 -p 7002 -a rc_test_20210112 #把修改的配置写到配置文件 config rewrite
注意:链接redis-cluster必须加上-c参数,java客户端则须要使用特定的集群模式.
添加/删除,新/旧节点:
在3.0/3.2/4.0版本,操做还须要围绕redis-trib.rb脚本,在5.0以后,就能够直接用redis-cli操做,
首先,假定咱们如今新建了两个节点172.25.100.18:7007和172.25.100.18:7008,
#3.0/3.2/4.0版本添加为主节点,不能带密码啊 redis-trib.rb add-node 172.25.100.18:7007 172.25.100.11:7001 #5.0版本以后添加为主节点,能够带密码了 redis-cli --cluster add-node 172.25.100.18:7007 172.25.100.11:7001 -a password01!
注意:add-node命令以后的172.25.100.18:7007为须要新加的主节点,然后面的172.25.100.11:7001为现存集群的任意一个节点,
这个时候经过redis-cli命令登陆以后指令cluster nodes会发现能够看到新节点了.可是尚未分配数据槽给新节点,致使新节点并不会有数据操做进去,在这一刻仍是没有意义的,只是单纯加了进去而已.
172.25.100.17:7006> CLUSTER NODES 653f26b0d647d6954c3151b60a0db5201b3e9afc 172.25.100.15:7003@17003 master - 0 1611215106400 3 connected 5461-10922 e28a4244cc0e3ca74d973e57b1e5c4d93cd230b1 172.25.100.17:7005@17005 master - 0 1611215105397 5 connected 10923-16383 acb57a858ddf4979da12e125cdf94fb13e19674c 172.25.100.17:7006@17006 myself,slave 653f26b0d647d6954c3151b60a0db5201b3e9afc 0 1611215104000 6 connected 132184b75bafe681869619bfb6df2b335f9e96b5 172.25.100.15:7004@17004 slave 7e4a0f849c1c383b9123d6f24bd1950cdc8b3ba3 0 1611215103393 4 connected 7e4a0f849c1c383b9123d6f24bd1950cdc8b3ba3 172.25.100.11:7001@17001 master - 0 1611215104000 1 connected 0-5460 2114ddc7d1355160a1703fb6992e1722983d3e4f 172.25.100.11:7002@17002 slave e28a4244cc0e3ca74d973e57b1e5c4d93cd230b1 0 1611215105000 5 connected 349a51df26f4723f14faba2a7fe3cad587659e86 172.25.100.18:7007@17007 master - 0 1611215104000 1 connected
因此,咱们第二部就是须要把数据槽分配给新节点,
#3.0/3.2/4.0版本须要手动添加,先用脚本指定集群内部任意一个已分配数据槽的节点IP redis-trib.rb reshard 172.25.100.11:7001 #提示:你想迁移多少个数据槽,我这里演示是4000个槽,因此填4000,而后按回车 How many slots do you want to move (from 1 to 16384)?4000 #提示:你想把这4000个槽分配给谁呢?那固然是新加的172.25.100.18:7007,可是这里要填cluster nodes查出来的ID,而后按回车 What is the receiving node ID? 349a51df26f4723f14faba2a7fe3cad587659e86 #提示:你想从那个节点抽取这4000个槽,若是你填对应节点的ID则只从那个节点抽,若是你填all,就表明从全部的节点随机抽过来 Source node #1: all #在5.0以后的版本,除了上面的手动分配方式,还支持自动分配,毕竟手动可能会有分配不合理的问题,其实自动更好. redis-cli --cluster rebalance --cluster-threshold 1 --cluster-use-empty-masters 172.25.100.11:7001 -a password01! #还能用check命令看看分配状况 redis-cli --cluster check 172.25.100.11:7001 -a password01!
一顿操做以后,再cluster nodes看一下,你就会发现新节点分配了数据槽了,
349a51df26f4723f14faba2a7fe3cad587659e86 172.25.100.18:7007@17007 master - 0 1611215104000 1 connected 0-1000 6000-8000 10000-11000
这个时候,这个节点就会有数据操做,也就是真正添加完毕.
这个时候不由要问,这台机只是主库啊,尚未从库,因此还须要把172.25.100.18:7008加进去
#3.0/3.2/4.0版本,把一个redis实例添加到集群内部作其中一台主库的从库 redis-trib.rb add-node --slave --master-id 349a51df26f4723f14faba2a7fe3cad587659e86 172.25.100.18:7008 172.25.100.11:7001 #5.0版本以后 redis-cli --cluster add-node --cluster-slave --cluster-master-id 349a51df26f4723f14faba2a7fe3cad587659e86 172.25.100.18:7008 172.25.100.11:7001 -a password01!
注意:
--slave 表示添加的是从节点
--master-id 349a51df26f4723f14faba2a7fe3cad587659e86 须要添加到的主节点的node id,咱们如今要添加的是7007的从库,因此ID就是7007的ID了
172.25.100.18:7008 须要添加进去的,新的节点IP
172.25.100.11:7001 现存集群的任意一个节点
由于添加slave不须要分配哈希槽,因此这样就完事了
最后,咱们来谈删除节点,必需要理解的是,咱们删除节点的前提是这个节点没有数据,这样才能安全删除,因此咱们删除节点以前,必需要迁移数据槽.还记得上面手动迁移数据槽嘛,如今再次操做一下.
#先删除从库 redis-trib.rb del-node 172.25.100.18:7008 c89856b99f08b02ecad68ce6e4ab92c9d989a177 #3.0/3.2/4.0版本,这个时候填的IP,就是要移除的主节点ip和端口号 redis-trib.rb reshard 172.25.100.18:7007 #要移除多少个数据槽,填的就是所有,也就是4000 How many slots do you want to move (from 1 to 16384)? 4000 #找谁接收这部分数据槽?随便一个啦 What is the receiving node ID?e28a4244cc0e3ca74d973e57b1e5c4d93cd230b1 #被删除master的node-id Source node #1:349a51df26f4723f14faba2a7fe3cad587659e86 #再次确认 Source node #2:done #就是执行这个reshard计划的意思 Do you want to proceed with the proposed reshard plan (yes/no)? yes #这个时候,就能直接删除了 redis-trib.rb del-node 172.25.100.18:7007 349a51df26f4723f14faba2a7fe3cad587659e86 #5.0以后 redis-cli --cluster del-node 172.25.100.18:7007 349a51df26f4723f14faba2a7fe3cad587659e86
这个时候,这个节点就不存在了,可是数据槽的分配势必有些混乱,因此想要合理一些,还须要微调,这里不展开说了.
redis cluster命令行
1.集群(cluster)
CLUSTER INFO 打印集群的信息
CLUSTER NODES 列出集群当前已知的全部节点(node),以及这些节点的相关信息。
2.节点(node)
CLUSTER MEET 将 ip 和 port 所指定的节点添加到集群当中,让它成为集群的一份子。
CLUSTER FORGET 从集群中移除 node_id 指定的节点。
CLUSTER REPLICATE 将当前节点设置为 node_id 指定的节点的从节点。
CLUSTER SAVECONFIG 将节点的配置文件保存到硬盘里面。
3.槽(slot)
CLUSTER ADDSLOTS [slot ...] 将一个或多个槽(slot)指派(assign)给当前节点。
CLUSTER DELSLOTS [slot ...] 移除一个或多个槽对当前节点的指派。
CLUSTER FLUSHSLOTS 移除指派给当前节点的全部槽,让当前节点变成一个没有指派任何槽的节点。
CLUSTER SETSLOT NODE 将槽 slot 指派给 node_id 指定的节点,若是槽已经指派给另外一个节点,那么先让另外一个节点删除该槽>,而后再进行指派。
CLUSTER SETSLOT MIGRATING 将本节点的槽 slot 迁移到 node_id 指定的节点中。
CLUSTER SETSLOT IMPORTING 从 node_id 指定的节点中导入槽 slot 到本节点。
CLUSTER SETSLOT STABLE 取消对槽 slot 的导入(import)或者迁移(migrate)。
4.键 (key)
CLUSTER KEYSLOT 计算键 key 应该被放置在哪一个槽上。
CLUSTER COUNTKEYSINSLOT 返回槽 slot 目前包含的键值对数量。
CLUSTER GETKEYSINSLOT 返回 count 个 slot 槽中的键。
给redis-trib.rb添加密码
上面提到了,redis-trib.rb脚本中链接Redis的代码里面,并未设定密码的参数,形成使用不便,咱们能够经过修改代码实现带密码使用这个脚本,方法以下
#先打开这个脚本 vim /opt/redis-4.0.14/src/redis-trib.rb #找到对应函数connect的对应配置Redis.new,我这里显示是第99行代码 def connect(o={}) return if @r print "Connecting to node #{self}: " if $verbose STDOUT.flush begin @r = Redis.new(:host => @info[:host], :port => @info[:port], :timeout => 60) @r.ping rescue xputs "[ERR] Sorry, can't connect to node #{self}" exit 1 if o[:abort] @r = nil end xputs "OK" if $verbose end #而后修改为 @r = Redis.new(:host => @info[:host], :port => @info[:port], :timeout => 60, :password => "你的密码")
注意,这样改代码的密码是固定的,也就是说在搭建集群时,全部redis主从实例都要统一密码.
而后,就能够和上面同样启动
#虽然在这里仍是看不到密码,可是密码已经写入到redis-trib.rb脚本,也就是带密码了 /opt/redis-4.0.14/src/redis-trib.rb create --replicas 1 172.25.100.11:7001 172.25.100.11:7002 172.25.100.15:7003 172.25.100.15:7004 172.25.100.17:7005 172.25.100.17:7006
这样就可使用了