一个系统运维的打怪升级之路

Redis服务高可用方案 Redis Cluster集群配置

2019-07-05
37次查阅
2019/7/5

本文在两台服务器上配置 6 节点 Redis Cluster,Redis 从 3.0 之后版本支持 redis-cluster 集群,Redis-Cluster 采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接,其结构特点:

  1. 所有的 redis 节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。
  2. 节点的fail是通过集群中超过半数的节点检测失效时才生效。
  3. 客户端与 redis 节点直连,不需要中间 proxy 层。客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
  4. redis-cluster 把所有的物理节点映射到[0-16383]slot上(不一定是平均分配),cluster 负责维护node<->slot<->value
  5. Redis 集群预分好16384个桶,当需要在 Redis 集群中放置一个 key-value 时,根据CRC16(key) mod 16384的值,决定将一个 key 放到哪个桶中。

服务器环境:

192.168.0.3(6001、6002、6003)
192.168.0.4(6004、6005、6006)

每台服务器搭建3个节点,组成3个主节点,3个从节点的redis集群。

安装redis

关闭防火墙和SELinux:

systemctl disable firewalld && systemctl stop firewalld

setenforce 0
sed -i 's/^SELINUX=.*$/SELINUX=disabled/g' /etc/selinux/config

安装系统依赖和更新:

yum install -y gcc g++ gcc-c++ make
yum -y update

两台服务器都编译安装redis:

wget http://download.redis.io/releases/redis-4.0.14.tar.gz
tar zxvf redis-4.0.14.tar.gz && cd redis-4.0.14
make PREFIX=/usr/local/redis-cluster install
mkdir /data/redis-cache
192.168.0.3:
mkdir -p /usr/local/redis-cluster/{6001,6002,6003}
192.168.0.4:
mkdir -p /usr/local/redis-cluster/{6004,6005,6006}

复制配置文件和集群管理工具:

\cp redis.conf /usr/local/redis-cluster/6001             # 复制redis配置文件,依次复制到6个节点对应的目录中
\cp src/redis-trib.rb /usr/local/redis-cluster/          # 集群管理工具

修改redis配置文件,用端口区分配置,修改如下:

vim redis.conf
bind 0.0.0.0                         # 绑定当前服务器的IP
port 6001                            # 端口6001, 6002, 6003 ...
daemonize yes                        # 后台运行
pidfile /var/run/redis_6001.pid      # pidfile文件对应 6001, 6002, 6003 ...
logfile "/data/redis-cache/6001.log" # 日志文件
dbfilename dump_6001.rdb             # 持久化文件
dir /data/redis-cache/               # 持久化路径
masterauth 123456                    # 认证密码
requirepass 123456                   # 设置Redis连接密码
cluster-enabled yes                  # 开启集群
cluster-config-file nodes-6001.conf  # 集群的配置,首次启动自动生成
cluster-node-timeout 5000            # 请求超时,设置5秒
appendonly yes                       # 开启aof持久化方式
appendfilename "appendonly_6001.aof" # 指定aof文件名,此文件存在在 dir 配置的路劲下
cluster-require-full-coverage no     # 只要有结点宕机导致16384个槽没全被覆盖,整个集群就全部停止服务,所以一定要改为no

注意:一共配置6个节点的配置文件,参数用端口号来区分配置。

# 192.168.0.3上启动:
/usr/local/redis-cluster/bin/redis-server /usr/local/redis-cluster/6001/redis.conf
/usr/local/redis-cluster/bin/redis-server /usr/local/redis-cluster/6002/redis.conf
/usr/local/redis-cluster/bin/redis-server /usr/local/redis-cluster/6003/redis.conf

# 192.168.0.4上启动:
/usr/local/redis-cluster/bin/redis-server /usr/local/redis-cluster/6004/redis.conf
/usr/local/redis-cluster/bin/redis-server /usr/local/redis-cluster/6005/redis.conf
/usr/local/redis-cluster/bin/redis-server /usr/local/redis-cluster/6006/redis.conf
# 192.168.0.3上关闭:
/usr/local/redis-cluster/bin/redis-cli -h 192.168.0.3 -a '123456' -p 6001 shutdown
/usr/local/redis-cluster/bin/redis-cli -h 192.168.0.3 -a '123456' -p 6002 shutdown
/usr/local/redis-cluster/bin/redis-cli -h 192.168.0.3 -a '123456' -p 6003 shutdown

# 192.168.0.4上关闭:
/usr/local/redis-cluster/bin/redis-cli -h 192.168.0.4 -a '123456' -p 6004 shutdown
/usr/local/redis-cluster/bin/redis-cli -h 192.168.0.4 -a '123456' -p 6005 shutdown
/usr/local/redis-cluster/bin/redis-cli -h 192.168.0.4 -a '123456' -p 6006 shutdown

或者更方便的关闭方法:

pkill redis

创建集群

前面已经准备好了搭建集群的redis节点,现在搭建这些节点为集群。官方提供了一个工具:redis-trib.rb,它是用ruby写的一个程序,所以需要安装ruby环境,为了方便操作,两台服务器都可以安装。

wget https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.5.tar.gz
tar zxvf ruby-2.5.5.tar.gz && cd ruby-2.5.5
./configure --prefix=/usr/local/ruby
make
make install

ln -s /usr/local/ruby/bin/* /usr/local/bin/

再用gem这个命令来安装 redis 接口,gem是ruby的一个工具包:

gem install redis

因为配置了密码,所以需要修改client.rb文件配置密码,否则redis-trib.rb命令会提示无法连接:

find / -name 'client.rb'
vim /usr/local/ruby/lib/ruby/gems/2.5.0/gems/redis-4.1.2/lib/redis/client.rb
# frozen_string_literal: true

require_relative "errors"
require "socket"
require "cgi"

class Redis
  class Client

    DEFAULTS = {
      :url => lambda { ENV["REDIS_URL"] },
      :scheme => "redis",
      :host => "127.0.0.1",
      :port => 6379,
      :path => nil,
      :timeout => 5.0,
      :password => 123456,     <-- 修改这里
      :db => 0,
      :driver => nil,
      :id => nil,
      :tcp_keepalive => 0,
      :reconnect_attempts => 1,
      :reconnect_delay => 0,
      :reconnect_delay_max => 0.5,
      :inherit_socket => false
    }

确认所有的节点redis都启动后,使用redis-trib.rb create创建(两台机器其中一台配置即可)

/usr/local/redis-cluster/redis-trib.rb create \
--replicas 1 \
192.168.0.3:6001 192.168.0.3:6002 192.168.0.3:6003 \
192.168.0.4:6004 192.168.0.4:6005 192.168.0.4:6006

# --replicas 1 参数表示为每个主节点创建一个从节点。

>>> Creating cluster
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
192.168.0.3:6001
192.168.0.4:6004
192.168.0.3:6002
Adding replica 192.168.0.4:6006 to 192.168.0.3:6001
Adding replica 192.168.0.3:6003 to 192.168.0.4:6004
Adding replica 192.168.0.4:6005 to 192.168.0.3:6002
M: c1fe365b5205ced547f0d478380792e277c15793 192.168.0.3:6001
   slots:0-5460 (5461 slots) master
M: 5606ab8fd7482d8f035e23435c3efb6b0c9087b1 192.168.0.3:6002
   slots:10923-16383 (5461 slots) master
S: a3257f6a5e3ed45f4f52139dea5cef91ffbff47d 192.168.0.3:6003
   replicates 36b96a2e90f7b913c9233e0f0b34a932f37759d5
M: 36b96a2e90f7b913c9233e0f0b34a932f37759d5 192.168.0.4:6004
   slots:5461-10922 (5462 slots) master
S: 430e9d0e3a3742060a23c8f0a976b4e041b90848 192.168.0.4:6005
   replicates 5606ab8fd7482d8f035e23435c3efb6b0c9087b1
S: a61b890b57073442d6587caeca046bb9185f9cdb 192.168.0.4:6006
   replicates c1fe365b5205ced547f0d478380792e277c15793
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 192.168.0.3:6001)
M: c1fe365b5205ced547f0d478380792e277c15793 192.168.0.3:6001
   slots:0-5460 (5461 slots) master
   1 additional replica(s)
S: a61b890b57073442d6587caeca046bb9185f9cdb 192.168.0.4:6006
   slots: (0 slots) slave
   replicates c1fe365b5205ced547f0d478380792e277c15793
S: a3257f6a5e3ed45f4f52139dea5cef91ffbff47d 192.168.0.3:6003
   slots: (0 slots) slave
   replicates 36b96a2e90f7b913c9233e0f0b34a932f37759d5
M: 5606ab8fd7482d8f035e23435c3efb6b0c9087b1 192.168.0.3:6002
   slots:10923-16383 (5461 slots) master
   1 additional replica(s)
M: 36b96a2e90f7b913c9233e0f0b34a932f37759d5 192.168.0.4:6004
   slots:5461-10922 (5462 slots) master
   1 additional replica(s)
S: 430e9d0e3a3742060a23c8f0a976b4e041b90848 192.168.0.4:6005
   slots: (0 slots) slave
   replicates 5606ab8fd7482d8f035e23435c3efb6b0c9087b1
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

集群测试

打开 192.168.0.3 6001 终端,-c连接到集群,-a配置密码:

redis-cli -h 192.168.0.3 -p 6001 -c -a '123456'

查看集群节点

192.168.0.3:6001> CLUSTER NODES
a61b890b57073442d6587caeca046bb9185f9cdb 192.168.0.4:6006@16006 slave c1fe365b5205ced547f0d478380792e277c15793 0 1562308837564 6 connected
a3257f6a5e3ed45f4f52139dea5cef91ffbff47d 192.168.0.3:6003@16003 slave 36b96a2e90f7b913c9233e0f0b34a932f37759d5 0 1562308837060 4 connected
5606ab8fd7482d8f035e23435c3efb6b0c9087b1 192.168.0.3:6002@16002 master - 0 1562308837000 2 connected 10923-16383
36b96a2e90f7b913c9233e0f0b34a932f37759d5 192.168.0.4:6004@16004 master - 0 1562308837061 4 connected 5461-10922
430e9d0e3a3742060a23c8f0a976b4e041b90848 192.168.0.4:6005@16005 slave 5606ab8fd7482d8f035e23435c3efb6b0c9087b1 0 1562308838067 5 connected
c1fe365b5205ced547f0d478380792e277c15793 192.168.0.3:6001@16001 myself,master - 0 1562308836000 1 connected 0-5460

查看集群节点信息

192.168.0.3:6001> CLUSTER INFO
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:425
cluster_stats_messages_pong_sent:415
cluster_stats_messages_sent:840
cluster_stats_messages_ping_received:410
cluster_stats_messages_pong_received:425
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:840

在6001节点 set 一个 key:

192.168.0.3:6001> set url 1987.name
-> Redirected to slot [12521] located at 192.168.0.3:6002
OK

192.168.0.3:6002> GET url
"1987.name"

在 6005 节点 get 这个 key,提示 get url 重定向到 192.168.0.3:6002:

192.168.0.4:6005> GET url
-> Redirected to slot [12521] located at 192.168.0.3:6002
"1987.name"

检查集群状态

./redis-trib.rb check 192.168.0.3:6002                                            
>>> Performing Cluster Check (using node 192.168.0.3:6002)
S: 5606ab8fd7482d8f035e23435c3efb6b0c9087b1 192.168.0.3:6002
   slots: (0 slots) slave
   replicates 430e9d0e3a3742060a23c8f0a976b4e041b90848
S: a3257f6a5e3ed45f4f52139dea5cef91ffbff47d 192.168.0.3:6003
   slots: (0 slots) slave
   replicates 36b96a2e90f7b913c9233e0f0b34a932f37759d5
M: 430e9d0e3a3742060a23c8f0a976b4e041b90848 192.168.0.4:6005
   slots:10923-16383 (5461 slots) master
   1 additional replica(s)
M: 36b96a2e90f7b913c9233e0f0b34a932f37759d5 192.168.0.4:6004
   slots:5461-10922 (5462 slots) master
   1 additional replica(s)
M: c1fe365b5205ced547f0d478380792e277c15793 192.168.0.3:6001
   slots:0-5460 (5461 slots) master
   1 additional replica(s)
S: a61b890b57073442d6587caeca046bb9185f9cdb 192.168.0.4:6006
   slots: (0 slots) slave
   replicates c1fe365b5205ced547f0d478380792e277c15793
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

集群相关命令

语法格式

redis-cli -c -p port

集群

  • cluster info打印集群的信息
  • cluster node列出集群当前已知的所有节点( node),以及这些节点的相关信息。

节点

  • cluster meet <ip> <port>将 ip 和 port 所指定的节点添加到集群当中,让它成为集群的一份子。
  • cluster forget <node_id>从集群中移除 node_id 指定的节点。
  • cluster replicate <node_id>将当前节点设置为 node_id 指定的节点的从节点。
  • cluster saveconfig将节点的配置文件保存到硬盘里面。

槽(slot)

  • cluster addslots <slot> [slot ...]将一个或多个槽( slot)指派( assign)给当前节点。
  • cluster delslots <slot> [slot ...]移除一个或多个槽对当前节点的指派。
  • cluster flushslots移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。
  • cluster setslot <slot> node <node_id>将槽 slot 指派给 node_id 指定的节点,如果槽已经指派给另一个节点,那么先让另一个节点删除该槽>,然后再进行指派。
  • cluster setslot <slot> migrating <node_id>将本节点的槽 slot 迁移到 node_id 指定的节点中。
  • cluster setslot <slot> importing <node_id>从 node_id 指定的节点中导入槽 slot 到本节点。
  • cluster setslot <slot> stable取消对槽 slot 的导入( import)或者迁移( migrate)。


  • cluster keyslot <key>计算键 key 应该被放置在哪个槽上。
  • cluster countkeysinslot <slot>返回槽 slot 目前包含的键值对数量。
  • cluster getkeysinslot <slot> <count>返回 count 个 slot 槽中的键 。

评论

想说点什么?