centos7.4 搭建 redis3 集群与实践
Redis Cluster 集群
redis-cluster 设计
Redis 集群搭建的方式有多种,例如使用 zookeeper 等,但从 redis 3.0 之后版本支持 redis-cluster 集群,Redis-Cluster 采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接。其 redis-cluster 架构图如下:
其结构特点:
-
所有的 redis 节点彼此互联(PING-PONG 机制),内部使用二进制协议优化传输速度和带宽。
-
节点的 fail 是通过集群中超过半数的节点检测失效时才生效。
-
客户端与 redis 节点直连,不需要中间 proxy 层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
-
redis-cluster 把所有的物理节点映射到[0-16383]slot 上(不一定是平均分配),cluster 负责维护 node<->slot<->value。
-
Redis 集群预分好 16384 个桶,当需要在 Redis 集群中放置一个 key-value 时,根据 CRC16(key) mod 16384 的值,决定将一个 key 放到哪个桶中。
redis cluster 节点分配
现在我们是三个主节点分别是:A, B, C 三个节点,它们可以是一台机器上的三个端口,也可以是三台不同的服务器。那么,采用哈希槽 (hash slot)的方式来分配 16384 个 slot 的话,它们三个节点分别承担的 slot 区间是:
节点A覆 盖0-5460; 节点B覆盖5461-10922; 节点C覆盖10923-16383.
获取数据:
如果存入一个值,按照 redis cluster 哈希槽的算法: CRC16('key')%16384 = 6782。 那么就会把这个 key 的存储分配到 B 上了。同样,当我连接(A,B,C)任何一个节点想获取'key'这个 key 时,也会这样的算法,然后内部跳转到 B 节点上获取数据
新增一个主节点:
新增一个节点 D,redis cluster 的这种做法是从各个节点的前面各拿取一部分 slot 到 D 上,我会在接下来的实践中实验。大致就会变成这样:
节点A覆盖1365-5460 节点B覆盖6827-10922 节点C覆盖12288-16383 节点D覆盖0-1364,5461-6826,10923-12287
同样删除一个节点也是类似,移动完成后就可以删除这个节点了。
Redis Cluster 主从模式
redis cluster 为了保证数据的高可用性,加入了主从模式,一个主节点对应一个或多个从节点,主节点提供数据存取,从节点则是从主节点拉取数据备份,当这个主节点挂掉后,就会有这个从节点选取一个来充当主节点,从而保证集群不会挂掉。
上面那个例子里, 集群有 ABC 三个主节点, 如果这 3 个节点都没有加入从节点,如果 B 挂掉了,我们就无法访问整个集群了。A 和 C 的 slot 也无法访问。
所以我们在集群建立的时候,一定要为每个主节点都添加了从节点, 比如像这样, 集群包含主节点 A、B、C, 以及从节点 A1、B1、C1, 那么即使 B 挂掉系统也可以继续正确工作。
B1 节点替代了 B 节点,所以 Redis 集群将会选择 B1 节点作为新的主节点,集群将会继续正确地提供服务。 当 B 重新开启后,它就会变成 B1 的从节点。
不过需要注意,如果节点 B 和 B1 同时挂了,Redis 集群就无法继续正确地提供服务了。
redis 集群的搭建
集群中至少应该有奇数个节点,所以至少有三个节点,每个节点至少有一个备份节点,所以下面使用 6 节点(主节点、备份节点由 redis-cluster 集群确定)。
下面使用 redis-3.2.11 安装,下载地址
wget http://download.redis.io/releases/redis-3.2.11.tar.gz
1. 安装 redis 节点指定端口
解压 redis 压缩包,编译安装
tar zxvf redis-3.2.11.tar.gz cd redis-3.2.11 make make install PREFIX=/usr/local/rediscluster
我们采用 3 台 redis 服务器,每台一个主节点,端口 6380,一个从节点,端口 6381
在/usr/local/rediscluster 目录下建立 6380,6381 两个文件夹
放入 redis.conf 配置文件
vim /usr/local/rediscluster/6380/redis.conf daemonize yes pidfile /usr/local/rediscluster/6380/6380.pid port 6380 logfile "/usr/local/rediscluster/6380/6380.log" #注释掉以下信息,不需要RDB持久化 #save 900 1 #save 300 10 #save 60 10000 #更改以下参数 appendonly yes appendfilename "appendonly-6380.aof" #取消以下参数注释,使redis工作在集群模式下 #启动cluster模式 cluster-enabled yes #集群信息文件名。由redis自己维护 cluster-config-file nodes-6380.conf #15秒联系不到对方的node,即认为对方有故障可能 cluster-node-timeout 15000 bind 192.168.31.109
vim /usr/local/rediscluster/6381/redis.conf daemonize yes pidfile /usr/local/rediscluster/6381/6381.pid port 6381 logfile "/usr/local/rediscluster/6381/6381.log" #注释掉以下信息,不需要RDB持久化 #save 900 1 #save 300 10 #save 60 10000 #更改以下参数 appendonly yes appendfilename "appendonly-6381.aof" #取消以下参数注释,使redis工作在集群模式下 #启动cluster模式 cluster-enabled yes #集群信息文件名。由redis自己维护 cluster-config-file nodes-6381.conf #15秒联系不到对方的node,即认为对方有故障可能 cluster-node-timeout 15000 bind 192.168.31.109
启动 2 个节点
/usr/local/rediscluster/bin/redis-server /usr/local/rediscluster/6380/redis.conf /usr/local/rediscluster/bin/redis-server /usr/local/rediscluster/6381/redis.conf
增加开机启动:
chmod +x /etc/rc.d/rc.local vim /etc/rc.d/rc.local /usr/local/rediscluster/bin/redis-server /usr/local/rediscluster/6380/redis.conf /usr/local/rediscluster/bin/redis-server /usr/local/rediscluster/6381/redis.conf
在其他 2 台电脑上,重复上面操作。
安装 redis-trib 所需的 ruby 脚本
复制 redis 解压文件 src 下的 redis-trib.rb 文件到 redis-cluster 目录
cp /usr/local/src/redis-3.2.11/src/redis-trib.rb /usr/local/rediscluster/bin/
安装 ruby 环境:
yum install rubygems gem install reids
报如下错误:提示 ruby 版本需要大于 2.2.2 版本。CentOS7 yum 库中 ruby 的版本支持到 2.0.0,可 gem 安装 redis 需要最低是 2.2.2
[root@redis1 bin]# gem install reids ERROR: Could not find a valid gem 'reids' (>= 0) in any repository ERROR: Possible alternatives: reid, reins
需要安装个高版本的 ruby
#安装curl yum install curl #安装rvm #gpg2 --keyserver hkp://keys.gnupg.net --recv-keys D39DC0E3 #curl -L get.rvm.io | bash -s stable #source /usr/local/rvm/scripts/rvm
查看 rvm 库中已知的 ruby 版本
rvm list known
安装一个 ruby 版本
rvm install 2.4.0
使用一个 ruby 版本
rvm use 2.4.0
卸载一个已知版本
rvm remove 2.0.0
查看现在版本
ruby --version
在重新安装 ruby 相关的 redis 就可以了
gem install redis [root@redis1 bin]# gem install redis Successfully installed redis-3.2.2 Parsing documentation for redis-3.2.2 Installing ri documentation for redis-3.2.2 Done installing documentation for redis after 1 seconds 1 gem installed
配置集群
[root@redis1 bin]# ./redis-trib.rb create --replicas 1 192.168.31.157:6380 192.168.31.157:6381 192.168.31.158:6380 192.168.31.158:6381 192.168.31.159:6380 192.168.31.159:6381 >>> Creating cluster >>> Performing hash slots allocation on 6 nodes... Using 3 masters: 192.168.31.157:6380 192.168.31.158:6380 192.168.31.159:6380 Adding replica 192.168.31.158:6381 to 192.168.31.157:6380 Adding replica 192.168.31.157:6381 to 192.168.31.158:6380 Adding replica 192.168.31.159:6381 to 192.168.31.159:6380 M: 82cddb744765cb7edd5ba182edb453af87fa69af 192.168.31.157:6380 slots:0-5460 (5461 slots) master S: 5b9a7ec39b05b50cd4753c41b4ebbf9ca5f78dc4 192.168.31.157:6381 replicates 7f85ed61f882f7e2af46cf46b8f3875bd9822335 M: 7f85ed61f882f7e2af46cf46b8f3875bd9822335 192.168.31.158:6380 slots:5461-10922 (5462 slots) master S: 5cacf567ab7ab593b48e3c503f4f4bde7d70094f 192.168.31.158:6381 replicates 82cddb744765cb7edd5ba182edb453af87fa69af M: b3d6fefba1719ecc0d52f39179c327a9e7757e46 192.168.31.159:6380 slots:10923-16383 (5461 slots) master S: 2e0e02da4eda74bd4e5e908e4ec6abdaf02afaa7 192.168.31.159:6381 replicates b3d6fefba1719ecc0d52f39179c327a9e7757e46 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.31.157:6380) M: 82cddb744765cb7edd5ba182edb453af87fa69af 192.168.31.157:6380 slots:0-5460 (5461 slots) master 1 additional replica(s) S: 5cacf567ab7ab593b48e3c503f4f4bde7d70094f 192.168.31.158:6381 slots: (0 slots) slave replicates 82cddb744765cb7edd5ba182edb453af87fa69af M: b3d6fefba1719ecc0d52f39179c327a9e7757e46 192.168.31.159:6380 slots:10923-16383 (5461 slots) master 1 additional replica(s) M: 7f85ed61f882f7e2af46cf46b8f3875bd9822335 192.168.31.158:6380 slots:5461-10922 (5462 slots) master 1 additional replica(s) S: 2e0e02da4eda74bd4e5e908e4ec6abdaf02afaa7 192.168.31.159:6381 slots: (0 slots) slave replicates b3d6fefba1719ecc0d52f39179c327a9e7757e46 S: 5b9a7ec39b05b50cd4753c41b4ebbf9ca5f78dc4 192.168.31.157:6381 slots: (0 slots) slave replicates 7f85ed61f882f7e2af46cf46b8f3875bd9822335 [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.
处理如下警告:
911:M 03 Apr 22:54:21.738 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128. vim /etc/sysctl.conf net.core.somaxconn= 1024 911:M 03 Apr 22:54:21.738 # Server started, Redis version 3.2.11 911:M 03 Apr 22:54:21.738 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect. vim /etc/sysctl.conf vm.overcommit_memory = 1 911:M 03 Apr 22:54:21.738 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled. vim /etc/rc.loacl echo never > /sys/kernel/mm/transparent_hugepage/enabled
redis 集群维护
先使用 create 参数 再加--replicas 后面接上数字,表示一个主需要几个从
集群一般需要 3 个主节点以上(包括 3 个)
./redis-trib.rb create --replicas 1 192.168.1.12:9000 192.168.1.12:9001 192.168.1.12:9002 192.168.1.12:9003 192.168.1.12:9004 192.168.1.12:9005
检查集群状态
./redis-trib.rb check 192.168.1.12:9000
./redis-cli -c -p 9000 表示以集群的方式连接 redis,如果这个节点上没有我需要的数据,它内部会实现 move 跳转,在集群里查找我的数据。
CLUSTER INFO
打印出集群信息
添加节点
在创建集群的时候,全部的插槽 16384 以平均分配了,所以在添加新的主节点的时候需要重新分配插槽,并转移插槽的数据,有两种方式
一:利用 redis-trib.rb 这个工具批量默认转移。
二:手动,cluster 这个命令,一个插槽一个 key 这样转移。
我果断用第一种
添加步骤:
- 先启动需要添加的节点服务,在上面创建的时候我们默认一个主一个从的方式,所以至少是两个节点,
- 利用 redis-trib.rb 执行集群添加节点
./redis-trib.rb add-node 192.168.1.12:9006 192.168.1.12:9000
192.168.1.12:9006 为新添加的节点
192.168.1.12:9000 为集群中任意一个老节点
它这里需要一个身份验证,添加的节点默认为主节点
3. 为新的主节点添加从节点
./redis-trib.rb add-node --slave --master-id
03ccad2ba5dd1e062464bc7590400441fafb63f2 192.168.1.12:9007 192.168.1.12:9000
--slave 表示添加的是从节点
--master-id 03ccad2ba5dd1e062464bc7590400441fafb63f2,主节点的 nodeid,这个 id 是刚才 192.168.1.12:9006 的 nodeid
192.168.1.12:9007 新节点
192.168.1.12:9000 为集群中任意一个老节点
4. 为添加的主节点分配插槽(slot)
./redis-trib.rb reshard 192.168.1.12:9000
reshard 表示重新分配 slot
192.168.1.12:9000 为集群中任意一个老节点
接下来就是交互式操作,根据提示操作就行了
5. 检查集群状态
./redis-trib.rb check 192.168.1.12:9000
192.168.1.12:9000 为集群中任意一个老节点
删除节点
同理,先转移要删除节点上的插槽,再执行
./redis-trib.rb del-node 192.168.1.12:9006
192.168.1.12:9006 要删除的节点
参考资料:
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于