广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >Redis分片集群的实现
  • 519
分享到

Redis分片集群的实现

Redis分片集群Redis分片 2023-01-30 12:01:35 519人浏览 薄情痞子
摘要

目录1 搭建分片集群1.1 集群结构1.2 准备实例和配置1.3 启动1.4 创建集群1.5 测试2 散列插槽3 集群伸缩3.1 创建节点并添加到集群3.2 转移插槽4 故障转移4.

1 搭建分片集群

主从和哨兵可以解决高可用高并发读的问题。但是依然有两个问题没有解决:

  • 海量数据存储问题,单个Redis节点对于数据的存储量是有上限的
  • 并发写的问题,高并发读的问题我们可以用主从集群来解决,那高并发写的问题又该怎样解决呢

针对上述问题,我们可以搭建Redis的分片集群,如图所示:

Redis的分片集群具有以下特征:

  • 集群中有多个master,每个master保存不同数据
  • 每个master都可以有多个slave节点
  • master之间通过ping监测彼此健康状态(可以取代哨兵机制)
  • 客户端请求可以访问集群任意节点,最终都会被转发到正确节点

接下来我们可以动手来搭建一个Redis分片集群

1.1 集群结构

分片集群需要的节点数量较多,这里我们搭建一个最小的分片集群,包含3个master节点,每个master包含一个slave节点,结构如下:

这里我们会在同一台虚拟机中开启6个redis实例,模拟分片集群,信息如下:

IPPORT角色
192.168.211.1007001master
192.168.211.1007002master
192.168.211.1007003master
192.168.211.1008001slave
192.168.211.1008002slave
192.168.211.1008003slave

1.2 准备实例和配置

这里我的redis安装目录为/usr/local/redis-6.2.6,以下操作将以此目录进行参考,额外需要注意的是,以下操作都是在redis没有设置密码的情况下进行的,如果你的redis设置了密码,那么按照以下步骤进行就会出问题。

1)创建出7001、7002、7003、8001、8002、8003目录

# 进入/local目录
cd /usr/local
# 创建目录
mkdir 7001 7002 7003 8001 8002 8003

2)在/usr/local下准备一个新的redis.conf文件,内容如下:

port 6379
# 开启集群功能
cluster-enabled yes
# 集群的配置文件名称,不需要我们创建,由redis自己维护
cluster-config-file /usr/local/6379/nodes.conf
# 节点心跳失败的超时时间
cluster-node-timeout 5000
# 持久化文件存放目录
dir /usr/local/6379
# 绑定地址
bind 0.0.0.0
# 让redis后台运行
daemonize yes
# 注册的实例ip
replica-announce-ip 192.168.211.100
# 保护模式
protected-mode no
# 数据库数量
databases 1
# 日志
logfile /usr/local/6379/run.log

3)将这个文件拷贝到每个目录下:

# 进入/local目录
cd /usr/local
# 执行拷贝
echo 7001 7002 7003 8001 8002 8003 | xargs -t -n 1 cp redis.conf

4)修改每个目录下的redis.conf,将其中的6379修改为与所在目录一致:

# 进入/local目录
cd /usr/local
# 修改配置文件
printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t sed -i 's/6379/{}/g' {}/redis.conf

1.3 启动

因为已经配置了后台启动模式,所以可以直接启动服务:

# 进入/usr/local目录
cd /usr/local
# 一键启动所有服务
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{<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->} -t redis-cli -p {<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->} shutdown

1.4 创建集群

虽然服务启动了,但是目前每个服务之间都是独立的,没有任何关联。我们需要执行以下命令来创建集群,注意,以下命令需要你的redis版本在5.0之后:

redis-cli --cluster create --cluster-replicas 1 192.168.211.100:7001 192.168.211.100:7002 192.168.211.100:7003 192.168.211.100:8001 192.168.211.100:8002 192.168.211.100:8003

命令说明:

  • redis-cli --cluster:代表集群操作命令
  • create:代表创建集群
  • --cluster-replicas 1 :指定集群中每个master的副本个数为1,也就是说一个master只有一个slave,此时节点总数 ÷ (replicas + 1) 得到的就是master的数量。因此节点列表中的前n个就是master,其它节点都是slave节点,在创建集群时这些slave会被随机分配给不同master

执行上述命令之后,控制台会列出当前主从节点分配的结果,即将那些slave分别分配给哪些master,并询问你是否同意,这里我们输入'yes'即可

确定之后,集群开始创建

通过命令可以查看集群状态:

redis-cli -p 7001 cluster nodes

1.5 测试

集群操作时,需要在redis-cli连接时带上-c参数才可以

redis-cli -p 7001

通过观察上述从节点的状态,我们发现7001的slave是8001,我们可以尝试在7001里插入一个数字,再从8001里获取

事实上,我们不仅可以从8001里获取到num,也可以从其他slave甚至其他master里获取到num:

而且我们发现,当我们试图从其他节点获取num时,最后都会跳转到7001,为什么会这样呢?这就涉及到我们即将讲解的插槽原理

2 散列插槽

一个Redis分片集群有0~16383共16384个插槽(hash slot),这些插槽会被平均分给每一个master节点,一个master节点映射着一部分插槽,这一点在集群创建时的信息中可以看到

在分片集群中,数据key并不是与某个节点绑定,而是与插槽绑定。数据key与插槽是多对一的关系,redis会根据key的有效部分计算插槽值,然后将key放入对应插槽,key的有效部分分两种情况:

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

举个例子,假如key是num,那么插槽值就会根据num来计算,如果key是{itheima}num,那么插槽值就会根据itheima来计算。计算方式是利用CRC16算法得到一个hash值,然后对16384取余,得到的结果就是slot值。

如果当前操作的key所在的插槽不属于本节点,则会发生重定向,重定向的目标是该插槽所属的节点,这个节点一定是master,如果我们连接的节点为slave,则会直接进行重定向,因为slave是没有插槽的。

针对上述几点,演示如下:

如上图所示,我们连接了7001,并试图插入数据k1,这时redis需要去判断k1所属的插槽位置,由于key中不包含’{}',因此整个key都是有效部分,redis会对k1做hash运算然后对16384取余,得到的结果是12706,这也就是k1所在的插槽的位置,在当前集群中,映射该插槽的节点是7003,此时就会发生重定向,我们也可以观察到当我们执行完set k1 1命令之后,操作的端口已经变成了7003。此时我们继续在7003端口中进行操作,比如修改数据num的值,而num所在的插槽是2765,在当前集群中,映射该插槽的节点是7001,因此当我们执行完set num 2命令之后,操作的端口又重新变成了7001

那么接下来让我们思考两个问题:

为什么数据key要与插槽绑定,而不是与节点绑定呢?

这是因为Redis的主节点有可能会出现宕机情况,也有可能由于集群伸缩而被删除,当节点删除或者发生宕机时,节点上保存的数据也就丢失了,但如果数据绑定的是插槽而不是节点,那么当出现上述情况时,就可以将故障节点的插槽转移至存活节点上。这样,数据跟插槽绑定,就永远都能够找到数据所在位置。

如何将同一类数据固定的保存在一个插槽中

在业务开发中,同一类型的数据key最好是保存在一个插槽中,因为如果分散保存,在我们调用的时候就很可能出现重定向的情况,重定向是会消耗一部分性能的。如果我们希望将同一类型的数据key最好是保存在一个插槽中,可以为这些key带上一个用’{}'包裹的固定前缀,比如{user}zs、{user}ls等等,因为我们之前说过,当key中包含"{}“,且”{}“中至少包含1个字符时,”{}"中的部分是有效部分,redis会根据这一部分来计算插槽值,如果我们将同一类型的key都加上这类前缀,就能保证这些key在同一个插槽中了

3 集群伸缩

集群已经创建了,那么如果我们想在集群中添加节点或删除节点,又应该怎么做呢?

redis-cli --cluster提供了很多操作集群的命令,可以通过下面方式查看:

其中就包括添加节点的命令:

假设现在有以下需求:向集群中添加一个新的master节点7004,并在这个节点中存储 num = 10,执行步骤如下:

3.1 创建节点并添加到集群

1)在/usr/local目录下创建一个文件夹:

cd /usr/local
mkdir 7004

2)拷贝配置文件:

cp redis.conf 7004

3)修改配置文件:

printf '%s\n' 7004 | xargs -I{<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->} -t sed -i 's/6379/{}/g' {<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->}/redis.conf

4)启动

redis-server 7004/redis.conf

接下来就需要将7004添加到集群中了,在执行添加操作之前,我们先来了解以下添加节点的命令

添加节点首先需要以下几个参数:

  • new_host:new_port :指定新添加的节点的ip地址与端口号,这个没什么好说的
  • existing_host:existing_port:任意指定一个集群中已经存在的节点的ip地址与端口号。因为集群中加入新节点是需要通知其他旧节点的,新节点只需要将自己的信息提供给集群中任意一个节点,那么整个集群就都能知道关于新节点的信息了
  • cluster-slave:可选项,不指定则表示该节点是master,如果指定了则表示该节点是一个slave
  • cluster-master-id <arg>:如果我们指定了cluster-slave,那么就需要通过该参数指定该节点的master的id

了解了该命令之后,接下来我们来执行添加节点操作:

执行命令:

redis-cli --cluster add-node 192.168.211.100:7004 192.168.211.100:7001

通过命令查看集群状态:

redis-cli -p 7001 cluster nodes

如图,7004加入了集群,并且默认是一个master节点:

但是,我们也可以看到7004是没有插槽的,因为插槽已经被其他master瓜分完毕了,因此没有任何数据可以存储到7004上,这时候我们就需要进行插槽的转移,即将其他matser的插槽分出一部分给7004

3.2 转移插槽

首先回归需求本身,我们的需求是将num=10存储在7004节点上,那么我们的目的就很明显了,首先需要知道num存储在哪个插槽上,然后将这个插槽转移到7004上即可

如上图所示,num的插槽为2765,该插槽目前是保存在7001上的,因此我们可以将0~3000的插槽从7001转移到7004,转移插槽的命令格式如下:

具体步骤如下:

1)输入转移插槽命令,这里我们需要转移的插槽在7001上,因此需要指定7001的地址

redis-cli --cluster reshard 192.168.211.100:7001

2)系统会询问我们要移动多少个插槽,这里我们输入3000即可

3)系统接着询问我们需要让哪个节点来接收插槽,这里我们需要输入7004的ID

4)接着系统会询问我们要从哪些节点中移动这些插槽到7004

这里我们有三个选择:

  • all:代表全部,也就是三个节点各转移一部分
  • 具体的id:目标节点的id
  • done:表示结束

这里我们需要从7001中获取插槽,因此填写7001的id,然后输入done表示结束

5)接下来会冒出一大串东西,并询问我们是否确定要移动这些插槽,这里我们直接输入yes即可

输入yes之后,等待控制台打印结束,插槽也就移动完毕了

6) 输入以下命令查看插槽是否已经移动到7004

redis-cli -p 7001 cluster nodes

很显然,我们的目的已经达成了

那么如果我们要删除7004节点,又应该怎样做呢?这里笔者只给去具体思路,大家可以自行尝试一下:

  • 先将 7004 分配的插槽转移至其他节点
  • 执行删除节点命令redis-cli --cluster del-node host:port node_id
  • 通过命令查询结果redis-cli -p 7001 cluster nodes

4 故障转移

之前我们提到过,redis分片集群可以通过master之间的心跳监测来监测彼此之间的健康状态,从而取代哨兵。而我们也知道,哨兵的作用就是监测master和slave的状态,当认为一个master客观下线后,会从slave中选举出一个新的master,现在让我们来验证一下redis分片集群是否具备这个功能。

首先集群的初始状态是这样的,如果状态为connected则表示节点正常连接

其中7001、7002、7003、7004都是master,我们计划让7002宕机。

4.1.自动故障转移

当集群中有一个master宕机会发生什么呢?我们可以直接停止一个redis实例,例如7002:

redis-cli -p 7002 shutdown

1)首先是该实例与其它实例失去连接

2)然后是疑似宕机,7002的状态变成了disconnected

3)最后是确定下线,将7002的一个slave提升为新的master,这里由于7002只有一个slave,即8002,因此8002被选为了新的master

4)接下来我们通过以下命令再次启动7002节点

redis-server /usr/local/7002/redis.conf

当7002再次启动之后,它就已经变为一个slave节点了

上面这种叫自动故障转移,但有的时候我们可能需要做手动故障转移,比如当某台master机器比较老旧,需要升级时,我们就可以在这个集群中新增一个节点,让这个节点成为取代原来的master成为新的master,这样原来的master就会变成新master的一个slave,从而实现机器的无感知升级

4.2 手动故障转移

我们可以在slave节点中使用cluster failover命令,这个命令会让当前slave节点的master暂时宕机,宕机期间会将自身的数据转移给执行命令的slave节点,宕机结束后,之前的master会变成slave,而执行命令的slave会变成新的master。

其详细流程如下:

当slave执行了cluster failover命令之后,就会向master节点发送节点替换通知,为了避免数据的丢失,master接收到slave节点发送过来的通知后,就会暂时拒绝来自客户端的任何数据读写请求。然后,master会将自己当前的offset返回给slave,slave接收到后会判断自身数据中的offset与master的offset是否一致,如果不一致,则需要进行数据同步。由于 master 已经拒绝了客户端的所有请求,那么一旦 slave完成数据同步,也就表示slave与master之间数据是完全一致的。

数据同步结束之后,就会开始进行故障转移,让slave与master 进行角色互换,该slave成为新的master,而旧的master则转变为一个新的slave。转移结束后,slave便会标记自己为master,并向集群中每一个节点广播故障转移的结果。当集群中节点收到广播后,后续的所有交互便转移至新的master。

这种failover命令可以指定三种模式:

缺省:默认的流程,如图1~6歩,一般我们会选择这个force:省略了对offset的一致性校验,直接开始故障转移takeover:直接执行第5歩,忽略数据一致性、忽略master状态和其它master的意见

接下来我们可以尝试一下,在7002这个slave节点上执行手动故障转移,让它重新夺回master地位,步骤如下:

1)利用redis-cli连接7002,并执行cluster failover命令

2)通过redis-cli -p 7001 cluster nodes命令查看节点状态

5 RedisTemplate访问分片集群

我们只需要通过以下简单的配置,就可以通过Java代码访问我们之前部署好的分片集群

1)在boot项目的pom文件中导入依赖

 <dependency>
 	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-redis</artifactId>
 </dependency>

2)在application.yml中指定sentinel相关信息:

spring:
  redis:
    cluster:
      nodes: #指定分片集群中每一个节点信息
        - 192.168.150.101:7001
        - 192.168.150.101:7002
        - 192.168.150.101:7003
        - 192.168.150.101:8001
        - 192.168.150.101:8002
        - 192.168.150.101:8003

3)在项目的启动类中,添加一个新的bean,这个bean是用来做Redis集群的读写分离的

@Bean
public LettuceClientConfigurationBuilderCustomizer clientConfigurationBuilderCustomizer(){
    return clientConfigurationBuilder -> clientConfigurationBuilder.readFrom(ReadFrom.REPLICA_PREFERRED);
}

bean中配置的信息是读写策略,包括四种可选项:

  • MASTER:从master读取
  • MASTER_PREFERRED:优先从master节点读取,master不可用才读取slave
  • REPLICA:从slave节点读取
  • REPLICA _PREFERRED:优先从slave节点读取,所有的slave都不可用才读取master

上述配置完毕之后,我们就可以正常使用RedisTemplate来对redis集群进行操作,如果集群中某个的master宕机了,集群就会自动选举新的master,并将新master的信息发送给该Java程序,这样Java程序就可以对新master进行写操作而对其他节点进行读操作了。而这一过程都是自动完成的,无需我们过多关注

到此这篇关于Redis 分片集群的实现的文章就介绍到这了,更多相关Redis 分片集群内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Redis分片集群的实现

本文链接: https://www.lsjlt.com/news/178782.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Redis分片集群的实现
    目录1 搭建分片集群1.1 集群结构1.2 准备实例和配置1.3 启动1.4 创建集群1.5 测试2 散列插槽3 集群伸缩3.1 创建节点并添加到集群3.2 转移插槽4 故障转移4....
    99+
    2023-01-30
    Redis 分片集群 Redis 分片
  • Redis 分片集群的实现
    目录1 搭建分片集群1.1 集群结构1.2 准备实例和配置1.3 启动1.4 创建集群1.5 测试2 散列插槽3 集群伸缩3.1 创建节点并添加到集群3.2 转移插槽4 故障转移4.1.自动故障转移4.2 手动故障转移5...
    99+
    2023-01-30
    Redis分片集群 Redis分片
  • Redis集群分片环境部署
    原理 集群技术是构建高并发网站的主要技术,访问网站的最大压力是在访问某个页面时,需要时查询数据库并相应,Redis从3.0版本以后开始支持集群功能了,要让集群正常工作至少得有三个主节点。Redis集群是基于...
    99+
    2022-10-18
  • redis分片式集群是怎么做的
    redis分片式集群的实现方法:准备6台Linux服务器,在每台服务器上安装redis服务。安装好之后,修改每台服务器的配置文件redis.conf,修改如下几项:#端口分别设置为10000~10005port 10000#开启cluste...
    99+
    2022-10-06
  • redis 分片集群搭建与使用教程
    目录前言搭建集群架构图前置准备搭建步骤创建集群Redis散列插槽说明集群伸缩(添加节点)故障转移使用redistemplate访问分片集群前言 redis可以说在实际项目开发中使用的非常频繁,在redis常用集群中,我们...
    99+
    2022-06-29
    redis 分片集群 redis分片集群搭建
  • redis分片集群如何搭建与使用
    本文小编为大家详细介绍“redis分片集群如何搭建与使用”,内容详细,步骤清晰,细节处理妥当,希望这篇“redis分片集群如何搭建与使用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识...
    99+
    2022-10-19
  • Redis 哨兵集群的实现
    目录1、Sentinel 哨兵2、Redis 主从分离一、配置Master二、配置Slave  1、在配置文件中配置从服务  2、在服务启动后设置  3、总结3、Sentinel 哨...
    99+
    2022-11-12
  • MongoDB中怎么实现分片与集群
    这期内容当中小编将会给大家带来有关MongoDB中怎么实现分片与集群,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。一、 mongodb分片与集群拓扑图二、分片与集群的部署...
    99+
    2022-10-18
  • redis如何实现集群
    这篇文章给大家分享的是有关redis如何实现集群的内容。小编觉得挺实用的,因此分享给大家做个参考。一起跟随小编过来看看吧。1.主从复制主从复制原理:从服务器连接主服务器,发送SYNC命令;主服务器接收到SY...
    99+
    2022-10-18
  • Redis Cluster集群数据分片机制是什么
    小编这次要给大家分享的是Redis Cluster集群数据分片机制是什么,文章内容丰富,感兴趣的小伙伴可以来了解一下,希望大家阅读完这篇文章之后能够有所收获。Redis Cluster数据分片机制Redis...
    99+
    2022-10-18
  • Redis集群的示例分析
    这篇文章主要介绍Redis集群的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!Redis集群详解Redis有三种集群模式,分别是:* 主从模式 * Se...
    99+
    2022-10-18
  • Redis集群实战
                       Redis基础到集群实战笔记   &n...
    99+
    2022-10-18
  • CentOS7上的mongodb分片群集
    CentOS7的mongodb分片群集 简介 高数据量和吞吐量的数据库应用会对单机的性能造成较大的压力,大的查询量会将单机的CPU耗尽,大的数据量对单机的存储压力较大,最终会耗尽系统的内存而将压力转移到磁...
    99+
    2022-10-18
  • MongoDB分布式集群分片
    MongoDB高可用集群搭建 一、环境准备 # 启动时需要使用非root用户,所有创建一个mongo用户: useradd mongo # 为mongo用户添加密码: echo 123456 | pass...
    99+
    2022-10-18
  • k8s部署redis cluster集群的实现
    目录Redis 介绍为什么要用Redis什么是Redis Cluster集群k8s以StatefulSet方式部署redis cluster集群:部署nfs创建pv部署redis初始...
    99+
    2022-11-12
  • redis 哨兵集群搭建的实现
    目录前言为什么需要哨兵集群搭建前准备搭建步骤集群测试前言 在上一篇,我们了解了Redis 复制集群的完整的搭建流程,本篇来分享一下如何搭建 redis 哨兵集群。 为什么需要哨兵集群 redis哨兵集群要解决的问题是什么...
    99+
    2022-08-10
    redis 哨兵集群搭建 redis 哨兵集群
  • redis复制集群搭建的实现
    目录前言环境准备搭建过程问题总结前言 Redis 复制集群是开发中一种比较常用的集群模式,本篇演示如何在Centos7上快速搭建一个redis复制集群; 环境准备 1、基于centos7系统的服务器(或者云服务器); 2...
    99+
    2022-08-10
    redis复制集群搭建 redis复制集群
  • redis 哨兵集群搭建的实现
    目录前言为什么需要哨兵集群搭建前准备搭建步骤集群测试前言 在上一篇,我们了解了redis 复制集群的完整的搭建流程,本篇来分享一下如何搭建 redis 哨兵集群。 为什么需要哨兵集群...
    99+
    2022-11-13
    redis 哨兵集群搭建 redis 哨兵集群
  • Mongodb 分片集群部署
    Mongodb分片集群介绍       分片(sharding)是指将数据库拆分,将其分散在不同的机器上的过程。将数据分散到不同的机器上,不需要功...
    99+
    2022-10-18
  • mongodb 分片集群搭建
    环境介绍:...
    99+
    2022-10-18
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作