Redis集群的学习(四)

发布于:2025-06-24 ⋅ 阅读:(18) ⋅ 点赞:(0)

一、Redis集群(cluster)

1.1、定义:

由于数据量过大,单个master复制集难以承担,因此需要对多个复制集进行集群,每个集群只负责整个数据集中的一小部分,在多个redis节点间共享数据的程序集。
在这里插入图片描述

1.2、集群能干什么?

  • 支持多个master,每个master可以有多个slave
  • 集群自带sentinel的故障转移机制,内置高可用的支持,无需再去使用哨兵功能
  • 客户端与redis节点连接时,不再需要连接集群中所有节点,只需要任意连接集群中的一个可用节点即可
  • slot槽位负责分配到各个物理节点,由对应的集群来负责维护节点、插槽和数据之间的关系

1.3、槽位slot

集群并未使用一致性hash算法,而是使用了槽位slot的概念。

以哈希槽分区算法为例,集群有16384个槽位,每个key通过CRC16校验后对16384取模来决定映射到哪一个槽位上。

HASH_SLOT = CRC16(key) mod 16384
在这里插入图片描述

***注意:***虽然集群节点上限为16384个,但建议最大节点约1000个

1.4、redis分片

  • 定义:使用redis集群时,会将数据分散到多个节点上,每个节点负责一部分数据的存储和查询。即每个节点上存储的数据是整个数据集的一部分。
  • 如何找到分片:以哈希槽分区算法为例,HASH_SLOT = CRC16(key) mod 16384

1.5、使用槽位和分片的优势

  • 方便扩容和缩容,且不会造成集群成不可用状态
  • 方便数据分派查找

1.6、注意

  • redis集群是不保证强一致性,即在特定情况下,redis集群会丢失一些被系统收到的写入命令。

二、集群算法

2.1、哈希取余分区

假设3台redis构成一个集群,用户每次读写都是根据公式hash(key)%3,来决定数据映射在哪台机器上。
在这里插入图片描述

  • 优点:
      1. 简单粗暴,直接有效
  • 缺点:
      1. 由于分母写死了,扩容/缩容困难,一旦节点数量发生变化,所有的映射规则都需要重新计算。例如,如果某台redis机器出故障,那么分母会进行变化,所有的映射规则都需要重新计算,此时有很大可能造成数据混乱。

2.2、一致性哈希分区

2.2.1、为了弥补哈希取余分区的缺点,引入一致性哈希分区。

当redis服务器数量发生变化时,尽量减少客户端到服务器的映射关系。

2.2.2、具体步骤

    1. 算法构建一致性哈希环
    • 构成hash空间[0,2^32-1],将线性空间变为环形空间。
    • 之前的hash取余分区,是将key通过hash函数映射到[0,232-1]区间内,然后对**节点数量**进行取模。而一致性哈希分区则是***对232取模***,然后将结果映射到环形空间上。
      在这里插入图片描述
    1. 服务器IP节点映射
    • 将集群中每个服务器的IP地址映射到环形空间上。
      在这里插入图片描述
    1. key落到服务器的落键规则
    • 将key通过hash函数映射到环形空间上,然后顺时针查找距离最近的服务器节点。
      在这里插入图片描述

2.2.3、优点

    1. 具有容错性,当一台服务器宕机后,key映射到这台服务器的数据,会转移到顺时针方向的下一台服务器上。
    1. 具备扩展性,当新增一台服务器时,会将该台服务器与逆时针上一台服务器间的数据转移到该服务器上,不会导致hash取余全部重新洗牌。

2.2.4、缺点

    1. 数据倾斜问题,当服务器节点数量较少时,会导致部分服务器的负载过大,大部分缓存的数据全部集中在一台机器上-----头重脚轻

2.3、哈希槽分区算法

2.3.1、为了解决一致性哈希分区的数据倾斜问题,引入了哈希槽分区的概念。

  • 为了解决数据倾斜问题,在数据与redis之间增加了一层映射关系,即哈希槽,用于管理数据与节点的关系。即节点上放的是槽,槽里面放的是数据。
  • 哈希槽实质是一个数组[0, 2^14-1],即16384个槽位。
    在这里插入图片描述

三、Redis集群搭建(采用哈希槽分区算法)

在这里插入图片描述

3.1、 三主三从集群配置(硬件够,可以多开,四主四从,五主五从)

    1. 在自己的redis目录下新建一个文件夹,命名为cluster
      在这里插入图片描述
    1. 根据上图配置,设置相关配置文件,注意IP地址
vim redisCluster6381.conf

daemonize yes
protected-mode no
port 6381
logfile "./cluster6381.log"
pidfile "./cluster6381.pid"
dir "./"
dbfilename dump6381.rdb
appendonly yes
appendfilename "appendonly6381.aof"
requirepass "123456"
masterauth "123456"

cluster-enabled yes
cluster-config-file nodes6381.conf
cluster-node-timeout 5000

其余6382,6383,6384,6385,6386.conf文件都一样,注意端口号和该机上的redis密码
至少是六个节点
在这里插入图片描述

本机硬件不够,就记录下相关配置操作

3.2、启动集群

    1. 启动6381,6382,6383,6384,6385,6386六个节点
#机器1
redis-server /path/redisCluster6381.conf
redis-server /path/redisCluster6382.conf

#机器2
redis-server /path/redisCluster6383.conf
redis-server /path/redisCluster6384.conf

#机器3
redis-server /path/redisCluster6385.conf
redis-server /path/redisCluster6386.conf

在这里插入图片描述

在这里插入图片描述

    1. 通过redis-cli为这6台机器构建集群关系
redis-cli -a 123456 --cluster create --cluster-replicas 1 192.168.127.132:6381 192.168.127.132:6382 192.168.127.138:6383 192.168.127.138:6384 192.168.127.142:6385 192.168.127.142:6386

–cluster-replicas 1 表示每个master都有一个slave
如果创建成功,不仅会显示集群信息,还会在每个节点的目录下生成一个nodes.conf文件
在这里插入图片描述

    1. 以6381为切入点,查看集群信息
redis-cli -a 123456 -p 6381 

在这里插入图片描述

cluster nodes #查看集群信息

在这里插入图片描述

三主三从集群搭建成功,值得注意的是和理论上建立的集群可能对不上,比如6381为主,6382为从,但实际上却是6384为从机,以实际为准

3.3、集群读写测试

  • 开启集群,要注意路由到位,即槽位的范围区间,否则会出现下面这个错误
    在这里插入图片描述

k1要跑到6385的机器上,k2在本机可以

  • 如何解决
    退出,重连redis
redis-cli -a 123456 -p 6381 -c #-c 表示集群模式

在这里插入图片描述

  • 查看某个key所属的槽位
cluster keyslot k1

3.4、主从容错切换迁移

  • 以6381主机为例,down掉6381,看从机是否会上位
    在这里插入图片描述

在这里插入图片描述

6381down掉,6384自动上位

  • 6381王者归来,能否重新上位?
    和哨兵模式一样,重新上线后,不会自动上位
    在这里插入图片描述

3.5、节点从属调整

cluster failover #手动触发故障转移

在这里插入图片描述

3.6、集群扩容

    1. 新增一台机器,填写相关配置文件,如redisCluster6387,6388.conf文件
    1. 启动新增的节点,方法和上面启动集群一样
    1. 新机器加入原有集群
redis-cli -a 123456 --cluster add-node 192.168.127.144:6387 192.168.127.132:6381

注意最后面是6381,不是6388,代表6381是新机6387的领路人

    1. 槽位重新洗牌,重新分配
redis-cli -a 123456 --cluster reshard 192.168.127.132:6381
    1. 为6388分配从节点,即6387的从节点
redis-cli -a 123456 --cluster add-node 192.168.127.144:6388 192.168.127.144:6387 --cluster-slave --cluster-master-id <6387的节点ID>

3.7、集群缩容

    1. 将6387,6388下线
#先获取6388的节点ID
redis-cli -a 123456 --cluster check 192.168.127.144:6388

#下线6388,删除该节点
redis-cli -a 123456 --cluster del-node 192.168.127.144:6388 <节点ID>

#下线6387,先将数据归还
redis-cli -a 123456 --cluster reshard 192.168.127.132:6381

redis-cli -a 123456 --cluster del-node 192.168.127.144:6387 <节点ID>

四、总结

    1. 不在同一槽位上的数据,无法使用mset,mget等操作
      在这里插入图片描述
    1. 如果在集群模式下,要使用mset,mget等操作
mset k1{z} v1 k2{z} v2 k3{z} v3
mget k1{z} k2{z} k3{z}
    1. 配置文件中参数cluster-require-full-coverage yes,代表集群最小必须是三主三从才能对外提供服务,如果任意一个一主一从挂了,那么集群就不能对外提供服务了。
    1. 集群算法分为三种:哈希取余分区、一致性哈希分区、哈希槽分区
      1. 哈希取余分区,扩容缩容困难
      1. 一致性哈希分区,解决了扩容缩容困难的问题,但是存在数据倾斜问题
      1. 哈希槽分区,解决了数据倾斜问题,但对硬件存在一定的要求,至少三主三从。

五、问题

1. 哈希槽分区算法为什么要用16384个槽位?

  • CRC16用2^16,应该是65536,为什么不用这么多,而是用了16384个槽位?
      1. 如果槽位数量达到65536,那么发送心跳信息的消息头达到8k(65536 / 8 / 1024),心跳包过于庞大,浪费带宽
      1. redis集群主节点数量不可能超过1000个,如果超过1000个,会造成网络拥塞。
      1. 槽位越少,节点越少的情况下,压缩比高,容易传输。

网站公告

今日签到

点亮在社区的每一天
去签到