Redis03 - 高可用

Redis高可用

文章目录

  • Redis高可用
    • 一:主从复制 & 读写分离
      • 1:主从复制的作用
      • 2:主从复制原理
        • 2.1:全量复制
        • 2.2:增量复制(环形缓冲区)
      • 3:主从复制实际演示
        • 3.1:基本流程
          • 准备好两个redis服务器
          • 配置修改
          • 启动两个服务器
          • 查看主从状态
          • 主从配置指令
          • 测试下
        • 3.2:一些说明
      • 4:读写分离问题
    • 二:哨兵模式
      • 1:基本工作流程
        • 1.1:哨兵集群组建(消息pub/sub)
        • 1.2:下线判断(客观下线)
        • 1.3:主哨兵选举(raft半数通过)
        • 1.4:新主库的选出(健康,完整的)
        • 1.5:故障转移(易主通知复制)
      • 2:哨兵模式实际演示
        • 2.1:基本流程
          • 创建哨兵服务器
          • 修改哨兵服务器的配置文件
          • 启动哨兵服务器
          • 主节点挂掉测试
          • 要是哨兵也挂了咋办?
        • 2.2:Jedis感知
    • 一:集群
      • 1:集群的引入
      • 2:设计目标
      • 3:常用概念
        • 3.1:哈希槽 hash_slot
        • 3.2:hash_tags
        • 分片nodes属性
        • 3.3:集群总线
      • 4:搭建实例
        • 4.1:基本流程
          • 创建六个redis服务器
          • 配置修改
          • 全部启动
          • 主从集群分配
        • 4.2:其他说明
          • 节点信息
          • 让某一个主节点挂掉会怎么样?
          • 主从都挂了怎么办?
          • Jedis

一:主从复制 & 读写分离

主从复制,主从复制是指将一台redis上的服务的数据复制到另外的redis上,前者称为主节点,后者称为从节点【单向性】

1:主从复制的作用

数据冗余

主从复制实现了数据的热备份,是持久化之外的一种数据冗余的方式

故障恢复

当主节点出现问题的时候,可以由从节点提供服务,实现快速的故障恢复,实际上是一种服务的冗余。

负载均衡

在主从复制的基础上,配合读写分离,可以由主节点提供写服务,从节点提供读服务,分担服务器的负载,尤其是在写少读多的情况下,通过配置多个从节点分担读负载,可以大大的提高redis服务器的并发量。

在这里插入图片描述

高可用基石

是哨兵模式和集群可以实现的基础,因此可以说是高可用的基础。

2:主从复制原理

和MongoDB的初始同步和复制很像

2.1:全量复制

当我们启动多个redis实例的时候,就可以使用replicaof(5.0以前是slaveof)形成主库和从库的关系

会按照三个步骤完成数据的第一次同步:

确立主从关系

例如:现在有实例 1(ip:172.16.19.3)和实例 2(ip:172.16.19.5)

我们在实例 2 上执行以下这个命令后,实例 2 就变成了实例 1 的从库,并从实例 1 上复制数据

replicaof 172.16.19.3 6379

全量复制的三个阶段

在这里插入图片描述
第一步:建立连接,协商同步

  • 主要是为全量复制做准备。
  • 在这一步,从库和主库建立起连接,并告诉主库即将进行同步,主库确认回复后,主从库间就可以开始同步了。
  • 具体来说,从库给主库发送 psync 命令,表示要进行数据同步,主库根据这个命令的参数来启动复制。psync 命令包含了主库的 runID 和复制进度 offset 两个参数。runID,是每个 Redis 实例启动时都会自动生成的一个随机 ID,用来唯一标记这个实例。当从库和主库第一次复制时,因为不知道主库的 runID,所以将 runID 设为“?”。offset,此时设为 -1,表示第一次复制。主库收到 psync 命令后,会用 FULLRESYNC 响应命令带上两个参数:主库 runID 和主库目前的复制进度 offset,返回给从库。从库收到响应后,会记录下这两个参数。
  • 注意,FULLRESYNC 响应表示第一次复制采用的全量复制,也就是说,主库会把当前所有的数据都复制给从库。

第二步:将主库所有同步数据给从库

  • 从库收到数据后,在本地完成数据加载。这个过程依赖于内存快照生成的 RDB 文件
  • 具体来说,主库执行 bgsave 命令,生成 RDB 文件,接着将文件发给从库。从库接收到 RDB 文件后,会先清空当前数据库,然后加载 RDB 文件。这是因为从库在通过 replicaof 命令开始和主库同步前,可能保存了其他数据。为了避免之前数据的影响,从库需要先把当前数据库清空。在主库将数据同步给从库的过程中,主库不会被阻塞,仍然可以正常接收请求。否则,Redis 的服务就被中断了。但是,这些请求中的写操作并没有记录到刚刚生成的 RDB 文件中。为了保证主从库的数据一致性,主库会在内存中用专门的 replication buffer,记录 RDB 文件生成后收到的所有写操作。

第三步:主库发送新的写命令给从库

  • 当主库完成 RDB 文件发送后,就会把此时 replication buffer 中的修改操作发给从库,从库再重新执行这些操作。这样一来,主从库就实现同步了
2.2:增量复制(环形缓冲区)

如果主从库在命令传播时出现了网络闪断,那么,从库就会和主库重新进行一次全量复制,开销非常大。

从 Redis 2.8 开始,网络断了之后,主从库会采用增量复制的方式继续同步。
在这里插入图片描述

repl_backlog_buffer

它是为了从库断开之后,如何找到主从差异数据而设计的环形缓冲区,从而避免全量复制带来的性能开销

⚠️ 如果从库断开时间太久,repl_backlog_buffer环形缓冲区被主库的写命令覆盖了,那么从库连上主库后只能乖乖地进行一次全量复制

所以repl_backlog_buffer配置尽量大一些,可以降低主从断开后全量复制的概率

repl_buffer

我们每个client连上Redis后,Redis都会分配一个client buffer,所有数据交互都是通过这个buffer进行的

注意点

一个从库如果和主库断连时间过长,造成它在主库repl_backlog_buffer的slave_repl_offset位置上的数据已经被覆盖掉了,此时从库和主库间将进行全量复制。

每个从库会记录自己的slave_repl_offset,每个从库的复制进度也不一定相同。

在和主库重连进行恢复时,从库会通过psync命令把自己记录的slave_repl_offset发给主库,主库会根据从库各自的复制进度,来决定这个从库可以进行增量复制,还是全量复制

3:主从复制实际演示

3.1:基本流程
准备好两个redis服务器

在这里插入图片描述

配置修改

分别将端口号改成6001【redis-master】,6002【redis-slave】 -> 配置文件redis.windows.conf

在这里插入图片描述

启动两个服务器

在这里插入图片描述

查看主从状态

输入info replication命令来查看当前的主从状态,可以看到默认的角色为:master,也就是说所有的服务器在启动之后都是主节点的状态。
在这里插入图片描述

主从配置指令

我们希望让6002作为从节点,通过一个命令即可:输入replicaof 127.0.0.1 6001

🎉 每次都去敲个命令配置主从太麻烦了,我们可以直接在配置文件中配置这个命令

命令后,就会将6001服务器作为主节点,而当前节点作为6001的从节点,并且角色也会变成:slave

在这里插入图片描述
在这里插入图片描述
可以看到从节点信息中已经出现了6002服务器,也就是说现在我们的6001和6002就形成了主从关系

  • 主服务器和从服务器都会维护一个复制偏移量,主服务器每次向从服务器中传递 N 个字节的时候,会将自己的复制偏移量加上 N。
  • 从服务器中收到主服务器的 N 个字节的数据,就会将自己额复制偏移量加上 N
  • 通过主从服务器的偏移量对比可以很清楚的知道主从服务器的数据是否处于一致,如果不一致就需要进行增量同步了。
测试下

在这里插入图片描述

3.2:一些说明

⚠️ 从节点压根就没办法进行数据插入,节点的模式为只读模式

在这里插入图片描述
🎉 那么如果我们现在不想让6002作为6001的从节点了呢?

可以在6002执行replicaof no one【我不是别人的从服务器】即可变回到master

在这里插入图片描述

🎉 全量复制和增量复制

接着我们再次让6002变成6001的从节点【或者在创建一个6003作为6001的从节点】

可以看到,在连接之后,也会直接同步主节点的数据,因此无论是已经处于从节点状态还是刚刚启动完成的服务器,都会从主节点同步数据,实际上整个同步流程为:

  1. 从节点执行replicaof ip port命令后,从节点会保存主节点相关的地址信息。
  2. 从节点通过每秒运行的定时任务发现配置了新的主节点后,会尝试与该节点建立网络连接,专门用于接收主节点发送的复制命令。
  3. 连接成功后,第一次会将主节点的数据进行全量复制,之后采用增量复制,持续将新来的写命令同步给从节点

在这里插入图片描述
⚠️ 当我们的主节点关闭后,从节点依然可以读取数据:但是从节点会提示报错信息

在这里插入图片描述
在这里插入图片描述
再次启动后恢复正常

在这里插入图片描述
🎉 除了作为Master节点的从节点外,我们还可以将其作为从节点的从节点

在这里插入图片描述
采用这种方式,优点肯定是显而易见的,但是缺点也很明显,整个传播链路一旦中途出现问题,那么就会导致后面的从节点无法及时同步。

4:读写分离问题

延迟与不一致问题

由于主从复制的命令传播是异步的,延迟与数据的不一致不可避免。

如果应用对数据不一致的接受程度程度较低,可能的优化措施包括:

  • 优化主从节点之间的网络环境(如在同机房部署);
  • 监控主从节点延迟(通过offset)判断,如果从节点延迟过大,通知应用不再通过该从节点读取数据;
  • 使用集群同时扩展写负载和读负载等。

数据过期问题

在单机版Redis中,存在两种删除策略:

  • 惰性删除:服务器不会主动删除数据,只有当客户端查询某个数据时,服务器判断该数据是否过期,如果过期则删除。
  • 定期删除:服务器执行定时任务删除过期数据,但是考虑到内存和CPU的折中

Redis 3.2中,从节点在读取数据时,增加了对数据是否过期的判断:如果该数据已过期,则不返回给客户端;

将Redis升级到3.2+可以解决数据过期问题。

故障切换问题

在没有使用哨兵的读写分离场景下,应用针对读和写分别连接不同的Redis节点;

当主节点或从节点出现问题而发生更改时,需要及时修改应用程序读写Redis数据的连接;

连接的切换可以手动进行,或者自己写监控程序进行切换,但前者响应慢、容易出错,后者实现复杂,成本都不算低

不持久化的主服务器自动重启非常危险

  • 我们设置节点A为主服务器,关闭持久化,节点B和C从节点A复制数据。
  • 这时出现了一个崩溃,但Redis具有自动重启系统,重启了进程,因为关闭了持久化,节点重启后只有一个空的数据集。
  • 节点B和C从节点A进行复制,现在节点A是空的,所以节点B和C上的复制数据也会被删除。

二:哨兵模式

在这里插入图片描述

哨兵作用

  • 监控 -> 哨兵会不断地检查主节点和从节点是否运作正常

  • 故障自动转移 -> 当主节点不能正常工作时,哨兵会开始自动故障转移操作,它会将失效主节点的其中一个从节点升级为新的主节点,并让其他从节点改为复制新的主节点

  • 配置提供者 -> 客户端在初始化时,通过连接哨兵来获得当前Redis服务的主节点地址

  • 通知 -> 哨兵可以将故障转移的结果发送给客户端

监控和自动故障转移功能,使得哨兵可以及时发现主节点故障并完成转移;

而配置提供者和通知功能,则需要在与客户端的交互中才能体现

1:基本工作流程

1.1:哨兵集群组建(消息pub/sub)

哨兵实例之间可以相互发现,要归功于 Redis 提供的 pub/sub 机制,也就是发布 / 订阅机制【消息传递】

🌰 举一个简单的栗子

在主从集群中,主库上有一个名为__sentinel__:hello的频道,不同哨兵就是通过它来相互发现,实现互相通信的。

哨兵 1 把自己的 IP(172.16.19.3)和端口(26579)发布到__sentinel__:hello频道上

哨兵 2 和 3 订阅了该频道。

那么此时,哨兵 2 和 3 就可以从这个频道直接获取哨兵 1 的 IP 地址和端口号。

然后,哨兵 2、3 可以和哨兵 1 建立网络连接。

在这里插入图片描述
通过这个方式,哨兵 2 和 3 也可以建立网络连接,这样一来,哨兵集群就形成了。

它们相互间可以通过网络连接进行通信,比如说对主库有没有下线这件事儿进行判断和协商。

1.2:下线判断(客观下线)

首先要理解两个概念:主观下线和客观下线

  • 主观下线:任何一个哨兵都是可以监控探测,并作出Redis节点下线的判断;
  • 客观下线:有哨兵集群共同决定Redis节点是否下线;

当某个哨兵(如下图中的哨兵2)判断主库“主观下线”后,就会给其他哨兵发送 is-master-down-by-addr 命令。

接着,其他哨兵会根据自己和主库的连接情况,做出 Y 或 N 的响应,Y 相当于赞成票,N 相当于反对票

在这里插入图片描述
如果赞成票数是大于等于哨兵配置文件中的 quorum 配置项(比如这里如果是quorum=2), 则可以判定主库客观下线了

1.3:主哨兵选举(raft半数通过)

判断完主库下线后,由哪个哨兵节点来执行主从切换呢?

为什么需要哨兵的选举

为了避免单节点哨兵的存在,就需要哨兵集群,而集群的出现表示必然要面临共识问题【选举问题】

故障转移和通知都由主哨兵节点进行负责即可。

哨兵的选举是怎样的

哨兵的选举,遵循的是著名的raft算法:

当投票数 r >= num / 2 + 1 就进行当选

如何成为leader哨兵节点

  • 第一,拿到半数以上的赞成票
  • 第二,拿到的票数同时还需要大于等于哨兵配置文件中的 quorum 值

以 3 个哨兵为例,假设此时的 quorum 设置为 2,那么,任何一个想成为 Leader 的哨兵只要拿到 2 张赞成票,就可以了。

1.4:新主库的选出(健康,完整的)
  • 过滤掉不健康的(下线或断线),没有回复过哨兵ping响应的从节点
  • 选择salve-priority从节点优先级最高(redis.conf)的
  • 选择复制偏移量最大,指复制最完整的从节点

在这里插入图片描述

1.5:故障转移(易主通知复制)

假设现在有这样的情况:主库节点已经客观下线了,哨兵节点3被选为了哨兵leader,并且决定新的主库为从节点slave_1

在这里插入图片描述

故障转移的流程

  1. 将slave-1脱离原从节点(5.0 中应该是replicaof no one),升级主节点,
  2. 将从节点slave-2指向新的主节点
  3. 通知客户端主节点已更换
  4. 将原主节点(oldMaster)变成从节点,指向新的主节点

在这里插入图片描述

转移之后

在这里插入图片描述

2:哨兵模式实际演示

2.1:基本流程

在这里插入图片描述

创建哨兵服务器

在这里插入图片描述

修改哨兵服务器的配置文件
# 其他的全部都删除掉,只写这一行
# 	其中第一个和第二个参数是固定的
# 	第三个参数是为监控对象名称,随意
# 第四个,第五个参数就是主节点的相关信息,包括IP地址和端口
# 最后一个参数是哨兵支持数大于等于多少sentinel monitor cuihaida-sentinel 127.0.0.1 6001 1
启动哨兵服务器

在这里插入图片描述
可以看到以哨兵模式启动后,会自动监控主节点,然后还会显示那些节点是作为从节点存在的。

主节点挂掉测试

一开始从节点还在常规报错,因为会认为主节点只是网络卡顿了,没必要急着切换主节点

在这里插入图片描述
但是一段时间之后,哨兵发现还是连接不上主节点,便开始重新选主

在这里插入图片描述
6003已经成为新的主节点

在这里插入图片描述
再次启动6001之后,发现他已经变成了6003的从节点

在这里插入图片描述
那么,这个选举规则是怎样的呢?是在所有的从节点中随机选取还是遵循某种规则呢?

  1. 首先会根据优先级进行选择,可以在配置文件中进行配置,添加replica-priority配置项(默认是100),越小表示优先级越高。
  2. 如果优先级一样,那就选择偏移量最大的
  3. 要是还选不出来,那就选择runid(启动时随机生成的)最小的。
要是哨兵也挂了咋办?

咱们可以多安排几个哨兵,只需要把哨兵的配置复制一下,然后修改端口,这样就可以同时启动多个哨兵了,我们启动3个哨兵(一主二从三哨兵),这里我们吧最后一个值改为2

sentinel monitor cuihaida 192.168.0.8 6001 2

这个值实际上代表的是当有几个哨兵认为主节点挂掉时,就判断主节点真的挂掉了

2.2:Jedis感知

在哨兵重新选举新的主节点之后,我们Java中的Redis的客户端怎么感知到呢?

<dependencies><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>4.2.1</version></dependency>
</dependencies>
public class Main {public static void main(String[] args) {try {//这里我们直接使用JedisSentinelPool来获取Master节点//需要把三个哨兵的地址都填入JedisSentinelPool pool = new JedisSentinelPool("cuihaida", new HashSet<>(Arrays.asList("192.168.0.8:26741", "192.168.0.8:26740", "192.168.0.8:26739")))) {Jedis jedis = pool.getResource();   //直接询问并得到Jedis对象,这就是连接的Master节点jedis.set("test", "114514");    //直接写入即可,实际上就是向Master节点写入Jedis jedis2 = pool.getResource();   //再次获取System.out.println(jedis2.get("test"));   //读取操作} catch (Exception e) {e.printStackTrace();}}
}

一:集群

1:集群的引入

如果我们服务器的内存不够用了,但是现在我们的Redis又需要继续存储内容,那么这个时候就可以利用集群来实现扩容。

因为单机的内存容量最大就那么多,已经没办法再继续扩展了,但是现在又需要存储更多的内容

这时我们就可以让N台机器上的Redis来分别存储各个部分的数据(每个Redis可以存储1/N的数据量),这样就实现了容量的横向扩展。

同时每台Redis还可以配一个从节点,这样就可以更好地保证数据的安全性。

在这里插入图片描述
那么问题来,现在用户来了一个写入的请求,数据该写到哪个节点上呢?

首先,一个Redis集群包含16384个插槽,集群中的每个Redis 实例负责维护一部分插槽以及插槽所映射的键值数据,那么这个插槽是什么意思呢?

实际上,插槽就是键的Hash计算后的一个结果,这里采用CRC16,能得到16个bit位的数据,也就是说算出来之后结果是0-65535之间,再进行取模,得到最终结果:

Redis key的路由计算公式:slot = CRC16(key) % 16384

结果的值是多少,就应该存放到对应维护的Redis下

比如Redis节点1负责0-25565的插槽,而这时客户端插入了一个新的数据a=10,a在Hash计算后结果为666,那么a就应该存放到1号Redis节点中。

简而言之,本质上就是通过哈希算法将插入的数据分摊到各个节点的,所以说哈希算法真的是处处都有用啊。

主从复制和哨兵机制保障了高可用,就读写分离而言虽然slave节点扩展了主从的读并发能力,但是写能力和存储能力是无法进行扩展,就只能是master节点能够承载的上限。

如果面对海量数据那么必然需要构建master(主节点分片)之间的集群,同时必然需要吸收高可用(主从复制和哨兵机制)能力,即每个master分片节点还需要有slave节点,这是分布式系统中典型的纵向扩展(集群的分片技术)的体现

所以在Redis 3.0版本中对应的设计就是Redis Cluster

在这里插入图片描述

2:设计目标

高性能可线性扩展至最多1000节点。集群中没有代理,(集群节点间)使用异步复制,没有归并操作

3:常用概念

3.1:哈希槽 hash_slot

redis分片没有使用一致性hash,而是采用了hash槽的概念,redis分片中有16284(214)个hash槽

每一个key通过校验之后对16284 mod决定放到那个槽里。分片中的每一个节点负责一部分槽。

比如集群中存在三个节点,则可能存在的一种分配如下:

  • 节点A包含0到5500号哈希槽;
  • 节点B包含5501到11000号哈希槽;
  • 节点C包含11001到16384号哈希槽。
3.2:hash_tags

hash_tags提供了一种策略,用来将多个(相关的)key分配到相同的hash槽中,这是实现muitl_key的基础。

hash_tags规则如下,如果满足如下规则,{和}之间的字符将用来计算hash槽,以保证这样的key保存在同一个slot中

  • key包含一个{字符
  • 并且 如果在这个{的右面有一个}字符
  • 并且 如果在{和}之间存在至少一个字符
--------- 举几个例子 ----------
{user1000}.following和{user1000}.followers这两个key会被hash到相同的hash slot中,因为只有user1000会被用来计算hash slot值。 foo{}{bar}这个key不会启用hash tag因为第一个{和}之间没有字符。 foozap这个key中的{bar部分会被用来计算hash slot foo{bar}{zap}这个key中的bar会被用来计算计算hash slot,而zap不会
分片nodes属性

每一个节点在分片中有唯一的名字

节点在配置文件中保存它的id,并且永久的使用这个id,直到被管理员使用CLUSTER RESET HARD命令重置节点。

节点id被用来在整个分集群中标识每个节点。一个节点可以修改自己的IP地址而不需要修改自己的id

节点ID不是唯一与节点绑定的信息,但是他是唯一的一个总是保持全局一致的字段。

3.3:集群总线

每个集群节点有一个额外的TCP端口用来接受其他节点的连接。

这个端口与用来接收client命令的普通TCP端口有一个固定的offset。该端口等于普通命令端口加上10000。

例如,一个Redis在端口6379和客户端连接,那么它的集群总线端口16379也会被打开。

节点到节点的通讯只使用集群总线,同时使用集群总线协议:有不同的类型和大小的帧组成的二进制协议。

在这里插入图片描述

集群拓扑

redis集群是一张全网拓扑,节点与其他每个节点之间都保持着TCP连接。

在一个拥有N个节点的集群中,每个节点由N-1个TCP传出连接,和N-1个TCP传入连接。 这些TCP连接总是保持活性。

当一个节点在集群总线上发送了ping请求并期待对方回复pong,(如果没有得到回复)在等待足够成时间以便将对方标记为不可达之前,它将先尝试重新连接对方以刷新与对方的连接。

而在全网拓扑中的redis集群节点,节点使用gossip协议和配置更新机制来避免在正常情况下节点之间交换过多的消息,因此集群内交换的消息数目(相对节点数目)不是指数级的。

节点握手

节点总是接受集群总线端口的链接,并且总是会回复ping请求,即使ping来自一个不可信节点。

然而,如果发送节点被认为不是当前集群的一部分,所有其他包将被抛弃

节点认定其他节点是当前集群的一部分有两种方式:

  • 如果一个节点出现在了一条MEET消息中。一条MEET消息非常像一个ping消息,但是它会强制接收者接受一个节点作为集群的一部分。节点只有在接收到系统管理员的如下命令后,才会向其他节点发送MEET消息
cluster meet ip port
  • 如果一个被信任的节点gossip了某个节点,那么接收到gossip消息的节点也会那个节点标记为集群的一部分。也就是说,如果在集群中,A知道B,而B知道C,最终B会发送gossip消息到A,告诉A节点C是集群的一部分。这时,A会把C注册未网络的一部分,并尝试与C建立连接。

🔉一旦我们把某个节点加入了连接图,它们最终会自动形成一张全连接图。这意味着只要系统管理员强制加入了一条信任关系(在某个节点上通过meet命令加入了一个新节点),集群可以自动发现其他节点

4:搭建实例

4.1:基本流程
创建六个redis服务器

在这里插入图片描述

配置修改

修改三个节点的配置【主节点端口:6001, 6002, 6003】【从节点端口:7001,7002,7003】

  • bind 127.0.0.1注释掉【56行】
  • 保护模式关闭protected-mode no【75行】
  • 设置端口【79行】
  • cluster-enabled yes解开注释 【707行】

🎉 改好一份复制redis.windows.conf到其他的服务器,然后其他的服务器只需要改端口就可以了

全部启动

⚠️ 要是起不来了,把所有的持久化文件全部删除,所有的节点内容必须是空的。

在这里插入图片描述

主从集群分配

然后输入redis-cli.exe --cluster create --cluster-replicas 1 127.0.0.1:6001 127.0.0.1:6002 127.0.0.1:6003 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003

这里的--cluster-replicas 1指的是每个节点配一个从节点:

在这里插入图片描述
输入之后,会为你展示客户端默认分配的方案,并且会询问你当前的方案是否合理。可以看到6001/6002/6003都被选为主节点,其他的为从节点,我们直接输入yes即可:

在这里插入图片描述
分配成功,可以看到插槽的分配情况

在这里插入图片描述

5:测试

随便连接一个节点,尝试插入一个值:

在这里插入图片描述
在插入时,出现了一个错误,实际上这就是因为a计算出来的哈希值(插槽),不归当前节点管,我们得去管这个插槽的节点执行

通过上面的分配情况,我们可以得到15495号插槽属于节点6003管理:

在这里插入图片描述

6:集群方式连接

以使用集群方式连接,这样我们无论在哪个节点都可以插入,只需要添加-c表示以集群模式访问:

在这里插入图片描述
可以看到,在6001节点成功对a的值进行了更新,只不过还是被重定向到了6003节点进行插入

4.2:其他说明
节点信息

我们可以输入cluster nodes命令来查看当前所有节点的信息

在这里插入图片描述

让某一个主节点挂掉会怎么样?

现在我们把6001挂掉,可以看到原本的6001从节点7001,晋升为了新的主节点,而之前的6001已经挂了

在这里插入图片描述
现在我们将6001重启,可以看到6001变成了7001的从节点

在这里插入图片描述

主从都挂了怎么办?

要是6001和7001都挂了

在这里插入图片描述
我们尝试插入新的数据,可以看到,当存在节点不可用时,会无法插入新的数据

Jedis
// 我们需要用到JedisCluster对象:
public class Main {public static void main(String[] args) {//和客户端一样,随便连一个就行,也可以多写几个,构造方法有很多种可以选择try(JedisCluster cluster = new JedisCluster(new HostAndPort("192.168.0.8", 6003))){System.out.println("集群实例数量:"+cluster.getClusterNodes().size());cluster.set("a", "yyds");System.out.println(cluster.get("a"));}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/14665.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

蓝桥杯C语言组:图论问题

蓝桥杯C语言组图论问题研究 摘要 图论是计算机科学中的一个重要分支&#xff0c;在蓝桥杯C语言组竞赛中&#xff0c;图论问题频繁出现&#xff0c;对参赛选手的算法设计和编程能力提出了较高要求。本文系统地介绍了图论的基本概念、常见算法及其在蓝桥杯C语言组中的应用&#…

在阿里云ECS上一键部署DeepSeek-R1

DeepSeek-R1 是一款开源模型&#xff0c;也提供了 API(接口)调用方式。据 DeepSeek介绍&#xff0c;DeepSeek-R1 后训练阶段大规模使用了强化学习技术&#xff0c;在只有极少标注数据的情况下提升了模型推理能力&#xff0c;该模型性能对标 OpenAl o1 正式版。DeepSeek-R1 推出…

Ollama + AnythingLLM + Deepseek r1 实现本地知识库

1、Ollama&#xff1a;‌是一个开源的大型语言模型 (LLM)服务工具&#xff0c;旨在简化在本地运行大语言模型的过程&#xff0c;降低使用大语言模型的门槛‌。 2、AnythingLLM&#xff1a;是由Mintplex Labs Inc. 开发的一款全栈应用程序&#xff0c;旨在构建一个高效、可定制、…

(Arxiv-2023)HiPA: 通过高频增强自适应实现一步文本到图像扩散模型

HiPA: 通过高频增强自适应实现一步文本到图像扩散模型 paper是NUS发布在Arxiv 2023的工作 paper title:HiPA: Enabling One-Step Text-to-Image Diffusion Models via High-Frequency-Promoting Adaptation Code&#xff1a;等待开源 Abstract 扩散模型已彻底改变了文本到图像…

Java版本与JDK版本

两者关联 Java版本指的Java语言和平台的版本&#xff0c;例如Java8、Java11、Java17等&#xff0c;每个版本会引入新特性、改进和修复。 JDK(Java Development Kit)版本则是开发工具包&#xff0c;包含编译器、调试器等工具&#xff0c;通常与Java版本对应&#xff0c;例如JDK…

【C语言标准库函数】三角函数

目录 一、头文件 二、函数简介 2.1. 正弦函数&#xff1a;sin(double angle) 2.2. 余弦函数&#xff1a;cos(double angle) 2.3. 正切函数&#xff1a;tan(double angle) 2.4. 反正弦函数&#xff1a;asin(double value) 2.5. 反余弦函数&#xff1a;acos(double value)…

活动预告 |【Part 2】Microsoft 安全在线技术公开课:通过扩展检测和响应抵御威胁

课程介绍 通过 Microsoft Learn 免费参加 Microsoft 安全在线技术公开课&#xff0c;掌握创造新机遇所需的技能&#xff0c;加快对 Microsoft Cloud 技术的了解。参加我们举办的“通过扩展检测和响应抵御威胁”技术公开课活动&#xff0c;了解如何更好地在 Microsoft 365 Defen…

MySQL第五次作业

根据图片内容完成作业 1.建表 &#xff08;1&#xff09;建立两个表:goods(商品表)、orders(订单表) mysql> create table goods( -> gid char(8) primary key, -> name varchar(10), -> price decimal(8,2), -> num int); mysql> create t…

Breakout靶场小试牛刀

1.首先经典两件套 nmap -A 扫描 发现开放很多端口&#xff08;80&#xff0c;10000&#xff0c;20000为重点关注&#xff09; 问题不大&#xff0c;先dirsearch扫一下目录再说 结果能看的manual里啥也没有&#xff0c;之后再查看80端口界面源代码 发现有一串字符 但是问了ai…

Vue el-tree 加载过滤出的父节点以及其包含的子节点

由于el-tree提供的过滤函数&#xff0c;过滤出来的目录节点不包含子节点&#xff0c;因此需要改造过滤函数&#xff0c;使其过滤出的目录节点包含子节点。 <template><div><el-input placeholder"请输入内容" v-model"filterText" clearab…

认识O(NlogN)的排序

归并排序 归并排序&#xff08;任何一个递归&#xff09;如果不懂可以画一个树状结构去帮助自己去理解。 核心排序方法为Merger public class 归并排序 {public static void main(String[] args) {int[] arr1 {3, 1, 2, 2, 5, 6};int[] arr2 Arrays.copyOf(arr1, arr1.len…

如何使用Gemini模型,国内如何订阅购买Gemini Pro的教程,Gemini Pro 免费试用操作步骤, 谷歌 aistudio 使用入口

最近的榜首又被Gemini给霸占了&#xff0c;很多童鞋想要体验一翻 Gemini免费库模型更新了 Gemini2.0向所有人开放了&#xff01;使用了真香 目前呢2.0flash和Gemini-2.0-Flash-Thinking-Exp、Gemini-2.0-Flash-Thinking-Exp-with-apps已经免费给所有注册用户开放了&#xff0c…

【数据结构】(7) 栈和队列

一、栈 Stack 1、什么是栈 栈是一种特殊的线性表&#xff0c;它只能在固定的一端&#xff08;栈顶&#xff09;进行出栈、压栈操作&#xff0c;具有后进先出的特点。 2、栈概念的例题 答案为 C&#xff0c;以C为例进行讲解&#xff1a; 第一个出栈的是3&#xff0c;那么 1、…

安宝特方案 | AR助力制造业安全巡检智能化革命!

引言&#xff1a; 在制造业中&#xff0c;传统巡检常面临流程繁琐、质量波动、数据难以追溯等问题。安宝特AR工作流程标准化解决方案&#xff0c;通过增强现实AR技术&#xff0c;重塑制造业安全巡检模式&#xff0c;以标准化作业流程为核心&#xff0c;全面提升效率、质量与…

语言月赛 202308【小粉兔做麻辣兔头】题解(AC)

》》》点我查看「视频」详解》》》 [语言月赛 202308] 小粉兔做麻辣兔头 题目描述 粉兔喜欢吃麻辣兔头&#xff0c;麻辣兔头的辣度分为若干级&#xff0c;用数字表示&#xff0c;数字越大&#xff0c;兔头越辣。为了庆祝粉兔专题赛 #1 的顺利举行&#xff0c;粉兔要做一些麻…

Dify Ollama本地私有化模型实践

今天给大家带来一篇deepseek本地部署&#xff0c;笔者最近由于研究AI大模型应用开发&#xff0c;笔记较少&#xff0c;后面将持续输出关于AI行业应用知识&#xff0c;请大家继续关注&#xff0c;话不多说&#xff0c;开始吧&#xff0c;啊哈哈。 DeepSeek 呢&#xff0c;最近十…

Kafka中的KRaft算法

我们之前的Kafka值依赖于Zookeeper注册中心来启动的&#xff0c;往里面注册我们节点信息 Kafka是什么时候不依赖Zookeeper节点了 在Kafka2.8.0开始就可以不依赖Zookeeper了 可以用KRaft模式代替Zookeeper管理Kafka集群 KRaft Controller和KRaft Leader的关系 两者关系 Lea…

GitPuk快速安装配置教程(入门级)

GitPuk是一款国产开源免费的代码管理工具&#xff0c;工具简洁易用&#xff0c;开源免费&#xff0c;本文将讲解如何快速安装和配置GitPuk&#xff0c;以快速入门上手。 1、安装 支持 Windows、Mac、Linux、docker 等操作系统。 1.1 Linux安装&#xfeff; 以下以Centos7安装…

2025年02月08日Github流行趋势

项目名称&#xff1a;anything-llm 项目地址url&#xff1a;https://github.com/Mintplex-Labs/anything-llm项目语言&#xff1a;JavaScript历史star数&#xff1a;34323今日star数&#xff1a;675项目维护者&#xff1a;timothycarambat, shatfield4, MrSimonC, franzbischof…

【C语言标准库函数】指数与对数函数:exp(), log(), log10()

目录 一、头文件 二、函数简介 2.1. exp(double x) 2.2. log(double x) 2.3. log10(double x) 三、函数实现&#xff08;概念性&#xff09; 3.1. exp(double x) 的模拟实现 3.2. log(double x) 和 log10(double x) 的模拟实现 四、注意事项 4.1. exp(double x) 的注…