Redis 集群搭建

Posted by 彭楷淳 on 2021-01-27
Estimated Reading Time 6 Minutes
Words 1.7k In Total
Viewed Times

由于主从复制所有的写操作都是先在 Master 上操作,然后同步更新到 Slave 上,所以从 Master 同步到 Slave 机器有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,Slave 机器数量的增加也会使这个问题更加严重。因此我们还需要集群来进一步提升 redis 性能。

集群原理


Redis 集群架构如下图:

img

Redis 集群运行原理如下:

  1. 所有的 Redis 节点彼此互联( PING-PONG 机制),内部使用二进制协议优化传输速度和带宽
  2. 节点的 fail 是通过集群中超过半数的节点检测失效时才生效
  3. 客户端与 Redis 节点直连,不需要中间 proxy 层,客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可
  4. Redis-cluster 把所有的物理节点映射到 [0-16383] slot 上, cluster (簇)负责维护 node<->slot<->value 。Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,Redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,Redis 会根据节点数量大致均等的将哈希槽映射到不同的节点

怎么样投票

投票过程是集群中所有 master 参与,如果半数以上 master 节点与 master 节点通信超过 cluster-node-timeout 设置的时间,认为当前 master 节点挂掉。

怎么样判定节点不可用

  1. 如果集群任意 master 挂掉,且当前 master 没有 slave, 集群进入 fail 状态,也可以理解成集群的 slot 映射 [0-16383] 不完整时进入 fail 状态。
  2. 如果集群超过半数以上 master 挂掉,无论是否有 slave ,集群进入 fail 状态,当集群不可用时,所有对集群的操作做都不可用,收到 ((error) CLUSTERDOWN The cluster is down) 错误。

ruby 环境


Redis 集群管理工具 redis-trib.rb 依赖 ruby 环境,首先需要安装 ruby 环境:

1
2
$ yum install ruby
$ yum install rubygems

集群搭建


首先我们对集群做一个简单规划,假设我的集群中一共有三个节点,每个节点一个主机一个从机,这样我一共需要 6 个 Redis 实例。首先创建 redis-cluster 文件夹,在该文件夹下分别创建 7001、7002、7003、7004、7005、7006 文件夹,用来存放我的 Redis 配置文件。将 Redis 也在 redis-cluster 目录下安装一份,然后将 redis.conf 文件向 7001-7006 这 6 个文件夹中分别拷贝一份,拷贝完成后,分别修改如下参数:

1
2
3
4
5
6
port 7001
#bind 127.0.0.1
cluster-enabled yes
cluster-config-XX XXX7001.conf
protected no
daemonize yes

这是 7001 目录下的配置,其他的文件夹将 7001 改为对应的数字即可。修改完成后,进入到 redis 安装目录中,分别启动各个 redis ,使用刚刚修改过的配置文件。启动成功后,我们可以查看 redis 进程,如下:

1
$ ps -aux|grep redis

这个表示各个节点都启动成功了。接下来我们就可以进行集群的创建了,首先将 redis/src 目录下的 redis-trib.rb 文件拷贝到 redis-cluster 目录下,然后在 redis-cluster 目录下执行如下命令:

1
$ ./redis-trib.rb create --replicas 1 192.168.248.128:7001 192.168.248.128:7002 192.168.248.128:7003 192.168.248.128:7004 192.168.248.128:7005 192.168.248.128:7006

注意:replicas 后面的 1 表示每个主机都带有 1 个从机,执行过程如下:

img

注意创建过程的日志,每个 redis 都获得了一个编号,同时日志也说明了哪些实例做主机,哪些实例做从机,每个从机的主机是谁,每个主机所分配到的 hash 槽范围等等。

查询集群信息


集群创建成功后,我们可以登录到 Redis 控制台查看集群信息,注意登录时要添加 -c 参数,表示以集群方式连接:

1
$ redis-cli -p 7001 -c

进入 Redis 控制台输入命令:

1
127.0.0.1:7001> cluster nodes

添加主节点


首先我们准备一个端口为 7007 的主节点并启动,准备方式和前面步骤一样,启动成功后,通过如下命令添加主节点:

1
$ ./redis-trib.rb add-node  127.0.0.1:7007 127.0.0.1:7001

主节点添加之后,我们可以通过 cluster nodes 命令查看主节点是否添加成功,此时我们发现新添加的节点没有分配到 slot。没有分配到 slot 将不能存储数据,此时我们需要手动分配 slot,分配命令如下:

1
$ ./redis-trib.rb reshard 127.0.0.1:7001

后面的地址为任意一个节点地址,在分配的过程中,我们一共要输入如下几个参数:

  1. 一共要划分多少个 hash 槽出来?就是我们总共要给新添加的节点分多少 hash 槽,这个参数依实际情况而定。

  2. 这些划分出来的槽要给谁,这里输入 7007 节点的编号。

  3. 要让谁出血?因为 hash 槽目前已经全部分配完毕,要重新从已经分好的节点中拿出来一部分给 7007 ,必然要让另外三个节点把吃进去的吐出来,这里我们可以输入多个节点的编号,每次输完一个点击回车,输完所有的输入 done 表示输入完成,这样就让这几个节点让出部分 slot,如果要让所有具有 slot 的节点都参与到此次 slot 重新分配的活动中,那么这里直接输入 all 即可。

OK,主要就是这几个参数,输完之后进入到 slot 重新分配环节,分配完成后,通过 cluster nodes 命令,我们可以发现 7007 已经具有 slot 了,如下:

img

刚刚我们是添加主节点,我们也可以添加从节点,比如我要把 7008 作为 7007 的从节点,添加方式如下:

1
$ ./redis-trib.rb add-node --slave --master-id 79bbb30bba66b4997b9360dd09849c67d2d02bb9  192.168.31.135:7008 192.168.31.135:7007

其中 79bbb30bba66b4997b9360dd09849c67d2d02bb9 是 7007 的编号。

删除节点


删除节点也比较简单,如下:

1
$ ./redis-trib.rb del-node 127.0.0.1:7005 4b45eb75c8b428fbd77ab979b85080146a9bc017

注意:4b45eb75c8b428fbd77ab979b85080146a9bc017 是要删除节点的编号。并且删除已经占有 hash 槽的结点会失败,报错如下:

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

需要将该结点占用的 hash 槽分配出去(分配方式与上文一致,不赘述)。

更多干货请移步:https://antoniopeng.com


If you like this blog or find it useful for you, you are welcome to comment on it. You are also welcome to share this blog, so that more people can participate in it. If the images used in the blog infringe your copyright, please contact the author to delete them. Thank you !