redis集群-4

redis集群原理

redis cluster在设计的时候,就考虑到了去中心化,去中间件,也就是说,集群中的每个节点都是平等的关系,都是对等的,每个节点都保存各自的数据和整个集群的状态。
每个节点都和其他所有节点连接,而且这些连接保持活跃,这样就保证了我们只需要连接集群中的任意一个节点,就可以获取到其他节点的数据。 Redis 集群没有并使用传统的一致性哈希来分配数据,而是采用另外一种叫做哈希槽 (hash slot)的方式来分配的。
redis cluster 默认分配了
16384 个slot,当我们set一个key 时,会用CRC16算法来取模得到所属的slot,然后将这个key 分到哈希槽区间的节点上,具体算法就是:CRC16(key) % 16384
所以我们在测试的时候看到set 和 get 的时候,直接跳转到了7001端口的节点。 Redis 集群会把数据存在一个 master 节点,然后在这个 master 和其对应的salve 之间进行数据同步。
当读取数据时,也根据一致性哈希算法到对应的 master 节点获取数据。只有当一个master 挂掉之后,才会启动一个对应的 salve 节点,充当 master 。

使用环境

解决单点固障,连接上集群中的任务一个节点都能取到数据.

安装环境

需要注意的是:reids集群从3.0开始支持的。必须要3个或以上的主节点,否则在创建集群时会失败,并且当存活的主节点数小于总节点数的一半时,整个集群就无法提供服务了
192.168.23.150 使用的docker
    node1_redis 172.16.0.10
    node2_redis 172.16.0.11

6个redis节点信息:
    172.16.0.10:7001
    172.16.0.10:7002
    172.16.0.10:7003
    172.16.0.11:7004
    172.16.0.11:7005
    172.16.0.11:7006

安装redis-3.2.8

分别在两个节点上安装redis
yum install -y gcc tar
-xf redis-3.2.8.tar.gz cd redis-3.2.8 make && make PREFIX=/opt/redis install
#centos7安装
make MALLOC=libc && make PREFIX=/opt/redis install
cd src 
cp redis
-trib.rb /opt/redis/bin/
echo
"export PATH=$PATH:/opt/redis/bin" >> /etc/profile.d/env.sh
source
/etc/profile

创建redis节点

分别在两个节点上创建,别外一台是7004,70057006
创建目录
    cd /opt/redis
    mkdir -p {data,logs}/redis_cluster/{7001,7002,7003}
准备配置文件redis.conf
    daemonize yes
  protected-mode no  #3.2 后的新特性,禁止公网访问redis cache,加强redis安全的 pidfile
/opt/redis/data/redis_cluster/7001/redis_7001.pid port 7001 timeout 300 loglevel debug logfile /opt/redis/data/redis_cluster/7001/redis_7001.log databases 16 save 900 1 save 300 10 save 60 10000 rdbcompression yes dbfilename dump.rdb dir /opt/redis/data/redis_cluster/7001/ cluster-enabled yes #开启集群 把注释#去掉 cluster-config-file nodes_7001.conf #集群的配置 配置文件首次启动自动生成 7001,7001,7002 cluster-node-timeout 15000 #请求超时 默认15秒,可自行设置 cp -a redis.conf /opt/redis/data/redis_cluster/7001/ cp -a redis.conf /opt/redis/data/redis_cluster/7002/ cp -a redis.conf /opt/redis/data/redis_cluster/7003/ sed -i 's/7001/7001/g' /opt/redis/data/redis_cluster/7001/redis.conf sed -i 's/7001/7002/g' /opt/redis/data/redis_cluster/7002/redis.conf sed -i 's/7001/7003/g' /opt/redis/data/redis_cluster/7003/redis.conf redis-server /opt/redis/data/redis_cluster/7001/redis.conf redis-server /opt/redis/data/redis_cluster/7002/redis.conf redis-server /opt/redis/data/redis_cluster/7003/redis.conf

创建redis集群

安装依赖
    yum -y install ruby ruby-devel rubygems rpm-build

    安装ruby redis 接口
        gem install redis  #执行这步失败的话。可以说明的方式操作
          1. Fetching: redis-3.2.2.gem (100%)
          2. Successfully installed redis-3.2.2
          3. Parsing documentation for redis-3.2.2
          4. Installing ri documentation for redis-3.2.2
          5. Done installing documentation for redis after 1 seconds
          6. 1 gem installed
        说明:由于ruby 官放提供的gem 源被GFW 干掉了,所以这里需要重新使用国内的源,方法如下:
        移除自带的源:
            gem sources -l
            gem sources --remove https://rubygems.org/
            添加国内淘宝源:
            gem source --add https://ruby.taobao.org/
            gem sources -l
            gem install redis
 报错:redis requires Ruby version >= 2.2.2
    解决:
    方法1:采用rvm来更新ruby(不好用)
      gpg2 --keyserver hkp://keys.gnupg.net --recv-keys D39DC0E3
      curl -L get.rvm.io | bash -s stable
      source /usr/local/rvm/scripts/rvm
      rvm list known #查看rvm库中已知的ruby版本
rvm install 2.3.3
      rvm use 2.3.3
rvm use 2.3.3 --default #默认使用版本
rvm remove 2.0.0 #移除2.0.0版本
ruby --version #查看版本
      
      gem install redis
 方法2:编译安装(好用)
      (1)
安装Ruby
      wget http://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.5.tar.gz
      tar zxvf  ruby-2.3.5.tar.gz
      cd ruby-2.3.5
      ./configure  --prefix=/opt/ruby
      make && make install
      ln -s /opt/ruby/bin/ruby /usr/bin/ruby
      ln -s /opt/ruby/bin/gem /usr/bin/gem
      ruby -v #查看版本
      (2)安装rubygem redis依赖
      wget http://rubygems.org/downloads/redis-3.3.0.gem
      gem install -l redis-3.3.0.gem
      redis-trib.rb   #出现帮助文档,说明成功了

       创建集群 redis
-trib.rb create --replicas 1 172.16.0.10:7001 172.16.0.10:7002 172.16.0.10:7003 172.16.0.11:7004 172.16.0.11:7005 172.16.0.11:7006 #--replicas 1 就是这个集群节点都有一个副本

连接集群

连接方式为 redis-cli -h 172.16.0.10 -c -p 7002  ,加参数 -c 可连接到集群,因为上面 redis.conf 将 bind 改为了ip地址,所以 -h 参数不可以省略。

集群验证

在第一台机器上连接集群的7002端口的节点,在另外一台连接7005节点,连接方式为 redis-cli -h 172.16.0.10 -c -p 7002  
,加参数 -c 可连接到集群,因为上面 redis.conf 将 bind 改为了ip地址,所以 -h 参数不可以省略。 在7005节点执行命令: set hello world 在7002节点执行: get hello 在任何节点上能获取到hello的值,说明集群运作正常(注意:用keys *查看不到key.但是get hello 可以获取到值,另外可以在副本节点上面添加数据)

集群状态查看

随便登陆一个redis node节点执行命令:
    redis-cli -h 172.16.0.10 -c -p 7002 #登陆
    cluster nodes  #查看节点信息

 添加节点

添加启动个节点,步聚和上面一样
执行redis-trib.rb add-node 添加新节点:
/opt/src/redis-3.0.5/src/redis-trib.rb add-node 127.0.0.1:7007 127.0.0.1:7001
说明:添加新节点到群集中,需要指定群集中任意一个已存在的节点,实例中的第一个IP:PORT 为新的redis 节点的IP及端口,第二个IP:PORT 为redis 群集中已经存在的任意redis 节点。
添加完成,登陆群集,验证加入后的新节点变为主节点:
redis-cli -c -h 127.0.0.1:7001
  1. 127.0.0.1:7001> cluster nodes
  2. 1455e7fe08990793e9663ed14cf9c19778ef01a7 127.0.0.1:7004 slave 5951f796ac2930f73b6988ccb633ab2ea10a873b 0 1447233606830 5 connected
  3. 577be6355e37a54c7a076e27ab0927298abcae5f 127.0.0.1:7003 slave 73bf492caa9ba02567581145b5d4f32f9f28e09d 0 1447233608841 4 connected
  4. 30117592dc0d31b1c611ca47820f1d820565926e 127.0.0.1:7005 slave 1e157ac10d8292661e80c6ee17f09d2dc94a4b2a 0 1447233607331 6 connected
  5. 1e157ac10d8292661e80c6ee17f09d2dc94a4b2a 127.0.0.1:7002 master - 0 1447233607835 3 connected 10923-16383
  6. 9868224efa99bca26a171f6e1c21dc11c4e2ab5c 127.0.0.1:7006 master - 0 1447233607331 0 connected
  7. 73bf492caa9ba02567581145b5d4f32f9f28e09d 127.0.0.1:7001 myself,master - 0 0 1 connected 0-5460
  8. 5951f796ac2930f73b6988ccb633ab2ea10a873b 127.0.0.1:7001 master - 0 1447233607331 2 connected 5461-10922
2.添加从节点:
/opt/src/redis-3.0.5/src/redis-trib.rb add-node --slave 127.0.0.1:7008 127.0.0.1:7001
redis-cli -c -p 7001
  1. 127.0.0.1:7001> cluster nodes
  2. ef275d7c4c1f00ce236011f0c0cd7b4be7eb7772 127.0.0.1:7007 slave 9868224efa99bca26a171f6e1c21dc11c4e2ab5c 0 1447241281594 0 connected
  3. 1455e7fe08990793e9663ed14cf9c19778ef01a7 127.0.0.1:7004 slave 5951f796ac2930f73b6988ccb633ab2ea10a873b 0 1447241282095 5 connected
  4. 577be6355e37a54c7a076e27ab0927298abcae5f 127.0.0.1:7003 slave 73bf492caa9ba02567581145b5d4f32f9f28e09d 0 1447241282597 4 connected
  5. 30117592dc0d31b1c611ca47820f1d820565926e 127.0.0.1:7005 slave 1e157ac10d8292661e80c6ee17f09d2dc94a4b2a 0 1447241281594 6 connected
  6. 1e157ac10d8292661e80c6ee17f09d2dc94a4b2a 127.0.0.1:7002 master - 0 1447241283098 3 connected 10923-16383
  7. 9868224efa99bca26a171f6e1c21dc11c4e2ab5c 127.0.0.1:7006 master - 0 1447241282095 0 connected
  8. 73bf492caa9ba02567581145b5d4f32f9f28e09d 127.0.0.1:7001 myself,master - 0 0 1 connected 0-5460
  9. 5951f796ac2930f73b6988ccb633ab2ea10a873b 127.0.0.1:7001 master - 0 1447241283599 2 connected 5461-10922

数据分片转移

数据分片,也可称数据转移。由第二篇中添加的主节点可知,新的主节点没有数据,也不能参加主的选举,所以,为了该主恩能够正常被选举,我们可以将原有主节点的数据转移至该节点:
我们先来看下新主节点:

192.168.159.30:7003> cluster nodes
4a5799c7a7f53e8700e99be5a7a50d65c4204cac 192.168.159.30:7003 myself,master - 0 0 3 connected 10923-16383
3d76e38836d78b0dc81ac7c0c306b57f2b6a389e 192.168.159.30:7006 slave 4a5799c7a7f53e8700e99be5a7a50d65c4204cac 0 1523528690606 6 connected
cc7833a44dd9f9a0157adec82e5afa959d20f29d 192.168.159.30:7004 slave 6d377542e01a23fe5cfc7f8f25365e910480a11a 0 1523528689096 4 connected
869458ad40bb9a2e4dcb870f3c2a4a2a2d3bc257 192.168.159.30:7005 slave 73b5273bfa67693eeb01a5c99c855a333d6214e0 0 1523528688595 5 connected
9078070919bf726e213dfa634d86a5ae1f7a0ae8 127.0.0.1:7008 slave 456cbd75f4a74f818cb396b207b1ad6a3e4a242e 0 1523528687589 7 connected
6d377542e01a23fe5cfc7f8f25365e910480a11a 192.168.159.30:7001 master - 0 1523528686584 1 connected 0-5460
73b5273bfa67693eeb01a5c99c855a333d6214e0 192.168.159.30:7002 master - 0 1523528687087 2 connected 5461-10922
456cbd75f4a74f818cb396b207b1ad6a3e4a242e 192.168.159.30:7007 master - 0 1523528689600 7 connected  #新加节点没有数据

 从上面的实例中可以很明显的看出,有三个从,四个主,当前登录的主为7003,且除了主节点7007没有数据外,其它三个主都有(7001:0-5460;7002:5461-10922;7003:10923-16383)

现在,我需要从三个节点抽取500个数据槽给新节点 7007,那么执行

redis-trib.rb reshard 127.0.0.1:7007

询问从1-16384 个插槽中要移动多少数据槽,我这里是500:

How many slots do you want to move (from 1 to 16384)? 500

询问接收数据槽节点的ID(根据上面的cluster nodes 可以得到 7007 的ID):

What is the receiving node ID? 9868224efa99bca26a171f6e1c21dc11c4e2ab5c

询问你是从所有主节点移除500 个数据槽还是单从某一个主节点中移出 500个数据槽?输入 all ,代表从所有主节点;如果要从某个节点逸出,那么只需要输入该主节点ID,回车即可:

Please enter all the source node IDs.
  Type 'all' to use all the nodes as source nodes for the hash slots.
  Type 'done' once you entered all the source nodes IDs.
Source node #1:all

输入完成,回车后开始移动数据槽

移动完成,再来看各主的数据

192.168.159.30:7003> cluster nodes
4a5799c7a7f53e8700e99be5a7a50d65c4204cac 192.168.159.30:7003 myself,master - 0 0 3 connected 11172-16383
3d76e38836d78b0dc81ac7c0c306b57f2b6a389e 192.168.159.30:7006 slave 4a5799c7a7f53e8700e99be5a7a50d65c4204cac 0 1523530671361 6 connected
cc7833a44dd9f9a0157adec82e5afa959d20f29d 192.168.159.30:7004 slave 6d377542e01a23fe5cfc7f8f25365e910480a11a 0 1523530673372 8 connected
869458ad40bb9a2e4dcb870f3c2a4a2a2d3bc257 192.168.159.30:7005 slave 73b5273bfa67693eeb01a5c99c855a333d6214e0 0 1523530675386 5 connected
9078070919bf726e213dfa634d86a5ae1f7a0ae8 127.0.0.1:7008 slave 456cbd75f4a74f818cb396b207b1ad6a3e4a242e 0 1523530670360 9 connected
6d377542e01a23fe5cfc7f8f25365e910480a11a 192.168.159.30:7001 master - 0 1523530674379 8 connected 500-5711 10923-11171
73b5273bfa67693eeb01a5c99c855a333d6214e0 192.168.159.30:7002 master - 0 1523530674883 2 connected 5712-10922
456cbd75f4a74f818cb396b207b1ad6a3e4a242e 192.168.159.30:7007 master - 0 1523530672367 9 connected 0-499    #很明显,主 7006 上已经被分配数据槽了!

上面是从所有主节点中平均抽取数据槽到新的主节点上。

==================对单一节点进行===========================

那么,我们也可以针对单一节点进行,比如,我想将7001 剩余的数据槽全部转移到 7007 上,那么如下:

执行:

redis-trib.rb reshard 127.0.0.1:7007

主节点 7001 上可以转移的数据槽:

How many slots do you want to move (from 1 to 16384)? 5295

接收数据节点的ID:

What is the receiving node ID? 9868224efa99bca26a171f6e1c21dc11c4e2ab5c

转移数据主节点的ID(就是要把哪个节点的数据转移出去的节点ID)

Please enter all the source node IDs.
  Type 'all' to use all the nodes as source nodes for the hash slots.
  Type 'done' once you entered all the source nodes IDs.
Source node #1:73bf492caa9ba02567581145b5d4f32f9f28e09d

输完一个要转移数据的节点后,会继续要求输入第二个节点的ID。由于这里我只想转移主节点7000 上的所有数据,所以,第二个节点ID 我输入done,代表只需要转移第一个主节点:

Source node #2:done

询问你是否确认要执行数据分片:

Do you want to proceed with the proposed reshard plan (yes/no)? yes

再次登录查看集群:

192.168.159.30:7003> cluster nodes
4a5799c7a7f53e8700e99be5a7a50d65c4204cac 192.168.159.30:7003 myself,master - 0 0 3 connected 11172-16383
3d76e38836d78b0dc81ac7c0c306b57f2b6a389e 192.168.159.30:7006 slave 4a5799c7a7f53e8700e99be5a7a50d65c4204cac 0 1523531456275 6 connected
cc7833a44dd9f9a0157adec82e5afa959d20f29d 192.168.159.30:7004 slave 456cbd75f4a74f818cb396b207b1ad6a3e4a242e 0 1523531457281 9 connected
869458ad40bb9a2e4dcb870f3c2a4a2a2d3bc257 192.168.159.30:7005 slave 73b5273bfa67693eeb01a5c99c855a333d6214e0 0 1523531454767 5 connected
9078070919bf726e213dfa634d86a5ae1f7a0ae8 127.0.0.1:7008 slave 456cbd75f4a74f818cb396b207b1ad6a3e4a242e 0 1523531454266 9 connected
6d377542e01a23fe5cfc7f8f25365e910480a11a 192.168.159.30:7001 master - 0 1523531453260 8 connected #可以看到7001没有数据了
73b5273bfa67693eeb01a5c99c855a333d6214e0 192.168.159.30:7002 master - 0 1523531455270 2 connected 5712-10922
456cbd75f4a74f818cb396b207b1ad6a3e4a242e 192.168.159.30:7007 master - 0 1523531452253 9 connected 0-5711 10923-11171

 节点删除

redis 群集中,要删除节点,必须先将该节点的数据全部转移,否则是无法删除节点的(也就是,redis 群集中智能删除空节点):

查看集群信息:

redis-cli -h 192.168.159.30 -p 7001 -c
192.168.159.30:7001> cluster nodes
3d76e38836d78b0dc81ac7c0c306b57f2b6a389e 192.168.159.30:7006 slave 4a5799c7a7f53e8700e99be5a7a50d65c4204cac 0 1523531623348 6 connected
9078070919bf726e213dfa634d86a5ae1f7a0ae8 127.0.0.1:7008 slave 456cbd75f4a74f818cb396b207b1ad6a3e4a242e 0 1523531627894 9 connected
456cbd75f4a74f818cb396b207b1ad6a3e4a242e 127.0.0.1:7007 master - 0 1523531625877 9 connected 0-5711 10923-11171
869458ad40bb9a2e4dcb870f3c2a4a2a2d3bc257 192.168.159.30:7005 slave 73b5273bfa67693eeb01a5c99c855a333d6214e0 0 1523531626887 5 connected
cc7833a44dd9f9a0157adec82e5afa959d20f29d 192.168.159.30:7004 slave 456cbd75f4a74f818cb396b207b1ad6a3e4a242e 0 1523531624862 9 connected
6d377542e01a23fe5cfc7f8f25365e910480a11a 127.0.0.1:7001 myself,master - 0 0 8 connected       #7001没有数据
73b5273bfa67693eeb01a5c99c855a333d6214e0 192.168.159.30:7002 master - 0 1523531628902 2 connected 5712-10922
4a5799c7a7f53e8700e99be5a7a50d65c4204cac 192.168.159.30:7003 master - 0 1523531623853 3 connected 11172-16383

我们来尝试删除某个带有数据的主节点:

[root@docker1 ~]# redis-trib.rb del-node 127.0.0.1:7002 '73b5273bfa67693eeb01a5c99c855a333d6214e0'  
>>> Removing node 73b5273bfa67693eeb01a5c99c855a333d6214e0 from cluster 127.0.0.1:7002
[ERR] Node 127.0.0.1:7002 is not empty! Reshard data away and try again  #7002是随便哪个能连上集群的端口,后面的是非空数据的节点ID. 可以看出非空的节点不能删除

再次删除空节点:

redis-trib.rb del-node 127.0.0.1:7002 '6d377542e01a23fe5cfc7f8f25365e910480a11a'
>>> Removing node 6d377542e01a23fe5cfc7f8f25365e910480a11a from cluster 127.0.0.1:7002
>>> Sending CLUSTER FORGET messages to the cluster...
>>> SHUTDOWN the node.


注:在删除节点时,不允许使用 redis-trib.rb del-node 删除节点IP:PORT '删除节点的ID'.只能用其它节点IP:PORT '要删除节点的ID'

验证被删除:

[root@docker1 ~]# redis-cli -h 192.168.159.30 -p 7002 -c
192.168.159.30:7002> cluster nodes
cc7833a44dd9f9a0157adec82e5afa959d20f29d 192.168.159.30:7004 slave 456cbd75f4a74f818cb396b207b1ad6a3e4a242e 0 1523532545171 9 connected
9078070919bf726e213dfa634d86a5ae1f7a0ae8 192.168.159.30:7008 slave 456cbd75f4a74f818cb396b207b1ad6a3e4a242e 0 1523532546685 9 connected
456cbd75f4a74f818cb396b207b1ad6a3e4a242e 192.168.159.30:7007 master - 0 1523532548195 9 connected 0-5711 10923-11171
869458ad40bb9a2e4dcb870f3c2a4a2a2d3bc257 192.168.159.30:7005 slave 73b5273bfa67693eeb01a5c99c855a333d6214e0 0 1523532546181 5 connected
73b5273bfa67693eeb01a5c99c855a333d6214e0 192.168.159.30:7002 myself,master - 0 0 2 connected 5712-10922
4a5799c7a7f53e8700e99be5a7a50d65c4204cac 192.168.159.30:7003 master - 0 1523532544157 3 connected 11172-16383
3d76e38836d78b0dc81ac7c0c306b57f2b6a389e 192.168.159.30:7006 slave 4a5799c7a7f53e8700e99be5a7a50d65c4204cac 0 1523532547190 6 connected



注#可以看出7001已经被删除了,上面删除的id就是7001的

 

posted @ 2018-04-12 15:13  xgmxm  阅读(696)  评论(0编辑  收藏  举报