Redis-cluster集群分片

597次阅读
没有评论

共计 12177 个字符,预计需要花费 31 分钟才能阅读完成。

Redis-cluster集群分片

redis cluster简介

redi再3.0前只支持单例模式,3.0之后才支持集群功能。该集群模式每个master节点都是不同的数据,集群模式采用虚拟slots分槽,所有的键根据哈希函数映射到0~16383整数槽内,计算公式:Slot=CRC16(key)&16384。每个节点负责维护一部分槽以及槽所映射的键值数据。如下3分片节点A/B/C:

  • Node A contains hash slots from 0 to 5500.
  • Node B contains hash slots from 5501 to 11000.
  • Node C contains hash slots from 11001 to 16383.

集群模式中的高可用

单例模式下的高可用可以用sentinel来做自动投票选举,而集群模式下不需要sentinel,而是依赖集群中的master角色节点。当集群某分片下slave发现自己的master为FAIL状态时,便开始尝试发起选举:

  1. 某分片slave发现自己的master为FAIL状态
  2. 将自己记录的集群currentEpoch(选举轮次标记)加1,并广播给集群中其他节点
  3. 集群内节点收到该信息后,只有为master的才会响应,判断请求的合法性并响应结果
  4. 该分片slave收集各master的返回结果,收到超半数master的同意后编成新master
  5. 广播Pong消息通知集群内所有节点,每个节点会更新最新的角色信息map配置

集群模式下客户端的访问方式

集群模式下,没有代理提供给客户端,客户端可以通过任意一个节点IP+PORT的方式来调用集群,也可以通过多个节点IP+PORT方式调用:

  • 客户端所请求数据刚好在请求的分片节点slots上时,该分片节点直接返回数据
  • 客户端所请求数据不在请求的分片节点slots上时,该分片节点会返回响应跳转重定位(moved+目标节点),告诉客户端去这个节点请求数据。有点类似nginx上配置了302跳转。业务中调用应当减少跳转重定位,因为这种情况下要多出一次请求链接,客户端中可以将slots的映射关系缓存到本地,并与变化时更新

集群部署

此处博主用单台服务器上部署多个实例来模拟:3主6从(3分片集群,每个分片一个master,2个slave)

配置ruby和依赖

安装ruby

[root@blog ~]# yum -y install ruby ruby-devel rubygems

上面安装ruby后会因版本出问题,需要重新装一个合适的版本

[root@blog ~]# curl -sSL https://rvm.io/pkuczynski.asc | gpg2 --import -
gpg: key 39499BDB: public key "Piotr Kuczynski <piotr.kuczynski@gmail.com>" imported
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)
[root@blog ~]# curl -L get.rvm.io | bash -s stable
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   194  100   194    0     0    200      0 --:--:-- --:--:-- --:--:--   200
100 24535  100 24535    0     0  11264      0  0:00:02  0:00:02 --:--:-- 20377
Downloading https://github.com/rvm/rvm/archive/1.29.12.tar.gz
Downloading https://github.com/rvm/rvm/releases/download/1.29.12/1.29.12.tar.gz.asc
gpg: Signature made Sat 16 Jan 2021 02:46:22 AM CST using RSA key ID 39499BDB
gpg: Good signature from "Piotr Kuczynski <piotr.kuczynski@gmail.com>"
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: 7D2B AF1C F37B 13E2 069D  6956 105B D0E7 3949 9BDB
GPG verified '/usr/local/rvm/archives/rvm-1.29.12.tgz'
Creating group 'rvm'
Installing RVM to /usr/local/rvm/
Installation of RVM in /usr/local/rvm/ is almost complete:

  * First you need to add all users that will be using rvm to 'rvm' group,
    and logout - login again, anyone using rvm will be operating with `umask u=rwx,g=rwx,o=rx`.

  * To start using RVM you need to run `source /etc/profile.d/rvm.sh`
    in all your open shell windows, in rare cases you need to reopen all shell windows.
  * Please do NOT forget to add your users to the rvm group.
     The installer no longer auto-adds root or users to the rvm group. Admins must do this.
     Also, please note that group memberships are ONLY evaluated at login time.
     This means that users must log out then back in before group membership takes effect!
Thanks for installing RVM 🙏
Please consider donating to our open collective to help us maintain RVM.

👉  Donate: https://opencollective.com/rvm/donate

调整ruby版本

# 使用rvm查看ruby可用版本
[root@blog ~]# rvm list known

# 使用rvm安装ruby指定版本
[root@blog ~]# rvm install 2.5.8

# 使用rvm移除先前版本
[root@blog ~]# rvm remove 2.0.0
ruby-2.0.0-p648 - #already gone
Using /usr/local/rvm/gems/ruby-2.5.8

ruby安装redis依赖

[root@blog ~]# gem install redis

准备节点配置文件

创建数据和配置存放目录

[root@blog ~]# mkdir /data/700{0..8}

准备每个实例的redis配置文件

cat >/data/7000/redis.conf<<EOF
port 7000
daemonize yes
pidfile /data/7000/redis.pid
loglevel notice
logfile "/data/7000/redis.log"
dbfilename dump.rdb
dir /data/7000
protected-mode no
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
EOF

cat > /data/7001/redis.conf<<EOF
port 7001
daemonize yes
pidfile /data/7001/redis.pid
loglevel notice
logfile "/data/7001/redis.log"
dbfilename dump.rdb
dir /data/7001
protected-mode no
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
EOF

cat > /data/7002/redis.conf<<EOF
port 7002
daemonize yes
pidfile /data/7002/redis.pid
loglevel notice
logfile "/data/7002/redis.log"
dbfilename dump.rdb
dir /data/7002
protected-mode no
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
EOF

cat > /data/7003/redis.conf<<EOF
port 7003
daemonize yes
pidfile /data/7003/redis.pid
loglevel notice
logfile "/data/7003/redis.log"
dbfilename dump.rdb
dir /data/7003
protected-mode no
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
EOF

cat > /data/7004/redis.conf<<EOF
port 7004
daemonize yes
pidfile /data/7004/redis.pid
loglevel notice
logfile "/data/7004/redis.log"
dbfilename dump.rdb
dir /data/7004
protected-mode no
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
EOF

cat > /data/7005/redis.conf<<EOF
port 7005
daemonize yes
pidfile /data/7005/redis.pid
loglevel notice
logfile "/data/7005/redis.log"
dbfilename dump.rdb
dir /data/7005
protected-mode no
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
EOF

cat > /data/7006/redis.conf<<EOF
port 7006
daemonize yes
pidfile /data/7006/redis.pid
loglevel notice
logfile "/data/7006/redis.log"
dbfilename dump.rdb
dir /data/7006
protected-mode no
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
EOF

cat > /data/7007/redis.conf<<EOF
port 7007
daemonize yes
pidfile /data/7007/redis.pid
loglevel notice
logfile "/data/7006/redis.log"
dbfilename dump.rdb
dir /data/7007
protected-mode no
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
EOF

cat > /data/7008/redis.conf<<EOF
port 7008
daemonize yes
pidfile /data/7008/redis.pid
loglevel notice
logfile "/data/7008/redis.log"
dbfilename dump.rdb
dir /data/7008
protected-mode no
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
EOF

启动所有实例

# 启动所有实例
[root@blog ~]# redis-server /data/7000/redis.conf 
[root@blog ~]# redis-server /data/7001/redis.conf 
[root@blog ~]# redis-server /data/7002/redis.conf 
[root@blog ~]# redis-server /data/7003/redis.conf 
[root@blog ~]# redis-server /data/7004/redis.conf 
[root@blog ~]# redis-server /data/7005/redis.conf
[root@blog ~]# redis-server /data/7006/redis.conf
[root@blog ~]# redis-server /data/7007/redis.conf
[root@blog ~]# redis-server /data/7008/redis.conf

# 查看实例允许装状态
[root@blog ~]# ps -ef |grep redis
root       3315      1  0 23:15 ?        00:00:00 redis-server *:7000 [cluster]
root       3317      1  0 23:15 ?        00:00:00 redis-server *:7001 [cluster]
root       3323      1  0 23:15 ?        00:00:00 redis-server *:7002 [cluster]
####### 略

使用redis-trib.rb初始化集群

# 注意这里--replicas 2,代表每个分片有2个slave
[root@blog ~]# redis-trib.rb create --replicas 2 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006 127.0.0.1:7007 127.0.0.1:7008
>>> Creating cluster
>>> Performing hash slots allocation on 9 nodes...
Using 3 masters:
127.0.0.1:7000
127.0.0.1:7001
127.0.0.1:7002
Adding replica 127.0.0.1:7003 to 127.0.0.1:7000
Adding replica 127.0.0.1:7004 to 127.0.0.1:7000
Adding replica 127.0.0.1:7005 to 127.0.0.1:7001
Adding replica 127.0.0.1:7006 to 127.0.0.1:7001
Adding replica 127.0.0.1:7007 to 127.0.0.1:7002
Adding replica 127.0.0.1:7008 to 127.0.0.1:7002
M: 661ee09e9b2b01bc0630b20ab2a9aed5e9eab8ea 127.0.0.1:7000
   slots:0-5460 (5461 slots) master
M: b7fbfbcdb17e31246e89b69f4e0261fbc417d3b1 127.0.0.1:7001
   slots:5461-10922 (5462 slots) master
M: e00fe07d6394f5b8e3dad2619a4e998394ca13ad 127.0.0.1:7002
   slots:10923-16383 (5461 slots) master
S: 4147647eae7ad8818729ae669f203138db3b3c96 127.0.0.1:7003
   replicates 661ee09e9b2b01bc0630b20ab2a9aed5e9eab8ea
S: 9c45df73cd2ecdc0186e73aae89a5773ef3971b8 127.0.0.1:7004
   replicates 661ee09e9b2b01bc0630b20ab2a9aed5e9eab8ea
S: a9fc1c5bc41e3b066ff2dc9e9f902de432969f34 127.0.0.1:7005
   replicates b7fbfbcdb17e31246e89b69f4e0261fbc417d3b1
S: e1c7aee712563b1fc9e1977d54d60ce171c89abf 127.0.0.1:7006
   replicates b7fbfbcdb17e31246e89b69f4e0261fbc417d3b1
S: 1961aba797f12a5f58ca727ba6cd0f427cca00c3 127.0.0.1:7007
   replicates e00fe07d6394f5b8e3dad2619a4e998394ca13ad
S: dba0b21206eb18aac23c74471c32fd2360a43a38 127.0.0.1:7008
   replicates e00fe07d6394f5b8e3dad2619a4e998394ca13ad
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join..
>>> Performing Cluster Check (using node 127.0.0.1:7000)
M: 661ee09e9b2b01bc0630b20ab2a9aed5e9eab8ea 127.0.0.1:7000
   slots:0-5460 (5461 slots) master
   2 additional replica(s)
S: dba0b21206eb18aac23c74471c32fd2360a43a38 127.0.0.1:7008
   slots: (0 slots) slave
   replicates e00fe07d6394f5b8e3dad2619a4e998394ca13ad
S: a9fc1c5bc41e3b066ff2dc9e9f902de432969f34 127.0.0.1:7005
   slots: (0 slots) slave
   replicates b7fbfbcdb17e31246e89b69f4e0261fbc417d3b1
S: 4147647eae7ad8818729ae669f203138db3b3c96 127.0.0.1:7003
   slots: (0 slots) slave
   replicates 661ee09e9b2b01bc0630b20ab2a9aed5e9eab8ea
S: 9c45df73cd2ecdc0186e73aae89a5773ef3971b8 127.0.0.1:7004
   slots: (0 slots) slave
   replicates 661ee09e9b2b01bc0630b20ab2a9aed5e9eab8ea
M: e00fe07d6394f5b8e3dad2619a4e998394ca13ad 127.0.0.1:7002
   slots:10923-16383 (5461 slots) master
   2 additional replica(s)
S: e1c7aee712563b1fc9e1977d54d60ce171c89abf 127.0.0.1:7006
   slots: (0 slots) slave
   replicates b7fbfbcdb17e31246e89b69f4e0261fbc417d3b1
S: 1961aba797f12a5f58ca727ba6cd0f427cca00c3 127.0.0.1:7007
   slots: (0 slots) slave
   replicates e00fe07d6394f5b8e3dad2619a4e998394ca13ad
M: b7fbfbcdb17e31246e89b69f4e0261fbc417d3b1 127.0.0.1:7001
   slots:5461-10922 (5462 slots) master
   2 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

查看集群状态

查看节点信息

[root@blog ~]# redis-cli -p 7000 cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:9
cluster_size:3
cluster_current_epoch:9
cluster_my_epoch:1
cluster_stats_messages_sent:1240
cluster_stats_messages_received:1240

master节点状态

[root@blog ~]# redis-cli -p 7000 cluster nodes | grep master
661ee09e9b2b01bc0630b20ab2a9aed5e9eab8ea 127.0.0.1:7000 myself,master - 0 0 1 connected 0-5460
e00fe07d6394f5b8e3dad2619a4e998394ca13ad 127.0.0.1:7002 master - 0 1675077063725 3 connected 10923-16383
b7fbfbcdb17e31246e89b69f4e0261fbc417d3b1 127.0.0.1:7001 master - 0 1675077062215 2 connected 5461-10922

slave节点状态

[root@blog ~]# redis-cli -p 7000 cluster nodes | grep slave
dba0b21206eb18aac23c74471c32fd2360a43a38 127.0.0.1:7008 slave e00fe07d6394f5b8e3dad2619a4e998394ca13ad 0 1675077081853 9 connected
a9fc1c5bc41e3b066ff2dc9e9f902de432969f34 127.0.0.1:7005 slave b7fbfbcdb17e31246e89b69f4e0261fbc417d3b1 0 1675077081350 6 connected
4147647eae7ad8818729ae669f203138db3b3c96 127.0.0.1:7003 slave 661ee09e9b2b01bc0630b20ab2a9aed5e9eab8ea 0 1675077082860 4 connected
9c45df73cd2ecdc0186e73aae89a5773ef3971b8 127.0.0.1:7004 slave 661ee09e9b2b01bc0630b20ab2a9aed5e9eab8ea 0 1675077081854 5 connected
e1c7aee712563b1fc9e1977d54d60ce171c89abf 127.0.0.1:7006 slave b7fbfbcdb17e31246e89b69f4e0261fbc417d3b1 0 1675077081854 7 connected
1961aba797f12a5f58ca727ba6cd0f427cca00c3 127.0.0.1:7007 slave e00fe07d6394f5b8e3dad2619a4e998394ca13ad 0 1675077082860 8 connected

集群完整性检测

# 只要存在一个slots未分配,则会出错
[root@blog ~]# redis-trib.rb check 127.0.0.1:7000
>>> Performing Cluster Check (using node 127.0.0.1:7000)
M: 661ee09e9b2b01bc0630b20ab2a9aed5e9eab8ea 127.0.0.1:7000
   slots:0-5460 (5461 slots) master
   2 additional replica(s)
S: dba0b21206eb18aac23c74471c32fd2360a43a38 127.0.0.1:7008
   slots: (0 slots) slave
   replicates e00fe07d6394f5b8e3dad2619a4e998394ca13ad
S: a9fc1c5bc41e3b066ff2dc9e9f902de432969f34 127.0.0.1:7005
   slots: (0 slots) slave
   replicates b7fbfbcdb17e31246e89b69f4e0261fbc417d3b1
S: 4147647eae7ad8818729ae669f203138db3b3c96 127.0.0.1:7003
   slots: (0 slots) slave
   replicates 661ee09e9b2b01bc0630b20ab2a9aed5e9eab8ea
S: 9c45df73cd2ecdc0186e73aae89a5773ef3971b8 127.0.0.1:7004
   slots: (0 slots) slave
   replicates 661ee09e9b2b01bc0630b20ab2a9aed5e9eab8ea
M: e00fe07d6394f5b8e3dad2619a4e998394ca13ad 127.0.0.1:7002
   slots:10923-16383 (5461 slots) master
   2 additional replica(s)
S: e1c7aee712563b1fc9e1977d54d60ce171c89abf 127.0.0.1:7006
   slots: (0 slots) slave
   replicates b7fbfbcdb17e31246e89b69f4e0261fbc417d3b1
S: 1961aba797f12a5f58ca727ba6cd0f427cca00c3 127.0.0.1:7007
   slots: (0 slots) slave
   replicates e00fe07d6394f5b8e3dad2619a4e998394ca13ad
M: b7fbfbcdb17e31246e89b69f4e0261fbc417d3b1 127.0.0.1:7001
   slots:5461-10922 (5462 slots) master
   2 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

redis-cli测试使用

# 向集群7000这个实例写入数据,返回了moved
[root@blog ~]# redis-cli -p 7000 set name 'xadocker'
(error) MOVED 5798 127.0.0.1:7001
[root@blog ~]# redis-cli -p 7000 get name
(error) MOVED 5798 127.0.0.1:7001

# 该数据并未自动写入7001实例,说明节点并不会将请求代理到真正的节点上写入
# 而是客户端自行重新再发起请求
[root@blog ~]# redis-cli -p 7001 get name
(nil)

# 客户端只能再次发起请求到7001写入数据
[root@blog ~]# redis-cli -p 7001 set name 'xadocker'
OK
[root@blog ~]# redis-cli -p 7001 get name
"xadocker"

# redis-cli使用-c参数开启跟随move和ask
#  -c                 Enable cluster mode (follow -ASK and -MOVED redirections).
[root@blog ~]# redis-cli -p 7000 set name 'xadocker'
(error) MOVED 5798 127.0.0.1:7001
[root@blog ~]# redis-cli -p 7000 -c set name 'xadocker'
OK
[root@blog ~]# redis-cli -p 7000 -c get name
"xadocker"

正文完
 
xadocker
版权声明:本站原创文章,由 xadocker 2020-06-26发表,共计12177字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)