Redis从入门到精通(十五)Redis分布式缓存(三)Redis分片集群的搭建和原理分析

前言

Redis分布式缓存系列文章:

Redis从入门到精通(十三)Redis分布式缓存(一)RDB和AOF持久化、Redis主从集群的搭建与原理分析
Redis从入门到精通(十四)Redis分布式缓存(二)Redis哨兵集群的搭建和原理分析

5.4 分片集群

主从和哨兵可以解决高可用、高并发读的问题,但是依然有两个问题没有解决:海量数据存储问题、高并发写的问题。这两个问题可以通过分片集群来解决。

5.4.1 搭建分片集群

分片集群需要的节点数量较多,这里我们搭建一个最小的分片集群,包含3个master节点,每个master包含1个slave节点,实际上master节点及其slave节点的数量可以更多。其结构如下:

在同一台虚拟机开启6个Redis实例,模拟分片集群,其信息如下:

IP端口角色
192.168.146.1288001master
192.168.146.1288002master
192.168.146.1288003master
192.168.146.1289001slave
192.168.146.1289002slave
192.168.146.1289003slave

搭建步骤如下:

  • 1)在/usr/local/redis_sharding中创建6个目录,名字分别是8001、8002、8003、9001、9002、9003:

  • 2)在6个目录下分别创建配置文件redis.conf,其内容如下(以8001为例,其余端口应与所在目录一致):
# /usr/local/redis_sharding/8001/redis.conf

# 端口
port 8001
# 开启集群功能
cluster-enabled yes
# 集群的配置文件名称,不需要我们创建,由redis自己维护
cluster-config-file /usr/local/redis_sharding/8001/nodes.conf
# 节点心跳失败的超时时间
cluster-node-timeout 5000
# 持久化文件存放目录
dir /usr/local/redis_sharding/8001
# 绑定地址
bind 0.0.0.0
# 让redis后台运行
daemonize yes
# 注册的实例ip
replica-announce-ip 192.168.146.128
# 保护模式
protected-mode no
# 数据库数量
databases 1
# 日志
logfile /usr/local/redis_sharding/8001/run.log
  • 3)在6个目录下分别启动服务
/usr/local/bin/redis-server /usr/local/redis_sharding/8001/redis.conf
/usr/local/bin/redis-server /usr/local/redis_sharding/8002/redis.conf
/usr/local/bin/redis-server /usr/local/redis_sharding/8003/redis.conf
/usr/local/bin/redis-server /usr/local/redis_sharding/9001/redis.conf
/usr/local/bin/redis-server /usr/local/redis_sharding/9002/redis.conf
/usr/local/bin/redis-server /usr/local/redis_sharding/9003/redis.conf

6个实例启动后,其进程如下:

  • 4)创建集群

虽然服务启动了,但是目前每个服务之间都是独立的,没有任何关联,还需要执行命令来创建集群。

Redis5.0之前集群命令都是用redis安装包下的src/redis-trib.rb来实现的。案例使用的是Redis7.2.4版本,集群管理已经集成到了redis-cli中,格式如下:

redis-cli --cluster create --cluster-replicas 1 192.168.146.128:8001 192.168.146.128:8002 192.168.146.128:8003 192.168.146.128:9001 192.168.146.128:9002 192.168.146.128:
9003

命令说明:

  • redis-cli --cluster:集群操作命令

  • create:创建集群

  • --cluster-replicas 1:指定集群中每个master的slave节点个数为1,那么节点总数÷(replicas + 1)得到的就是master的数量。

    本例中即6÷(1 + 1)=3,因此上述命令列出的节点列表中的前3个就是master节点(8001、8002、8003),其他节点都是slave节点,随机分配到不同的master。

命令执行后:

可见,9002分配给了8001,9003分配给了8002,9001分配给了8003。输入yes继续执行:

集群创建完成。通过以下命令查看集群状态:

redis-cli -p 8001 cluster nodes

  • 5)测试

尝试连接8001节点,并存储一个数据:

redis-cli -p 8001

127.0.0.1:8001> set age 21
OK
127.0.0.1:8001> get age
"21"
127.0.0.1:8001> set name aaa
(error) MOVED 5798 192.168.146.128:8002

可以发现,测试过程中出现了错误,提示我们要去8002节点操作。

实际上在进行集群操作时,需要给redis-cli命令加上-c参数:

127.0.0.1:8001> set name aaaaaa
-> Redirected to slot [5798] located at 192.168.146.128:8002
OK
192.168.146.128:8002> get name
"aaaaaa"

5.4.2 散列插槽

Redis会把每一个master节点映射到0~16383共16384个插槽上,在创建集群时就可以看到具体的分配情况:

Redis会根据Key值的有效部分计算插槽值(利用CRC16算法得到一个hash值,然后对16384取余,得到的结果就是插槽值),然后将数据存到插槽值对应的master节点上。 Key值的有效部分分两种情况:

  • Key中包含"{}",且“{}”中至少包含1个字符,则“{}”中的部分是有效部分;
  • key中不包含“{}”,整个key都是有效部分。

例如:

127.0.0.1:8001> set test aaa
-> Redirected to slot [6918] located at 192.168.146.128:8002
OK

在8001节点上执行set test aaa时,对test进行插槽值计算得到的结果是6918,因此要存储到8002节点上。

127.0.0.1:8003> get test
-> Redirected to slot [6918] located at 192.168.146.128:8002
"aaa"

在8003节点上执行get test时,也要根据插槽值去8002节点上查找。

5.4.3 集群伸缩

Redis提供了很多操作集群的命令,可以通过redis-cli --cluster help命令查看具体有哪些。

5.4.3.1 需求分析

现在有一个需求:向集群中添加一个新的master节点,并向其中存储test=bbb。

换句话说,就是添加一个新的master节点到集群中,并将部分插槽分配到给新的master节点。

5.4.3.2 创建新的Redis实例

/usr/local/redis_sharding目录下创建文件夹8004,并拷贝配置文件redis.conf,将其中的端口、目录等配置修改为8004:

启动8004节点:

/usr/local/bin/redis-server /usr/local/redis_sharding/8004/redis.conf

5.4.3.3 添加新节点到Redis集群

执行以下命令:

redis-cli --cluster add-node 192.168.146.128:8004 192.168.146.128:8001

查看集群状态:

redis-cli -p 8001 cluster nodes

如图,8004节点加入了集群,并且是一个master节点,但是其插槽数量为0,因此没有任何数据可以保存到8004节点上。

5.4.3.4 转移插槽

由前面的测试可知,Key值为"test"时其插槽值为6918,我们可以将5461~7461共2000个插槽由8002转移到8004,其命令格式为:

具体的操作步骤如下:

执行以下命令:

redis-cli --cluster reshard 192.168.146.128:8001

得到如下反馈:

询问要移动多少个插槽,我们计划是2000个:

询问要使用哪个节点来接收这些插槽,我们计划是8004节点,因此这里输入8004节点的ID:

询问要从哪个节点移动这些插槽,我们计划是8002节点,因此这里输入8002节点的ID:

如果这里没有输入8002节点的ID,而是输入all,则代表从全部master节点中各移动一部分。

然后再输入done,完成插槽移动的准备工作:

询问是否确认转移,输入yes,开始执行插槽的移动。移动完成后,再次查看集群的状态:

可见,插槽5461~7460以从8002节点移动到了8004节点。

下面进行测试:

127.0.0.1:8001> set test bbb
-> Redirected to slot [6918] located at 192.168.146.128:8004
OK

可见,数据已成功保存到8004节点,需求成功实现。

5.4.4 故障转移

目前,8001、8002、8003、8004都是master节点,如果其中一个实例宕机,会发生什么呢?

5.4.4.1 自动故障转移

执行以下命令,停止8002实例:

redis-cli -p 8002 shutdown

再查询集群状态,集群已识别到8002宕机,并把9001实例提升为master:

当8002再次启动时,自动成为slave节点:

5.4.4.2 手动故障转移

在某个slave节点上执行cluster failover命令,可以手动让集群中的某个master节点宕机,然后自己提升为master节点,实现无感知的数据迁移。

例如,在进行自动故障转移时,8002节点成为了slave节点。我们可以在8002节点上执行cluster failover命令,就可以重新夺回master的地位。

127.0.0.1:8002> cluster failover
OK

查看集群状态:

可见,8002节点重新夺回master地位,9001节点降为slave节点。

5.4.5 RedisTemplate

RedisTemplate底层同样基于lettuce实现了对Redis分片集群的支持,使用步骤与主从集群基本一致,只是在配置文件application.yml中略有差异:

# src/main/resources/application.yml

spring:
  redis:
    cluster:
      nodes:
        - 192.168.146.128:8001
        - 192.168.146.128:8002
        - 192.168.146.128:8003
        - 192.168.146.128:8004
        - 192.168.146.128:9001
        - 192.168.146.128:9002
        - 192.168.146.128:9003

下面做个简单的测试:调用/redis/set/test/ccc接口,由日志可知写操作由master节点8004实例完成,这个之前的测试结果是一致的:

5.5 小结

第5章到此就学习完毕了,本章的主题是:Redis分布式缓存。回顾一下本章的学习的内容:

(十三)RDB、AOF持久化的原理;Redis主从复制集群的搭建和原理分析。
(十四)Redis哨兵集群的搭建和原理分析。
(十五)Redis分片集群的搭建和原理分析。

更多内容请查阅分类专栏:Redis从入门到精通

感兴趣的读者还可以查阅我的另外几个专栏:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

维先生d

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值