Redis(1.11)Redis cluster 分布式集群搭建

Posted 郭大侠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis(1.11)Redis cluster 分布式集群搭建相关的知识,希望对你有一定的参考价值。

概念与了解:Redis(1.7)Redis高可用架构(理论篇)

【0】试验环境

结构图如下:

  

(这里试验没有那么多机器,就用3台机器搭建试验)

redis1是redis集群的一个节点A,上面运行了两个redis实例,7001 7004

redis2是redis集群的一个节点B,上面运行了两个redis实例,7002 7005

redis3是redis集群的一个节点C,上面运行了两个redis实例,7003 7006

-- 试验集群包含 A/B/C A1/B1/C1 6个节点

  A、B、C 为主节点对应Redis实例:7001 7002 7003

  A1、A2、A3 为主节点的从库,对应Redis实例:7004 7005 7006

-- 交叉构建主从节点,对应关系为

  【A > B】  【B>C】  【C>A1】

    A:192.168.135.173

    B:192.168.135.174

    C:192.168.135.175

-- IP与端口分布:

redis4.0.11版本

cluster1:

  主:192.168.135.173 7001 /data/redis/redis-cluster/nodes-7001/redis.conf

  备:192.168.135.174 7005 /data/redis/redis-cluster/nodes-7005/redis.conf

cluster2:

  主:192.168.135.174 7002 /data/redis/redis-cluster/nodes-7002/redis.conf

  备:192.168.135.175 7006 /data/redis/redis-cluster/nodes-7006/redis.conf

cluster3:

  主:192.168.135.175 7003 /data/redis/redis-cluster/nodes-7003/redis.conf

  备:192.168.135.175 7004 /data/redis/redis-cluster/nodes-7004/redis.conf

-- 外界连接策略

  外端可以用F5、keepalived+haproyx结果,实现2个负载均衡(3台主的写,3台备的读)

 

【1】安装redis

  详细参考:Redis(1.1)linux下安装redis

  快速安装:

#【1.1】构建目录
#173 mkdir -p /data/redis/7001data mkdir -p /data/redis/7001log mkdir -p /data/redis/7001conf mkdir -p /data/redis/7004data mkdir -p /data/redis/7004log mkdir -p /data/redis/7004conf #174 mkdir -p /data/redis/7002data mkdir -p /data/redis/7002log mkdir -p /data/redis/7002conf mkdir -p /data/redis/7005data mkdir -p /data/redis/7005log mkdir -p /data/redis/7005conf #175 mkdir -p /data/redis/7003data mkdir -p /data/redis/7003log mkdir -p /data/redis/7003conf mkdir -p /data/redis/7006data mkdir -p /data/redis/7006log mkdir -p /data/redis/7006conf

#【1.2】安装(其实这一步可以省略,多实例不过是用不同的配置文件启动redis而已)
cd /soft/redis-4.0.14 && make PREFIX=\'/data/redis/7001data\' install 
cd /soft/redis-4.0.14 && make PREFIX=\'/data/redis/7004data\' install  
cd /soft/redis-4.0.14 && make PREFIX=\'/data/redis/7002data\' install 
cd /soft/redis-4.0.14 && make PREFIX=\'/data/redis/7005data\' install 
cd /soft/redis-4.0.14 && make PREFIX=\'/data/redis/7003data\' install 
cd /soft/redis-4.0.14 && make PREFIX=\'/data/redis/7006data\' install 
#【1.3】配置文件
vim /data/redis/7001conf/7001redis.conf
vim /data/redis/7004conf/7004redis.conf
vim /data/redis/7002conf/7002redis.conf
vim /data/redis/7005conf/7005redis.conf
vim /data/redis/7003conf/7003redis.conf
vim /data/redis/7006conf/7006redis.conf

然后目录和名字对应改一下即可(参数参考:Redis配置文件(4.0.14)
daemonize yes
logfile "/data/redis/7001log/redis.log"
#requirepass 123456
#masterauth 123456 bind 192.168.135.173 127.0.0.1 pidfile /data/redis/7001conf/redis.pid dbfilename redis.rdb dir /data/redis/7001conf/
port 7001
appendonly yes
appendfilename "appendonly.aof"
appendfsync always
cluster-enabled yes 
cluster-config-file nodes-7001.conf 
cluster-node-timeout 15000
appendonly yes

 【1.4】全部启动起来

redis-server /data/redis/7001conf/7001redis.conf

.....以此为例

 【1.5】构建的启动脚本 /data/redis/startall.sh,举例如下(每个机器根据自身情况修改)

#!/bin/bash
if [ $1 == \'start\' ]; then
redis-server /data/redis/7002conf/7002redis.conf
redis-server /data/redis/7005conf/7005redis.confelse
redis-cli -p 7002 -h 192.168.135.174 shutdown
redis-cli -p 7005 -h 192.168.135.174 shutdownfi

 

【2】安装redis-trib所需的 ruby脚本

  注意(本文用的4.0.11 所以需要用ruby等一系列很麻烦的操作。redis 5.0以后的版本 可以直接使用 redis-cli的方式搭建(redis-cli --cluster create 192.168.80.131:7001 192.168.80.131:7002 192.168.80.131:7003 192.168.80.131:7004 192.168.80.131:7005 192.168.80.131:7006 --cluster-replicas 1),省去了第【2】步,直接到【3】

  一台机器装即可

   3.0以上的redis才支持cluster,且需要 ruby 2.2以上版本才支持 redis-trib命令,而Centos7中默认的是2.0版本

  ruby下载:http://www.ruby-lang.org/zh_cn/downloads/

  ruby安装:http://www.ruby-lang.org/zh_cn/documentation/installation/#yum

  如果是直接下的tar.gz,一般是源码。

  yum源配置:Yum源配置

  离线安装:https://blog.csdn.net/zhanaolu4821/article/details/99750304


#[2.1] 查看ruby是否存在
ruby -v
#如果存在则需要卸载原来的老版本
rpm -e ruby-2.0.0.648-33.el7_4.x86_64 --nodeps
rpm -e ruby-irb-2.0.0.648-33.el7_4.noarch --nodeps
rpm -e ruby-libs-2.0.0.648-33.el7_4.x86_64 --nodeps

#【2.2】安装依赖包
yum install -y zlib-devel curl-devel openssl-devel httpd-devel apr-devel apr-util-devel 

#【2.3】源码安装ruby
#不存在可以去官网下载安装
#源码安装
./configure
make 
make install
ruby -v #检查是否安装成功

#默认情况下,Ruby 安装到 /usr/local 目录,并且已经在usr/local/bin/下面加了环境变量。
#如果想使用其他目录,可以把 --prefix=DIR 选项传给 ./configure 脚本。如果命令还是没用则退出登录用户再重登试试。

#【2.4】ruby-redis.gem安装(必须联网)
#这一步如果报错参考:gem install redis报错
#添加国内源命令
#gem source -l #查看当前gem源
#gem source -a https://gems.ruby-china.com/

#删除国外源并添加国内源
gem sources --add gem source -a https://gems.ruby-china.com/ --remove https://rubygems.org/
#要是自己下载的包就直接这样既可 gem install /soft/redis-4.1.3.gem
#要是网络安装
  gem install redis
    

【3】创建redis cluster

前置核心:

  (1)要先启动redis服务端

  (2)设置集群的时候密码必须为空,可以设计好集群后再配置密码

  (3)配置文件中的 bind 127.0.0.1  必须要改,改成 bind youripv4    127.0.0.1  ,这样其他机器和本机都可以直接访问

  (4)如果redis数据库数据不为空,则删除掉所有的数据(比如 aof,rdb 等,还不赶紧则 flushall)

#【3.1】切换到源码目录下
cd /soft/redis-4.0.14/src/
cp ./redis-trib.rb /usr/bin #添加环境变量


#【3.2】开始创建集群
redis-trib.rb create --replicas 1 192.168.135.173:7001 192.168.135.173:7004 192.168.135.174:7002 192.168.135.174:7005 192.168.135.175:7003 192.168.135.175:7006

#5.0以后可以直接用 redis-cli --cluster create 192.168.80.131:7001 192.168.80.131:7002 192.168.80.131:7003 192.168.80.131:7004 192.168.80.131:7005 192.168.80.131:7006 --cluster-replicas 1
--cluster-replicas 1表示希望为集群中的每个主节点创建一个从节点(一主一从)。
--cluster-replicas 2表示希望为集群中的每个主节点创建两个从节点(一主二从)。
输完命令后,集群相关信息会展现出来如下图:(这个主从是自动判断分配的
  

构建成功如下图:

   

 

#【3.3】创建失败

参考:Redis(1.12)Redis cluster搭建常见错误

 

 

【4】连接集群及核验

#【4.1】去任意节点登录集群 redis-cli -c
redis-cli -c -h 192.168.135.173 -p 7001

#【4.2】使用的时候会自动分布
set 和 get 都会跳到对应的实例上去。
  

 


 #【4.3】核验检查

 (1)redis-trib.rb check 192.168.135.173:7001 #(任意节点的IP:端口 即可)

    

     

 


  (2)任意节点 redis-cli -c 登录上去之后,使用 CLUSTER 命令(按tab 可以自动补全)

  redis -c -h 192.168.135.173 -p 7001

    (2.1)CLUSTER NODES

        

          

 

   (2.2)CLUSTER INFO

      

 

【5】添加删除集群节点

注意,千万不要cluster增删节点命令与 redis-trib.rb 增删节点混用!!!

【5.0】新增节点规划与操作

cluster 相关命令参考:https://www.cnblogs.com/kevingrace/p/7910692.html

192.168.135.174:7007
192.168.135.175:7008

192.168.135.174:      cd /data/redis      mkdir -p 7007{conf,log}     cp 7002conf/7002redis.conf 7007conf/7007redis.conf     #修改配置文件中的7002为7007即可
192.168.135.175:       cd /data/redis     mkdir -p 7008{conf,log}     cp 7003conf/7003redis.conf 7008conf/7008redis.conf     #修改配置文件中的7003为7008即可

【5.1】cluster meet 命令增删节点

【5.1.1】Cluster meet 增加节点(不建议使用这种办法,建议使用【5.2】)

#在任意节点登录都可以,我这里用 173:7001 节点登录了
redis-cli -c -h 192.168.135.173 -p 7001

#添加节点命令(用这个命令添加进来默认是没有分配槽位的,会在需要的时候自动把其他MSTER的槽位转移过来用的
cluster meet 192.168.135.174 7007
cluster meet 192.168.135.175 7008
#效果如下图,默认是以主节点的身份添加进来的
  

 

 #把其中一个设置为从,这里设置192.168.135.175:7008为7007的从

  A:比如要登录7008

    redis-cli -p 7008 -h 192.168.135.175 -c 

   B: 在A的登录环境下, cluster replicate 7007node_id

    cluster replicate d80a9c494633a6d84697ac5330dfb024e4a0866d

    #这是在没进行任何操作的情况,如果已经进行了set相关

    Node 192.168.135.173:7001 is not empty  

      

    查看了一下,原来是7008因为我之前set了一下,自动给它分配了一个槽位,所以如上图操作,我把该槽位释放掉就可以执行让其变成从库了!

    但如上图所示,并没有自动分配槽位给新增的主节点,而是等到使用的时候才会按需分配,且我们的13026槽位也并没有分配给某个具体master节点.所以,检查报错如下:

      

    出现新的错误:[ERR] Not all 16384 slots are covered by nodes

 

    修复:redis-trib.rb fix 192.168.135.175:7008 即,把这个槽从新分配一下给master

 

        

 

 

【5.1.2】cluster forget 命令移除节点

#登录
  redis-cli -p 7001 -h 192.168.135.173 -c

#(1)移除节点命令(移除7007   CLUSTER FORGET d80a9c494633a6d84697ac5330dfb024e4a0866d

#(2)发现错误
  (error)ERR Can\'t forget my master!
  (error)ERR I tried hard but I can\'t forget myself...
  #意思就是,从节点不能移除 master 节点,且如果登录的是主节点要移除的是自己也不行

#(3)解决办法
  切换到另外一个主节点即可。
  例如,删除 7007和7008
  cluster forget d80a9c494633a6d84697ac5330dfb024e4a0866d
  cluster forget c70173985021665bacd74231f03c2a001468e703

#(4)核验
  cluster nodes
#(5)保存当前配置
  cluster saveconfig

【5.2】redis-trib.rb 增删节点

参考:redis使用总结(二)

【5.2.1】redis-trib.rb 增加扩张节点

#(1)新增主节点,7001是原本存在的主节点(这里可以是集群中的任意节点),7007是新主节点
  redis-trib.rb add-node 192.168.135.174:7007 192.168.135.173:7001
  #命令的意思是,添加主节点 192.168.135.174:7001 到 192.168.135.17:7001所在集群

  #报错,因为我们之前使用过它加入进群
    [ERR] Node 192.168.135.174:7007 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.

  #解决
  在192.168.135.174机器上
    redis-cli -p 7007 -h 192.168.135.174 shutdown
    rm -rf /data/redis/7007conf/{appendonly.aof,redis.rdb,redis.pid,nodes-7007.conf}
    redis-server /data/redis/7007conf/7007redis.conf
  再次执行命令,执行成功,如下图:
      

 

 

#(2)登录集群任意节点,获取 id标识
  redis-cli -h 192.168.135.173 -c -p 7001 cluster nodes

#(3)添加从节点,7001是原本存在的主节点(这里可以写集群中的任意节点信息),7008是新增为7007从库的新节点
  redis-trib.rb add-node --slave --master-id c70173985021665bacd74231f03c2a001468e703 192.168.135.175:7008 192.168.135.173:7001
  #命令的意思,添加从节点,然后其主节点ID为...(通过cluster nodes获取 7007的id),从节点IP:端口, 加入 192.168.135.173:7001 所在的集群

#(4)为主节点重新分配solt
  redis-trib.rb reshard 192.168.135.174:7007
    #重新分配,会弹出如下对话框,输入4000,即设置该节点slot数为4000
  How many slots do you wan to move(from 1 to 16384)? 4000
What is the receiving node ID? #输入7007的 id
  Source node #1:all #从哪里分配?all则标识全部节点重新洗牌分配(新环境可以,但旧环境会导致停机的),也可以写具体的node_id

  #自动平衡槽数量
    redis-trib.rb rebalance 192.168.135.174:7007

【5.2.2】redis-trib.rb 缩减节点

#(1)流程说明

  A:确定要下线移除的节点是否存在slot,如果有,需要先把slot迁移到其他节点,保证整个集群槽节点映射的完整性;
  
  B:当下线的节点没有槽或本身是从节点时,就可以通知集群内其他节点(或者叫忘记节点),当下线的节点被集群忘记后正常关闭。
#(2)登录任意集群节点查看 node_id
  redis-cli -c -h 192.168.135.173 -p 7001 cluster nodes
#(3
)删除节点   #分为两种,一种是删除主节点 192.168.135.174:7007,另一种是删除从节点 192.168.135.175:7008   
  #删除从节点7008(因为没有分配哈希槽,可以直接删除)
    redis-trib.rb del-node 192.168.135.175:7008
c70173985021665bacd74231f03c2a001468e703
    #redis-trib.rb del-node ip:port node_id
  
  #删除主节点7007(分配了hash槽,需要把hash槽转移到别的节点去,才能够删除)
  直接删除肯定会报错的:
     
#(4)缩减槽位
redis-trib.rb reshard 192.168.135.174:7007 #后面这个IP及端口,其实是集群内任意节点都可以,主要是为了让命令识别是哪个集群,任意节点都可以让其识别出整个集群信息
#redis-trib.rb reshard --from e37957bd67cc4932183c6549ee7368cbc93b7499 --to ba694e2969adb6c06a1f7dc596168ccc57ee9e1d --slots 1500 --yes 192.168.135.173:7001


    

  看上图中,下班部分的框线,意思是

  (1)想要移走多少个slot?

  (2)谁接受这些slot,这里我写的node_id 是7001的

  (3)这些移动的槽来源在哪里,写我们的7007对应的node_id即可

  #移走之后,可以删掉7007节点了

    redis-trib.rb del-node 192.168.135.174:7007 99a603ef36215bfadf382dadb62f9bfe59711b41


#知道了上面reshard意思,我们可以直接用命令写完这些,不需要交互方式写。
  redis-trib.rb reshard --from e37957bd67cc4932183c6549ee7368cbc93b7499 --to ba694e2969adb6c06a1f7dc596168ccc57ee9e1d --slots 1500 --yes 192.168.135.173:7001
#把7001对应的node_id 移动1500个槽给 7004

     

      

 

       

【6】redis cluster的故障转移

     redis集群实现了,高可用,当集群内少量节点出现故障时,通过故障转移可以保证集群正常对外服务。

  当集群里某个节点出现了问题,redis集群内的节点通过Ping Pong消息发现节点是否健康,是否有故障。

  故障恢复:

    如果下线节点是主节点,则需要在它的从节点中选一个替换它,保证集群的高可用,转移过程如下:

      (1)资格检查(必须要主节点才有资格投票)

      (2)准备选举时间

      (3)发起投票

      (4)选举投票,从库>50%

 

 【6.1】查看当前集群状况,构造测试数据

redis-cli -c -p 7001 -h 192.168.135.173

  

 

 好,如上图,现在三个主库上都有了。

模拟:现在重启 192.168.135.175 机器,包含7003和7006 2个节点

  

 

   如上图,之前t5是在7006的,现在get t5切换到了7002 证明已经自动故障转移了

  重启 192.168.135.175 7003和7006 节点之后,我们可以看到主从又自动分配了,但原本的主从关系已经随着故障转移彻底改变了。

    

 

【7】集群性能测试方法

这个命令在/data/redis/bin/redis-benchmark  ,是redis自带的。

用法及参数如下:

redis-benchmark [-h <host>] [-p <port>] [-c <clients>] [-n <requests>] [-k <boolean>]

 -h <hostname>      Server hostname (default 127.0.0.1)
 -p <port>          Server port (default 6379)
 -s <socket>        Server socket (overrides host and port)
 -a <password>      Password for Redis Auth
 -c <clients>       Number of parallel connections (default 50)
 -n <requests>      Total number of requests (default 100000)
 -d <size>          Data size of SET/GET value in bytes (default 3)
 --dbnum <db>       SELECT the specified db number (default 0)
 -k <boolean>       1=keep alive 0=reconnect (default 1)
 -r <keyspacelen>   Use random keys for SET/GET/INCR, random values for SADD
  Using this option the benchmark will expand the string __rand_int__
  inside an argument with a 12 digits number in the specified range
  from 0 to keyspacelen-1. The substitution changes every time a command
  is executed. Default tests use this to hit random keys in the
  specified range.
 -P <numreq>        Pipeline <numreq> requests. Default 1 (no pipeline).
 -e                 If server replies with errors, show them on stdout.
                    (no more than 1 error per second is displayed)
 -q                 Quiet. Just show query/sec values
 --csv              Output in CSV format
 -l                 Loop. Run the tests forever
 -t <tests>         Only run the comma separated list of tests. The test
                    names are the same as the ones produced as output.
 -I                 Idle mode. Just open N idle connections and wait.

Examples:

 Run the benchmark with the default configuration against 127.0.0.1:6379:
   $ redis-benchmark

 Use 20 parallel clients, for a total of 100k requests, against 192.168.1.1:
   $ redis-benchmark -h 192.168.1.1 -p 6379 -n 100000 -c 20

 Fill 127.0.0.1:6379 with about 1 million keys only using the SET test:
   $ redis-benchmark -t set -n 1000000 -r 100000000

 Benchmark 127.0.0.1:6379 for a few commands producing CSV output:
   $ redis-benchmark -t ping,set,get -n 100000 --csv

 Benchmark a specific command line:
   $ redis-benchmark -r 10000 -n 10000 eval \'return redis.call("ping")\' 0

 Fill a list with 10000 random elements:
   $ redis-benchmark -r 10000 -n 10000 lpush mylist __rand_int__

 On user specified command lines __rand_int__ is replaced with a random integer
 with a range of values selected by the -r option.

案例语句:

#(1)常规通用
-c 客户端,-r 请求多少个随机key ,-n 总请求量 ,-t 操作 ,-P 通道、线程 time /data/redis/bin/redis-benchmark -h 192.168.135.173 -p 7001 -c 200 -r 1000000 -n 2000000 -t get,set,lpush,lpop -P 16 -q

#(2)100个并发连接,100000个请求,检测host为192.168.135.173,port为6379的redis服务器性能
redis-benchmark -h 192.168.135.173 -p 7001 -c 100 -n 100000

#(3)测试存取大小为100字节的数据包的性能
redis-benchmark -h 192.168.135.173 -p 7001 -q -d 100

#(4)测试某些redis操作的性能
redis-benchmark -t set,lpush -n 100000 -q

#(5)只测试某些值存取的性能
redis-benchmark -n 100000 -q script load "redis.call(\'set\',\'key1\',\'value1\')"

 

【8】redis5.0.x版本集群安装

所有的步骤思路,和4.0.11并无不同,只是命令语法改了一点而已

8.1】创建集群并自动分配槽

redis
-cli --cluster create 192.168.80.131:7001 192.168.80.131:7002 192.168.80.131:7003 192.168.80.131:7004 192.168.80.131:7005 192.168.80.131:7006 --cluster-replicas 1

8.2】对集群槽位重新分片
redis-cli --cluster reshard 192.168.135.173:7001
  
  How many slots do you want to move(from 1 to 16384)? 需要移动分配的槽位数量
  
What is the receiving node ID  指定接收这些槽位数的 节点ID
  Source node #1:  all/ID 重新分片的源节点(source node)
  Do you want to proceed with the proposed reshard plan (yes/no)? yes 确认

【8.3】检查集群是否正常

redis-cli --cluster check 192.168.135.173:7001

【8.4】添加节点

redis-cli --cluster add-node 192.168.135.174:7007 192.168.135.173:7001

#命令中的 add-node 表示我们要 将一个节点添加到集群里面, add-node 之后跟着的是新节点的 IP 地址和端口号, 再之后跟着的是集群中任意一个已存在节点的 IP 地址和端口号
和其他主节点相比, 新节点还有两点区别:
  新节点没有包含任何数据, 因为它没有包含任何哈希桶。
  尽管新节点没有包含任何哈希嘈, 但它仍然是一个主节点, 所以在集群需要将某个从节点升级为新的主节点时, 这个新节点不会被选中。

(1)添加节点后,让节点成为主节点

  #可以使用如下命令来分配槽位使其成为真正的主节点。

    redis-cli --cluster reshard 192.168.135.174:7007 (这个IP+端口,可以是集群内任意节点信息)
(2)添加节点后,让节点变成从节点
  
  #实现使用 cluster nodes 查看好对应的主节点 node_id =》登录上从节点:redis-cli -h 192.168.135.174 -p 7007 =》 设置该节点为指定主节点node_id的从库:命令如下

    redis 192.168.135.174:7007> cluster replicate 主节点ID
【8.5】删除节点

#删除从节点
  redis-cli --cluster del-node 192.168.135.174:7007 10363eb...

 #删除主节点
    #如果主节点有从节点,将从节点转移到其他主节点
    #如果主节点有slot,去掉分配的slot,然后在删除主节点

    redis-cli --cluster del-node 192.168.135.174:7007 108929...

    [ERR] Node 127.0.0.1:7003 is not empty! Reshard data away and try again.

    [ERR] 哈希槽非空

  #重新分片去掉所有哈希槽

    redis-cli --cluster reshard 192.168.135.174:7007

  #重新分片后从节点也自动转移到其他主节点了

    redis-cli --cluster del-node 192.168.135.174:7007 10363eb...

 

 

参考文献:

https://www.cnblogs.com/PatrickLiu/p/8458788.html

https://www.cnblogs.com/wslook/p/9152596.html

Redis(1.12)Redis cluster搭建常见错误

以上是关于Redis(1.11)Redis cluster 分布式集群搭建的主要内容,如果未能解决你的问题,请参考以下文章

Redis Cluster集群

redis cluster集群选主

怎样设置redis cluster的日志输出

redis cluster集群理解

redis cluster

redis集群与分片-Redis Cluster集群的搭建与实践