1.为什么使用分片集群
主从和哨兵可以解决高可用、高并发读的问题。但是依然有两个问题没有解决:
- 海量数据存储问题
- 高并发写的问题 哨兵模式本质是依旧是主从模式,在主从模式下我们可以增加
slave
节点来拓展读并发能力,但是没办法扩展写能力和存储能力。
使用分片集群可以解决上述问题,分片集群特征:
- 集群中有多个
master
,每个master
保存不同数据。 - 每个
master
都可以有多个slave
节点。 master
之间通过ping
监测彼此健康状态。- 客户端请求可以访问集群任意节点,最终都会被转发到正确节点。
2.分片集群介绍
分片集群是将多个Redis
主从结构联合起来,每个主从结构具有一个主实例和多个从实例。Redis
的分片集群可以在数据量不断增大的情况下进行水平扩容,将键值放在指定的实例中,以此来降低系统对单主节点的依赖,从而提高Redis
服务的读写性能。
3.散列插槽
Redis
会把每一个master
节点映射到0~16383
共16384
个插槽(hash slot
)上。哈希槽类似于数据分区,每个键值对都会根据它的key
,被映射到一个哈希槽中,具体执行过程分为两大步:
- 根据键值对的
key
,按照CRC16
算法计算一个16bit
的值 - 再用
16bit
值对16384
取模,得到0~16383
范围内的模数,每个模数代表一个相应编号的哈希槽 每个Redis
节点负责处理一部分槽位,假如集群中有master
节点ABC
,每个节点负责的槽位范围如下:
master 节点 | 处理槽位 |
---|---|
A | 0-5460 |
B | 5461-10922 |
C | 10923-16383 |
查看集群信息时就能看到:
注意:**数据key
不是与节点绑定,而是与插槽绑定。**这样绑定的好处是,当集群发生扩容增加节点或者宕机减少了master
节点,Redis
能够更加方便的将插槽转移到仍然存活的节点上,数据跟随插槽转移,使得我们能够找到原本数据所在的位置。
Redis
会根据key
的有效部分计算插槽值,分两种情况:
key
中包含"{}“,且”{}“中至少包含1个字符,”{}"中的部分是有效部分key
中不包含"{}",整个key
都是有效部分
4.搭建分片集群
4.1.集群结构
分片集群需要的节点数量较多,这里我们搭建一个最小的分片集群,包含3个master
节点,每个master
包含一个slave
节点,结构如下:
这里我们会在同一台虚拟机中开启6个redis
实例,模拟分片集群,信息如下:
IP | PORT | 角色 |
---|---|---|
10.0.4.10 | 7001 | master |
10.0.4.10 | 7002 | master |
10.0.4.10 | 7003 | master |
10.0.4.10 | 8001 | slave |
10.0.4.10 | 8002 | slave |
10.0.4.10 | 8003 | slave |
4.2.准备实例和配置
删除之前的7001、7002、7003这几个目录,重新创建出7001、7002、7003、8001、8002、8003目录:
# 进入/home/redis目录
cd /home/redis
# 删除旧的,避免配置干扰
rm -rf 7001 7002 7003
# 创建目录
mkdir 7001 7002 7003 8001 8002 8003
在/home/redis
下准备一个新的redis.conf
文件,内容如下:
port 6379
# 开启集群功能
cluster-enabled yes
# 集群的配置文件名称,不需要我们创建,由redis自己维护
cluster-config-file /home/redis/6379/nodes.conf
# 节点心跳失败的超时时间
cluster-node-timeout 5000
# 持久化文件存放目录
dir /home/redis/6379
# 绑定地址
bind 0.0.0.0
# 让redis后台运行
daemonize yes
# 注册的实例ip
replica-announce-ip 10.0.4.10
# 保护模式
protected-mode no
# 数据库数量
databases 16
# 日志
logfile /home/redis/6379/run.log
将这个文件拷贝到每个目录下:
# 进入/home/redis
cd /home/redis
# 执行拷贝
echo 7001 7002 7003 8001 8002 8003 | xargs -t -n 1 cp redis.conf
修改每个目录下的redis.conf
,将其中的6379修改为与所在目录一致:
# 进入/home/redis目录
cd /home/redis
# 修改配置文件
printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t sed -i 's/6379/{}/g' {}/redis.conf
4.3.启动
因为已经配置了后台启动模式,所以可以直接启动服务:
# 进入/home/redis目录
cd /home/redis
# 一键启动所有服务
printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t redis-server {}/redis.conf
通过ps查看状态:
ps -ef | grep redis
发现服务都已经正常启动:
如果要关闭所有进程,可以执行命令:
ps -ef | grep redis | awk '{print $2}' | xargs kill
或者(推荐这种方式):
printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t redis-cli -p {} shutdown
4.4.创建集群
虽然服务启动了,但是目前每个服务之间都是独立的,没有任何关联。
我们需要执行命令来创建集群,在Redis5.0
之前创建集群比较麻烦,5.0之后集群管理命令都集成到了redis-cli
中。
1)Redis5.0
之前
Redis5.0
之前集群命令都是用redis
安装包下的src/redis-trib.rb
来实现的。因为redis-trib.rb
是有ruby
语言编写的所以需要安装ruby
环境。
# 安装依赖
yum -y install zlib ruby rubygems
gem install redis
然后通过命令来管理集群:
# 进入redis的src目录
cd /home/redis/redis-6.2.4/src
# 创建集群
./redis-trib.rb create --replicas 1 10.0.4.10:7001 10.0.4.10:7002 10.0.4.10:7003 10.0.4.10:8001 10.0.4.10:8002 10.0.4.10:8003
2)Redis5.0
以后
我们使用的是Redis6.2.4
版本,集群管理以及集成到了redis-cli
中,格式如下:
redis-cli --cluster create --cluster-replicas 1 10.0.4.10:7001 10.0.4.10:7002 10.0.4.10:7003 10.0.4.10:8001 10.0.4.10:8002 10.0.4.10:8003
命令说明:
redis-cli --cluster
或者./redis-trib.rb
:代表集群操作命令create
:代表是创建集群--replicas 1
或者--cluster-replicas 1
:指定集群中每个master
的副本个数为1,此时节点总数 ÷ (replicas + 1)
得到的就是master
的数量。因此节点列表中的前n
个就是master
,其它节点都是slave
节点,随机分配到不同master
运行后的样子:
这里询问是否按照上面列出的方式创建集群?如果没有问题,输入yes
,则集群开始创建:
通过命令可以查看集群状态:
redis-cli -p 7001 cluster nodes
4.5.测试
尝试连接7001节点,存储一个数据:
# 连接
redis-cli -p 7001
# 存储数据
set num 123
# 读取数据
get num
# 再次存储
set a 1
结果悲剧了:
集群操作时,需要给redis-cli
加上-c
参数才可以:
redis-cli -c -p 7001
这次可以了: