之前我们所学习的都是 Redis 的单机版,我们知道 Redis 之所以读取速度快是因为它是存储在内存中的。内存的容量是有限的,单台 Redis 会碰到性能瓶颈,这就需要使用 Redis集群(Redis-cluster)
。
一、集群原理
1.1 集群架构
如上图所示,每一个蓝色圆圈就是一个 Redis 节点,这些节点组成了一个 Redis集群(Redis-cluster)
。节点之间使用 Ping——Pong
机制进行互联,其内部用二进制协议优化传输速度和带宽。
Redis客户端和节点直接连接即可,无需中间件,一台客户端连接一个节点即可,Client 访问时直接访问任意一个Redis节点即可。
1.2 负载均衡
当我们搭建了集群后,其是如何实现负载均衡的呢?
Redis 集群中内置了 16384 个哈希槽(slot)
,它会把所有的物理节点都映射到**[0,16383]**的slot上。
当我们需要在Redis集群中放置了个 key-value 时,Redis 先对 key 使用 crc16
算法得出一个结果,然后将结果对16384取余,这样每一个 key 都会对应一个编号在0 ~16383的 哈希槽。
Redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。例如我们有三个节点,其每个节点哈希槽范围为:0 ~ 5000,5001 ~ 10000,10001~ 16383。
当我们存储一个名为 Hello1 的 key 时,其通过 crc16
算法计算出的结果为1500,Redis 集群就会将这个 key 放在对应1500的哈希槽
中,又因为哈希槽0~ 5000被映射到了 Server1,则 Hello1 就被放置在了 Server1。
1.3 容错机制
通过上面的负载均衡的原理,知道其实每一台 Redis 客户端保存的内容都是不一样的,那么当Redis集群中任意一个节点挂掉(连接失败)时,整个集群就挂了。
为了实现 Redis 的高可用,需要为每一个节点添加备用机,即主备机制
。
一般集群都有集群管理工具,但是 Redis 集群没有,它是通过投票机制
来实现的。
以下图为例简单说一下投票机制:
- 当黄色节点发现无法 ping 通红色节点,它就觉得红色节点可能挂掉了,于是它会发起投票。
- 其他节点会尝试去 ping 红色节点,只要有超过半数的节点无法 ping 通红色节点,就判定红色节点挂掉(即使它实际上可能并没有挂掉)。
- 当红色节点被判定挂掉后,会启动该节点的备用机。如果该节点不存在备用机,或备用机也挂掉,那么整个Redis集群就挂掉了。
二、搭建集群
Redis 集群为了实现容错机制,最少需要三个节点(一个出错,另外两个投票),又因为每个节点至少要有一台备份机,因此一个最简单的 Redis 集群需要6个 Redis 客户端。
这里只是演示一下,使用伪集群
,即6台 Redis 搭建在一台 Linux 上,仅使用端口号进行区分,设端口号范围为7001 ~ 7006。
2.1 准备原始 Redis
注:《Redis 初探(1)——Redis 的安装》这篇文章中源码和安装后的文件是在同一文件夹下,本篇文章不使用这种方法。
准备一个 Redis 安装包,将源码解压到当前文件夹:
1 | wxs@ubuntu:~$ ls |
进入解压后文件夹,执行 make 编译:
1 | wxs@ubuntu:~$ cd redis-4.0.8/ |
注:所有源码安装需要自行编译的都需要 gcc、g++ 等相关软件支持
将其安装到/usr/local/redis
目录下:
1 | wxs@ubuntu:~/redis-4.0.8$ sudo make install PREFIX=/usr/local/redis |
该目录下只有一个 bin 目录,存放 redis 的可执行文件,我们从源码包中拷贝一份 redis 配置文件过来:
1 | wxs@ubuntu:/usr/local/redis$ ls |
编辑该配置文件:
(1)修改 bind 端口号为 0.0.0.0
,使其支持远程访问。
(2)开启后端模式。
(3)设置日志文件位置
(4)开启 AOF 持久化
2.2 准备 Redis 集群客户端
注意:用来做集群的客户端必须是干净的客户端,像备份文件 dump.rdb
、appendonly.aof
等应当先删除掉,避免不必要的错误。
在 /usr/local
中创建 redis-cluster
文件夹,拷贝六份原始 Redis:
1 | wxs@ubuntu:/usr/local/redis-cluster$ sudo cp -r ../redis redis01 |
以 redis01 为例,编辑其 redis.conf
文件:
(1)修改端口号为 7001
(2)修改 pidfile
(3)开启集群开关
依次修改其他客户端,端口号范围从7001 ~ 7006。
编写一个启动这些客户端的批处理 startup.sh
:
1 | cd redis01/bin |
执行脚本,启动成功:
编写一个关闭这些客户端的批处理 shutdown.sh
:
1 | cd redis01/bin |
执行脚本,关闭成功:
目录结构如下:
1 | wxs@ubuntu:/usr/local/redis-cluster$ ls |
2.3 搭建集群
从 redis 源码的 src 目录中拷贝 redis-trib.rb
过来:
1 | wxs@ubuntu:/usr/local/redis-cluster$ sudo cp ~/redis-4.0.8/src/redis-trib.rb . |
因为这是一个 shell
文件,需要安装 shell 和 shell 包管理器:
1 | wxs@ubuntu:/usr/local/redis-cluster$ sudo apt-get install shell shellgems |
安装 shell 关于 Redis 的库,可以执行 gem install redis
或者前往官网下载安装包后安装。
1 | wxs@ubuntu:/usr/local/redis-cluster$ sudo gem install redis |
执行 redis-trib.rb
时需要附带参数,格式如下:
先启动所有客户端,然后执行脚本:
1 | wxs@ubuntu:/usr/local/redis-cluster$ ./startup.sh |
创建成功:
最后说两句:
- 如果你不是伪集群,真的在服务器上搭建了集群,即
真集群
,那么只需要在任意一台上执行redis-trib.rb
即可。 - 在真集群的情况下,除了在配置文件中要
bind 0.0.0.0
以外,还要注意关闭防火墙,不然无法搭建。 - 如果关闭所有 redis 客户端后,想要重新开启集群,在客户端都启动后,进入任意客户端执行
cluster nodes
即可。 - 如果想要重新生成集群,需要删除每个 Redis 中生成的持久化文件。
三、使用 redis-cli 连接集群
使用任意一个 redis-cli
(以redis01的为例),使用 -h
指定ip地址(默认连接127.0.0.1),使用 -p
参数指定端口号(默认连接原始的端口为6379的 redis),使用 -c
参数指定是集群(不加会导致无法将 key 放入对应的客户端中)。
1 | wxs@ubuntu:/usr/local/redis-cluster$ ./redis01/bin/redis-cli -h 192.168.30.155 -p 7001 -c |
当我在7001中添加了一个 name jitwxs
后,它计算出 key 的哈希槽为5798,这个范围在7002中,因此这个 key 被移动到了7002中,并且当前连接重定向到了7002。
1 | 192.168.30.155:7002> keys * |