Java中高级核心知识全面解析——Redis(集群【概述{主从复制、哨兵、集群化}、数据分区方案、节点通信机制、数据结构简析】)5

Spring-Data-Redis下实现redis连接断开后自动重连(真正解决) 原先使用jedis的时候,处理手段是在从连接池获取连接时捕获JedisConnectionException异常,在异常处理部分重新获取连接,但是spring data redis似乎不会,如下所示: org.springframework.data.redis.RedisConnectionFailureException: java.net.SocketException: Connec... 阅读详情

一、[集群]入门实践教程

1.Redis 集群概述

1)Redis 主从复制

到目前为止,我们所学习的 Redis 都是 单机版 的,这也就意味着一旦我们所依赖的 Redis 服务宕机了,我们的主流程也会受到一定的影响,这当然是我们不能够接受的。

所以一开始我们的想法是:搞一台备用机。这样我们就可以在一台服务器出现问题的时候切换动态地到另一台去:

幸运的是,两个节点数据的同步我们可以使用 Redis 的 主从同步 功能帮助到我们,这样一来,有个备份,心里就踏实多了。

2)Redis 哨兵

后来因为某种神秘力量,Redis 老会在莫名其妙的时间点出问题 (比如半夜 2 点),我总不能 24 小时时刻守在电脑旁边切换节点吧,于是另一个想法又开始了:给所有的节点找一个**“管家”,自动帮我监听照顾节点的状态并切换:

这大概就是
Redis 哨兵 (Sentinel)** 的简单理解啦。什么?管家宕机了怎么办?相较于有大量请求的Redis服务来说,管家宕机的概率就要小得多啦… 如果真的宕机了,我们也可以直接切换成当前可用的节点保证可用…

3)Redis 集群化

好了,通过上面的一些解决方案我们对 Redis 的 稳定性 稍微有了一些底气了,但单台节点的计算能力始终有限,所谓人多力量大,如果我们把 多个节点组合 成 一个可用的工作节点,那就大大增加了Redis 的 高可用、可扩展、分布式、容错 等特性:

2.主从复制


主从复制,是指将一台 Redis 服务器的数据,复制到其他的 Redis 服务器。前者称为 主节点(master),后者称为 从节点(slave)。且数据的复制是 单向 的,只能由主节点到从节点。Redis 主从复制支持 主从同步 和 从从同步两种,后者是 Redis 后续版本新增的功能,以减轻主节点的同步负担。

1)主从复制主要的作用

  • 数据冗余: 主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
  • 故障恢复: 当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复 (实际上是一种服务的冗余)。
  • 负载均衡: 在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务 (即写 Redis 数据时应用连接主节点,读 Redis 数据时应用连接从节点),分担服务器负载。尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高 Redis 服务器的并发量。
  • 高可用基石: 除了上述作用以外,主从复制还是哨兵和集群能够实施的 基础,因此说主从复制是 Redis 高可用的基础。

2)快速体验

在 Redis 中,用户可以通过执行 SLAVEOF 命令或者设置 slaveof 选项,让一个服务器去复制另一个服务器,以下三种方式是 完全等效 的:

  • 配置文件:在从服务器的配置文件中加入: slaveof <masterip> <masterport>
  • 启动命令:redis-server 启动命令后加入 --slaveof <masterip> <masterport>
  • 客户端命令:Redis 服务器启动后,直接通过客户端执行命令: slaveof <masterip> <masterport>,让该 Redis 实例成为从节点。

需要注意的是:主从复制的开启,完全是在从节点发起的,不需要我们在主节点做任何事情。

①、第一步:本地启动两个节点

在正确安装好 Redis 之后,我们可以使用 redis-server --port <port> 的方式指定创建两个不同端口的 Redis 实例,例如,下方我分别创建了一个6379 和 6380 的两个 Redis 实例:

# 创建一个端口为 6379 的 Redis 实例 
redis-server --port 6379 
# 创建一个端口为 6380 的 Redis 实例 
redis-server --port 6380

此时两个 Redis 节点启动后,都默认为 主节点。

②、第二步:建立复制

我们在 6380 端口的节点中执行 slaveof 命令,使之变为从节点:

# 在 6380 端口的 Redis 实例中使用控制台 
redis-cli -p 6380 
# 成为本地 6379 端口实例的从节点 
127.0.0.1:6380> SLAVEOF 127.0.0.1ø 6379 
OK
③、第三步:观察效果

下面我们来验证一下,主节点的数据是否会复制到从节点之中:

  • 先在 从节点 中查询一个 不存在 的 key:
127.0.0.1:6380> GET mykey 
(nil)
  • 再在 主节点 中添加这个 key:
127.0.0.1:6379> SET mykey myvalue 
OK
  • 此时再从 从节点 中查询,会发现已经从 主节点 同步到 从节点:
127.0.0.1:6380> GET mykey 
"myvalue"
④、第四步:断开复制

通过 slaveof <masterip> <masterport> 命令建立主从复制关系以后,可以通过 slaveof no one 断开。需要注意的是,从节点断开复制后,不会删除已有的数据,只是不再接受主节点新的数据变化。

从节点执行 slaveof no one 之后,从节点和主节点分别打印日志如下:

# 从节点打印日志 
61496:M 17 Mar 2020 08:10:22.749 # Connection with master lost. 
61496:M 17 Mar 2020 08:10:22.749 * Caching the disconnected master state. 
61496:M 17 Mar 2020 08:10:22.749 * Discarding previously cached master state. 
61496:M 17 Mar 2020 08:10:22.749 * MASTER MODE enabled (user request from 'id=4 addr=127.0.0.1:55096 fd=8 name= age=1664 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=34 qbuf-free=32734 obl=0 oll=0 omem=0 events=r cmd=slaveof') 

# 主节点打印日志 
61467:M 17 Mar 2020 08:10:22.749 # Connection with replica 127.0.0.1:6380 lost.

3)实现原理简析


为了节省篇幅,我把主要的步骤都 浓缩 在了上图中,其实也可以 **简化成三个阶段:准备阶段-数据同步阶段-命令传播阶段。**下面我们来进行一些必要的说明。

①、身份验证 | 主从复制安全问题

在上面的 快速体验 过程中,你会发现 slaveof 这个命令居然不需要验证?这意味着只要知道了 ip 和端口就可以随意拷贝服务器上的数据了?

那当然不能够了,我们可以通过在 主节点 配置 requirepass 来设置密码,这样就必须在 从节点 中对应配置好 masterauth 参数 (与主节点 requirepass 保持一致) 才能够进行正常复制了。

②、SYNC 命令是一个非常耗费资源的操作

每次执行 SYNC 命令,主从服务器需要执行如下动作:

  1. 主服务器 需要执行 BGSAVE 命令来生成 RDB 文件,这个生成操作会 消耗 主服务器大量的 CPU、内存和磁盘 I/O 的资源;
  2. 主服务器 需要将自己生成的 RDB 文件 发送给从服务器,这个发送操作会 消耗 主服务器 大量的网络资源 (带宽和流量),并对主服务器响应命令请求的时间产生影响;
  3. 接收到 RDB 文件的 从服务器 需要载入主服务器发来的 RBD 文件,并且在载入期间,从服务器会因为阻塞而没办法处理命令请求;

特别是当出现 断线重复制 的情况是时,为了让从服务器补足断线时确实的那一小部分数据,却要执行一次如此耗资源的 SYNC 命令,显然是不合理的。

③、PSYNC 命令的引入

所以在 Redis 2.8 中引入了 PSYNC 命令来代替 SYNC ,它具有两种模式:

  1. 全量复制: 用于初次复制或其他无法进行部分复制的情况,将主节点中的所有数据都发送给从节点,是一个非常重型的操作;
  2. 部分复制: 用于网络中断等情况后的复制,只将 中断期间主节点执行的写命令 发送给从节点,与全量复制相比更加高效。需要注意 的是,如果网络中断时间过长,导致主节点没有能够完整地保存中断期间执行的写命令,则无法进行部分复制,仍使用全量复制;

部分复制的原理主要是靠主从节点分别维护一个 复制偏移量,有了这个偏移量之后断线重连之后一比较,之后就可以仅仅把从服务器断线之后确实的这部分数据给补回来了。

3.Redis Sentinel 哨兵


上图展示了一个典型的哨兵架构图,它由两部分组成,哨兵节点和数据节点:

  • 哨兵节点: 哨兵系统由一个或多个哨兵节点组成,哨兵节点是特殊的 Redis 节点,不存储数据;
  • 数据节点: 主节点和从节点都是数据节点;

在复制的基础上,哨兵实现了 自动化的故障恢复 功能,下方是官方对于哨兵功能的描述:

  • 监控(Monitoring): 哨兵会不断地检查主节点和从节点是否运作正常。
  • 自动故障转移(Automatic failover): 当 主节点 不能正常工作时,哨兵会开始 自动故障转移操作,它会将失效主节点的其中一个 从节点升级为新的主节点,并让其他从节点改为复制新的主节点。
  • 配置提供者(Configuration provider): 客户端在初始化时,通过连接哨兵来获得当前 Redis服务的主节点地址。
  • 通知(Notification): 哨兵可以将故障转移的结果发送给客户端。

其中,监控和自动故障转移功能,使得哨兵可以及时发现主节点故障并完成转移。而配置提供者和通知功能,则需要在与客户端的交互中才能体现。

1)快速体验

①、第一步:创建主从节点配置文件并启动

正确安装好 Redis 之后,我们去到 Redis 的安装目录 (mac 默认在 /usr/local/ ),找到 redis.conf文件复制三份分别命名为 redis-master.conf / redis-slave1.conf / redis-slave2.conf ,分别作为1 个主节点和2 个从节点的配置文件 (下图演示了我本机的 redis.conf 文件的位置)

打开可以看到这个 .conf 后缀的文件里面有很多说明的内容,全部删除然后分别改成下面的样子:

#redis-master.conf 
port 6379 
daemonize yes 
logfile "6379.log" 
dbfilename "dump-6379.rdb" 

#redis-slave1.conf 
port 6380 
daemonize yes 
logfile "6380.log" 
dbfilename "dump-6380.rdb" 
slaveof 127.0.0.1 6379 

#redis-slave2.conf 
port 6381 
daemonize yes 
logfile "6381.log" 
dbfilename "dump-6381.rdb" 
slaveof 127.0.0.1 6379

然后我们可以执行 redis-server <config file path> 来根据配置文件启动不同的 Redis 实例,依次启动主从节点:

redis-server /usr/local/redis-5.0.3/redis-master.conf 
redis-server /usr/local/redis-5.0.3/redis-slave1.conf 
redis-server /usr/local/redis-5.0.3/redis-slave2.conf

节点启动后,我们执行 redis-cli 默认连接到我们端口为 6379 的主节点执行 info Replication 检查一下主从状态是否正常:(可以看到下方正确地显示了两个从节点)


小插曲:
更多阿里、腾讯、美团、京东等一线互联网大厂Java面试真题;包含:基础、并发、锁、JVM、设计模式、数据结构、反射/IO、数据库、Redis、Spring、消息队列、分布式、Zookeeper、Dubbo、Mybatis、Maven、面经等。
更多Java程序员技术进阶小技巧;例如高效学习(如何学习和阅读代码、面对枯燥和量大的知识)高效沟通(沟通方式及技巧、沟通技术)
更多Java大牛分享的一些职业生涯分享文档


请点击这里添加》》》》》》》》》社群,免费获取


比你优秀的对手在学习,你的仇人在磨刀,你的闺蜜在减肥,隔壁老王在练腰, 我们必须不断学习,否则我们将被学习者超越!
趁年轻,使劲拼,给未来的自己一个交代!

②、第二步:创建哨兵节点配置文件并启动

按照上面同样的方法,我们给哨兵节点也创建三个配置文件。(哨兵节点本质上是特殊的 Redis 节点,所以配置几乎没什么差别,只是在端口上做区分就好)

# redis-sentinel-1.conf 
port 26379 
daemonize yes 
logfile "26379.log" 
sentinel monitor mymaster 127.0.0.1 6379 2 

# redis-sentinel-2.conf 
port 26380 
daemonize yes 
logfile "26380.log" 
sentinel monitor mymaster 127.0.0.1 6379 2 

# redis-sentinel-3.conf 
port 26381 
daemonize yes 
logfile "26381.log" 
sentinel monitor mymaster 127.0.0.1 6379 2

其中, sentinel monitor mymaster 127.0.0.1 6379 2 配置的含义是:该哨兵节点监控 127.0.0.1:6379 这个主节点,该主节点的名称是 mymaster ,最后的 2 的含义与主节点的故障判定有关:至少需要 2 个哨兵节点同意,才能判定主节点故障并进行故障转移。

执行下方命令将哨兵节点启动起来:

redis-server /usr/local/redis-5.0.3/redis-sentinel-1.conf --sentinel 
redis-server /usr/local/redis-5.0.3/redis-sentinel-2.conf --sentinel 
redis-server /usr/local/redis-5.0.3/redis-sentinel-3.conf --sentinel

使用 redis-cil 工具连接哨兵节点,并执行 info Sentinel 命令来查看是否已经在监视主节点了:

# 连接端口为 26379 的 Redis 节点 
➜ ~ redis-cli -p 26379 
127.0.0.1:26379> info Sentinel 
# Sentinel 
sentinel_masters:1 
sentinel_tilt:0 
sentinel_running_scripts:0 
sentinel_scripts_queue_length:0 
sentinel_simulate_failure_flags:0 master0:name=mymaster,status=ok,address=127.0.0.1:6379,slaves=2,sentinels=3

此时你打开刚才写好的哨兵配置文件,你还会发现出现了一些变化:

③、第三步:演示故障转移

首先,我们使用 kill -9 命令来杀掉主节点,同时 在哨兵节点中执行 info Sentinel 命令来观察故障节点的过程:

➜ ~ ps aux | grep 6379 
longtao 	74529 	0.3 	0.0 	4346936 	2132 	?? 	Ss 	10:30上午 	0:03.09 
redis-server *:26379 [sentinel] 
longtao 	73541 	0.2 	0.0 	4348072 	2292 	?? 	Ss 	10:18上午 	0:04.79 
redis-server *:6379 
longtao 	75521 	0.0 	0.0 	4286728 	728 s008 	S+ 	10:39上午 	0:00.00 
grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git -- exclude-dir=.hg --exclude-dir=.svn 6379 
longtao 	74836 	0.0 	0.0 	4289844 	944 s006 	S+ 	10:32上午 	0:00.01 
redis-cli -p 26379 
➜ ~ kill -9 73541

如果 刚杀掉瞬间 在哨兵节点中执行 info 命令来查看,会发现主节点还没有切换过来,因为哨兵发现主节点故障并转移需要一段时间:

# 第一时间查看哨兵节点发现并未转移,还在 6379 端口 
127.0.0.1:26379> info Sentinel 
# Sentinel 
sentinel_masters:1 
sentinel_tilt:0 sentinel_running_scripts:0 
sentinel_scripts_queue_length:0 
sentinel_simulate_failure_flags:0 
master0:name=mymaster,status=ok,address=127.0.0.1:6379,slaves=2,sentinels=3

一段时间之后你再执行 info 命令,查看,你就会发现主节点已经切换成了 6381 端口的从节点:

# 过一段时间之后在执行,发现已经切换了 6381 端口 
127.0.0.1:26379> info Sentinel 
# Sentinel 
sentinel_masters:1 
sentinel_tilt:0 
sentinel_running_scripts:0 
sentinel_scripts_queue_length:0 
sentinel_simulate_failure_flags:0 
master0:name=mymaster,status=ok,address=127.0.0.1:6381,slaves=2,sentinels=3

但同时还可以发现,哨兵节点认为新的主节点仍然有两个从节点 (上方 slaves=2),这是因为哨兵在将 6381 切换成主节点的同时,将 6379 节点置为其从节点。虽然 6379 从节点已经挂掉,但是由于 哨兵并不会对从节点进行客观下线,因此认为该从节点一直存在。当 6379 节点重新启动后,会自动变成6381 节点的从节点。

另外,在故障转移的阶段,哨兵和主从节点的配置文件都会被改写:

  • 对于主从节点: 主要是 slaveof 配置的变化,新的主节点没有了 slaveof 配置,其从节点则slaveof 新的主节点。
  • 对于哨兵节点: 除了主从节点信息的变化,纪元(epoch) (记录当前集群状态的参数) 也会变化,纪元相关的参数都 +1 了。

2)客户端访问哨兵系统代码演示

上面我们在 快速体验 中主要感受到了服务端自己对于当前主从节点的自动化治理,下面我们以 Java 代码为例,来演示一下客户端如何访问我们的哨兵系统:

public static void testSentinel() throws Exception { 
	String masterName = "mymaster"; 
	Set<String> sentinels = new HashSet<>(); 
	sentinels.add("127.0.0.1:26379"); 
	sentinels.add("127.0.0.1:26380"); 
	sentinels.add("127.0.0.1:26381"); 
	
	// 初始化过程做了很多工作 
	JedisSentinelPool pool = new JedisSentinelPool(masterName, sentinels); 
	Jedis jedis = pool.getResource(); 
	jedis.set("key1", "value1"); 
	pool.close(); 
}
①、客户端原理

Jedis 客户端对哨兵提供了很好的支持。如上述代码所示,我们只需要向 Jedis 提供哨兵节点集合和 masterName ,构造 JedisSentinelPool 对象,然后便可以像使用普通 Redis 连接池一样来使用了:通过 pool.getResource() 获取连接,执行具体的命令。

在整个过程中,我们的代码不需要显式的指定主节点的地址,就可以连接到主节点;代码中对故障转移没有任何体现,就可以在哨兵完成故障转移后自动的切换主节点。之所以可以做到这一点,是因为在 JedisSentinelPool 的构造器中,进行了相关的工作;主要包括以下两点:

  1. 遍历哨兵节点,获取主节点信息: 遍历哨兵节点,通过其中一个哨兵节点 + masterName 获得主节点的信息;该功能是通过调用哨兵节点的 sentinel get-master-addr-by-name 命令实现;
  2. 增加对哨兵的监听: 这样当发生故障转移时,客户端便可以收到哨兵的通知,从而完成主节点的切换。具体做法是:利用 Redis 提供的 发布订阅 功能,为每一个哨兵节点开启一个单独的线程,订阅哨兵节点的 + switch-master 频道,当收到消息时,重新初始化连接池。

3)新的主服务器是怎样被挑选出来的?

故障转移操作的第一步 要做的就是在已下线主服务器属下的所有从服务器中,挑选出一个状态良好、数据完整的从服务器,然后向这个从服务器发送 slaveof no one 命令,将这个从服务器转换为主服务器。但是这个从服务器是怎么样被挑选出来的呢?

简单来说 Sentinel 使用以下规则来选择新的主服务器:

  1. 在失效主服务器属下的从服务器当中, 那些被标记为主观下线、已断线、或者最后一次回复 PING 命令的时间大于五秒钟的从服务器都会被 淘汰。
  2. 在失效主服务器属下的从服务器当中, 那些与失效主服务器连接断开的时长超过 down-after 选项指定的时长十倍的从服务器都会被 淘汰。
  3. 在 经历了以上两轮淘汰之后 剩下来的从服务器中, 我们选出 复制偏移量(replication offset)最大 的那个 从服务器 作为新的主服务器;如果复制偏移量不可用,或者从服务器的复制偏移量相同,那么 带有最小运行 ID 的那个从服务器成为新的主服务器。

4.Redis 集群


上图 展示了 Redis Cluster 典型的架构图,集群中的每一个 Redis 节点都 互相两两相连,客户端任意直连 到集群中的 任意一台,就可以对其他 Redis 节点进行 读写 的操作。

1)基本原理


Redis 集群中内置了 16384 个哈希槽。当客户端连接到 Redis 集群之后,会同时得到一份关于这个 集群的配置信息,当客户端具体对某一个 key 值进行操作时,会计算出它的一个 Hash 值,然后把结果对 16384 求余数,这样每个key 都会对应一个编号在 0-16383 之间的哈希槽,Redis 会根据节点数量 大致均等 的将哈希槽映射到不同的节点。

再结合集群的配置信息就能够知道这个 key 值应该存储在哪一个具体的 Redis 节点中,如果不属于自己管,那么就会使用一个特殊的 MOVED 命令来进行一个跳转,告诉客户端去连接这个节点以获取数据:

GET x 
-MOVED 3999 127.0.0.1:6381

MOVED 指令第一个参数 3999 是 key 对应的槽位编号,后面是目标节点地址, MOVED 命令前面有一个减号,表示这是一个错误的消息。客户端在收到 MOVED 指令后,就立即纠正本地的 槽位映射表,那么下一次再访问 key 时就能够到正确的地方去获取了。

2)集群的主要作用

  1. 数据分区: 数据分区 (或称数据分片) 是集群最核心的功能。集群将数据分散到多个节点,一方面突破了 Redis 单机内存大小的限制,存储容量大大增加;另一方面 每个主节点都可以对外提供读服务和写服务,大大提高了集群的响应能力。Redis 单机内存大小受限问题,在介绍持久化和主从复制时都有提及,例如,如果单机内存太大, bgsave 和 bgrewriteaof 的 fork 操作可能导致主进程阻塞,主从环境下主机切换时可能导致从节点长时间无法提供服务,全量复制阶段主节点的复制缓冲区可能溢出……
  2. 高可用: 集群支持主从复制和主节点的 自动故障转移 (与哨兵类似),当任一节点发生故障时,集群仍然可以对外提供服务。

3)快速体验

①、第一步:创建集群节点配置文件

首先我们找一个地方创建一个名为 redis-cluster 的目录:


小插曲:
更多阿里、腾讯、美团、京东等一线互联网大厂Java面试真题;包含:基础、并发、锁、JVM、设计模式、数据结构、反射/IO、数据库、Redis、Spring、消息队列、分布式、Zookeeper、Dubbo、Mybatis、Maven、面经等。
更多Java程序员技术进阶小技巧;例如高效学习(如何学习和阅读代码、面对枯燥和量大的知识)高效沟通(沟通方式及技巧、沟通技术)
更多Java大牛分享的一些职业生涯分享文档


请点击这里添加》》》》》》》》》社群,免费获取


比你优秀的对手在学习,你的仇人在磨刀,你的闺蜜在减肥,隔壁老王在练腰, 我们必须不断学习,否则我们将被学习者超越!
趁年轻,使劲拼,给未来的自己一个交代!

mkdir -p ~/Desktop/redis-cluster

然后按照上面的方法,创建六个配置文件,分别命名为:redis_7000.conf / redis_7001.conf … redis_7005.conf,然后根据不同的端口号修改对应的端口值就好了:

# 后台执行 
daemonize yes 
# 端口号 
port 7000 
# 为每一个集群节点指定一个 pid_file 
pidfile ~/Desktop/redis-cluster/redis_7000.pid 
# 启动集群模式 
cluster-enabled yes 
# 每一个集群节点都有一个配置文件,这个文件是不能手动编辑的。确保每一个集群节点的配置文件不通 
cluster-config-file nodes-7000.conf 
# 集群节点的超时时间,单位:ms,超时后集群会认为该节点失败 
cluster-node-timeout 5000 
# 最后将 appendonly 改成 yes(AOF 持久化) 
appendonly yes

记得把对应上述配置文件中根端口对应的配置都修改掉 (port/ pidfile/ cluster-config-file)。

②、第二步:分别启动 6 个 Redis 实例
redis-server ~/Desktop/redis-cluster/redis_7000.conf 
redis-server ~/Desktop/redis-cluster/redis_7001.conf 
redis-server ~/Desktop/redis-cluster/redis_7002.conf 
redis-server ~/Desktop/redis-cluster/redis_7003.conf 
redis-server ~/Desktop/redis-cluster/redis_7004.conf 
redis-server ~/Desktop/redis-cluster/redis_7005.conf

然后执行 ps -ef | grep redis 查看是否启动成功:

可以看到 6 个 Redis 节点都以集群的方式成功启动了,但是现在每个节点还处于独立的状态,也就是说它们每一个都各自成了一个集群,还没有互相联系起来,我们需要手动地把他们之间建立起联系。

③、第三步:建立集群

执行下列命令:

redis-cli --cluster create --cluster-replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
  • 这里稍微解释一下这个 --replicas 1 的意思是:我们希望为集群中的每个主节点创建一个从节点。

观察控制台输出:

看到 [OK] 的信息之后,就表示集群已经搭建成功了,可以看到,这里我们正确地创建了三主三从的集群。

④、第四步:验证集群

我们先使用 redic-cli 任意连接一个节点:

redis-cli -c -h 127.0.0.1 -p 7000 
127.0.0.1:7000>
  • -c 表示集群模式;-h 指定 ip 地址; -p 指定端口。

然后随便 set 一些值观察控制台输入:

127.0.0.1:7000> SET name wmyskxz 
-> Redirected to slot [5798] located at 127.0.0.1:7001 
OK
127.0.0.1:7001>

可以看到这里 Redis 自动帮我们进行了Redirected操作跳转到了7001这个实例上。

我们再使用 cluster info (查看集群信息) 和 cluster nodes (查看节点列表) 来分别看看:(任意节点输入均可)

127.0.0.1:7001> CLUSTER INFO 
cluster_state:ok 
cluster_slots_assigned:16384 
cluster_slots_ok:16384 
cluster_slots_pfail:0 
cluster_slots_fail:0 
cluster_known_nodes:6 
cluster_size:3 
cluster_current_epoch:6 
cluster_my_epoch:2 
cluster_stats_messages_ping_sent:1365 
cluster_stats_messages_pong_sent:1358 
cluster_stats_messages_meet_sent:4 
cluster_stats_messages_sent:2727 
cluster_stats_messages_ping_received:1357 
cluster_stats_messages_pong_received:1369 
cluster_stats_messages_meet_received:1 
cluster_stats_messages_received:2727 

127.0.0.1:7001> CLUSTER NODES 
56a04742f36c6e84968cae871cd438935081e86f 127.0.0.1:7003@17003 slave 
4ec8c022e9d546c9b51deb9d85f6cf867bf73db6 0 1584428884000 4 connected 
4ec8c022e9d546c9b51deb9d85f6cf867bf73db6 127.0.0.1:7000@17000 master - 0 
1584428884000 1 connected 0-5460 
e2539c4398b8258d3f9ffa714bd778da107cb2cd 127.0.0.1:7005@17005 slave 
a3406db9ae7144d17eb7df5bffe8b70bb5dd06b8 0 1584428885222 6 connected 
d31cd1f423ab1e1849cac01ae927e4b6950f55d9 127.0.0.1:7004@17004 slave 
236cefaa9cdc295bc60a5bd1aed6a7152d4f384d 0 1584428884209 5 connected 
236cefaa9cdc295bc60a5bd1aed6a7152d4f384d 127.0.0.1:7001@17001 myself,master - 0 
1584428882000 2 connected 5461-10922 
a3406db9ae7144d17eb7df5bffe8b70bb5dd06b8 127.0.0.1:7002@17002 master - 0 1584428884000 3 connected 10923-16383 
127.0.0.1:7001>

5)数据分区方案简析

①、方案一:哈希值 % 节点数

哈希取余分区思路非常简单:计算 key 的 hash 值,然后对节点数量进行取余,从而决定数据映射到哪个节点上。

不过该方案最大的问题是,当新增或删减节点时,节点数量发生变化,系统中所有的数据都需要 重新计算映射关系,引发大规模数据迁移。

②、方案二:一致性哈希分区



与哈希取余分区相比,一致性哈希分区将 增减节点的影响限制在相邻节点。以上图为例,如果在node1 和 node2 之间增加 node5 ,则只有node2 中的一部分数据会迁移到 node5 ;如果去掉node2 ,则原 node2 中的数据只会迁移到 node4 中,只有 node4 会受影响。

一致性哈希分区的主要问题在于,当 节点数量较少 时,增加或删减节点,对单个节点的影响可能很大,造成数据的严重不平衡。还是以上图为例,如果去掉 node2 , node4中的数据由总数据的1/4左右变为 1/2 左右,与其他节点相比负载过高。

③、方案三:带有虚拟节点的一致性哈希分区

该方案在 一致性哈希分区的基础上,引入了 虚拟节点 的概念。Redis 集群使用的便是该方案,其中的虚拟节点称为 槽(slot)。槽是介于数据和实际节点之间的虚拟概念,每个实际节点包含一定数量的槽,每个槽包含哈希值在一定范围内的数据。

在使用了槽的一致性哈希分区中,槽是数据管理和迁移的基本单位。槽 解耦 了 数据和实际节点 之间的关系,增加或删除节点对系统的影响很小。仍以上图为例,系统中有 4 个实际节点,假设为其分配16个槽(0-15);

  • 槽 0-3 位于 node1;4-7 位于 node2;以此类推…

如果此时删除 node2 ,只需要将槽 4-7 重新分配即可,例如槽 4-5 分配给 node1 ,槽 6 分配给 node3 ,槽 7 分配给 node4 ;可以看出删除 node2 后,数据在其他节点的分布仍然较为均衡。

6)节点通信机制简析

集群的建立离不开节点之间的通信,例如我们上访在 快速体验 中刚启动六个集群节点之后通过 redis- cli 命令帮助我们搭建起来了集群,实际上背后每个集群之间的两两连接是通过了 CLUSTER MEET <ip> <port> 命令发送 MEET 消息完成的,下面我们展开详细说说。

①、两个端口

在哨兵系统中,节点分为数据节点和哨兵节点:前者存储数据,后者实现额外的控制功能。在 集群中,没有数据节点与非数据节点之分:所有的节点都存储数据,也都参与集群状态的维护。为此,集群中的每个节点,都提供了两个 TCP 端口:

  • 普通端口: 即我们在前面指定的端口 (7000等)。普通端口主要用于为客户端提供服务 (与单机节 点类似);但在节点间数据迁移时也会使用。
  • 集群端口: 端口号是普通端口 + 10000 (10000是固定值,无法改变),如 7000 节点的集群端口为 17000 。集群端口只用于节点之间的通信,如搭建集群、增减节点、故障转移等操作时节点间的通信;不要使用客户端连接集群接口。为了保证集群可以正常工作,在配置防火墙时,要同时开启普通端口和集群端口。
②Gossip 协议

节点间通信,按照通信协议可以分为几种类型:单对单、广播、Gossip 协议等。重点是广播和 Gossip的对比。

  • 广播是指向集群内所有节点发送消息。优点 是集群的收敛速度快(集群收敛是指集群内所有节点获得的集群信息是一致的),缺点 是每条消息都要发送给所有节点,CPU、带宽等消耗较大。
  • Gossip 协议的特点是:在节点数量有限的网络中,每个节点都 “随机” 的与部分节点通信 (并不 是真正的随机,而是根据特定的规则选择通信的节点),经过一番杂乱无章的通信,每个节点的状态很快会达到一致。Gossip 协议的 优点 有负载 (比广播) 低、去中心化、容错性高 (因为通信有冗余) 等;缺点 主要是集群的收敛速度慢。
③、消息类型

集群中的节点采用 固定频率(每秒10次) 的 定时任务 进行通信相关的工作:判断是否需要发送消息及消息类型、确定接收节点、发送消息等。如果集群状态发生了变化,如增减节点、槽状态变更,通过节点间的通信,所有节点会很快得知整个集群的状态,使集群收敛。

节点间发送的消息主要分为 5 种: meet 消息 、ping消息 、 pong消息 、fail消息 、 publish 消 息 。不同的消息类型,通信协议、发送的频率和时机、接收节点的选择等是不同的:

  • MEET 消息: 在节点握手阶段,当节点收到客户端的 CLUSTER MEET 命令时,会向新加入的节点发送 MEET 消息,请求新节点加入到当前集群;新节点收到 MEET 消息后会回复一个 PONG 消息。
  • PING 消息: 集群里每个节点每秒钟会选择部分节点发送 PING 消息,接收者收到消息后会回复一个 PONG 消息。PING 消息的内容是自身节点和部分其他节点的状态信息,作用是彼此交换信息,以及检测节点是否在线。 PING 消息使用 Gossip 协议发送,接收节点的选择兼顾了收敛速度和带宽成本,具体规则如下:(1)随机找 5 个节点,在其中选择最久没有通信的 1 个节点;(2)扫描节点列表,选择最近一次收到 PONG 消息时间大于 cluster_node_timeout / 2 的所有节点,防止这些节点长时间未更新。
  • PONG消息: PONG 消息封装了自身状态数据。可以分为两种:第一种 是在接到 MEET/PING 消息后回复的 PONG 消息;第二种 是指节点向集群广播 PONG 消息,这样其他节点可以获知该节点的最新信息,例如故障恢复后新的主节点会广播 PONG 消息。
  • FAIL 消息: 当一个主节点判断另一个主节点进入 FAIL 状态时,会向集群广播这一 FAIL 消息;接收节点会将这一 FAIL 消息保存起来,便于后续的判断。
  • PUBLISH 消息: 节点收到 PUBLISH 命令后,会先执行该命令,然后向集群广播这一消息,接收节点也会执行该 PUBLISH 命令。

7)数据结构简析

节点需要专门的数据结构来存储集群的状态。所谓集群的状态,是一个比较大的概念,包括:集群是否处于上线状态、集群中有哪些节点、节点是否可达、节点的主从状态、槽的分布……

节点为了存储集群状态而提供的数据结构中,最关键的是 clusterNode 和 clusterState 结构:前者记录了一个节点的状态,后者记录了集群作为一个整体的状态。

①、clusterNode 结构

clusterNode结构保存了 一个节点的当前状态,包括创建时间、节点 id、ip 和端口号等。每个节点都会用一个 clusterNode 结构记录自己的状态,并为集群内所有其他节点都创建一个 clusterNode 结构来记录节点状态。

下面列举了 clusterNode 的部分字段,并说明了字段的含义和作用:

typedef struct clusterNode { 
	//节点创建时间 
	mstime_t ctime; 
	//节点id 
	char name[REDIS_CLUSTER_NAMELEN]; 
	//节点的ip和端口号 
	char ip[REDIS_IP_STR_LEN]; 
	int port; 
	//节点标识:整型,每个bit都代表了不同状态,如节点的主从状态、是否在线、是否在握手等 
	int flags; 
	//配置纪元:故障转移时起作用,类似于哨兵的配置纪元 
	uint64_t configEpoch; 
	//槽在该节点中的分布:占用16384/8个字节,16384个比特;每个比特对应一个槽:比特值为1,则该 比特对应的槽在节点中;比特值为0,则该比特对应的槽不在节点中 
	unsigned char slots[16384/8]; 
	//节点中槽的数量 
	int numslots; 
	………… 
} clusterNode;

除了上述字段, clusterNode还包含节点连接、主从复制、故障发现和转移需要的信息等。

②、clusterState 结构

clusterState 结构保存了在当前节点视角下,集群所处的状态。主要字段包括:

typedef struct clusterState { 
	//自身节点 
	clusterNode *myself; 
	//配置纪元 
	uint64_t currentEpoch; 
	//集群状态:在线还是下线 
	int state; 
	//集群中至少包含一个槽的节点数量 
	int size; 
	//哈希表,节点名称->clusterNode节点指针 
	dict *nodes; 
	//槽分布信息:数组的每个元素都是一个指向clusterNode结构的指针;如果槽还没有分配给任何节点,则为NULL 
	clusterNode *slots[16384]; 
	………… 
} clusterState;

除此之外, clusterState 还包括故障转移、槽迁移等需要的信息。

Redis集群模式全解析:从主从复制到Cluster的架构演进与实践指南 在分布式系统架构中,数据缓存是提升应用性能的关键技术。其核心原理是通过内存存储高频访问数据,减少对后端数据库的访问压力,从而显著降低响应延迟。这一技术价值在于能够支撑高并发场景,保障系统的高可用性与可扩展性。随着业务规模增长,单点缓存服务会面临数据容量与并发性能的双重瓶颈。为此,Redis提供了主从复制、哨兵和Cluster三种集群化方案,分别解决数据冗余、自动故障转移和数据分片等核心问题。其中,哨兵模式通过监控与选举机制实现高可用,而Cluster模式则采用哈希槽分片机制支撑海量数据存储与高并发写入。这些 阅读详情

相关推荐

Redis集群方案深度对比:传统代理分片与官方Redis Cluster实战解析

在分布式系统架构中,数据分片与高可用是核心挑战。其原理是通过将数据分散存储于多个节点,并引入路由机制,以实现水平扩展和故障容错。这项技术的核心价值在于突破单机容量与性能瓶颈,构建高并发、高可用的数据服务层。在缓存、会话存储、实时排行榜等典型应用场景中,Redis作为关键组件,其集群化方案的选择至关重要。本文聚焦于两种主流实现:基于客户端或代理的传统分片方案,以及官方原生的Redis Cluster。文章将深入剖析两者在数据分片、高可用机制、运维复杂度及性能表现上的差异,并结合一致性哈希、Gossip协议等关

weixin_34391445的博客 423

springboot redis 断线重连_redis主从复制

https://blog.youkuaiyun.com/weixin_39811842/article/details/111020517

nizhongli37的博客 840

中间件:分布式系统的交通枢纽与核心组件实战解析

在分布式系统架构中,中间件作为连接应用与基础设施的关键组件,其核心价值在于解耦、复用与标准化。从原理上看,中间件通过提供标准接口和协议,将业务逻辑与底层技术细节分离,例如消息队列实现异步通信,缓存加速数据访问。其技术价值在于提升系统扩展性、可靠性和开发效率,是构建高可用、高性能系统的基石。应用场景广泛,涵盖服务通信、数据管理、系统协调等,例如API网关统一入口、Redis缓存热点数据、Nacos实现服务发现。本文聚焦于中间件的核心思想、主流组件(如Kafka、Redis)的深度解析,并结合部署配置与生产运维

chongyuwan4121的博客 488

springboot redis 断线重连_Redis(9)——史上最强【集群】入门实践教程

一、Redis 集群概述Redis 主从复制到 目前 为止,我们所学习的 Redis 都是 单机版 的,这也就意味着一旦我们所依赖的 Redis 服务宕机了,我们的主流程也会受到一定的影响,这当然是我们不能够接受的。所以一开始我们的想法是:搞一台备用机。这样我们就可以在一台服务器出现问题的时候切换动态地到另一台去:幸运的是,两个节点数据的同步我们可以使用 Redis 的 主从同步 功能帮助到我们,...

weixin_39755853的博客 1599

Redis Cluster与Proxy集群方案深度对比与选型指南

在分布式系统架构中,数据分片与高可用是构建高性能缓存层的核心挑战。Redis作为主流的内存数据库,其集群化方案的选择直接关系到系统的扩展性与稳定性。从技术原理上看,数据分片机制决定了数据如何分布,而高可用方案则保障了服务的连续性。Redis Cluster作为官方原生方案,采用去中心化的Gossip协议和哈希槽分片,实现了节点的自治理与数据自动迁移,其价值在于架构简洁、性能无损,适合云原生与统一技术栈的场景。相反,基于Proxy(如Codis)的集群方案通过引入中间代理层,在客户端兼容性与运维可视化方面优势

weixin_30588675的博客 591

Building a Scalable Chat Application with Redis Pub/Sub: A Step-by-Step Guide

本文详细介绍了如何使用Redis Pub/Sub构建高可用实时聊天系统,包括Redis Pub/Sub机制解析、系统架构设计、性能优化方案和高可用保障策略。通过实战案例和代码示例,帮助开发者掌握实时消息传递技术,构建可扩展的聊天应用。

weixin_29271053的博客 390

调研Redis高可用两种方案

导读:Redis是被广泛使用的基础软件之一。对于工程师和,架构师,运维人员来说,了解Redis的高可用方案和背后的原理,是必备的基础知识。本文作者深入分析了Redis高可...

weixin_45583158的博客 391

服务器集群全解析:从负载均衡到K8s,7大类型与实战选型指南

在分布式系统与云计算领域,集群技术是构建高可用、可扩展服务的核心基础。其核心原理是通过将多台服务器组织成一个逻辑整体,以单一系统形象对外提供服务,从而突破单机在性能、可靠性或存储容量上的限制。从技术价值看,集群通过冗余和并行处理,实现了负载均衡、故障转移和横向扩展,是支撑现代互联网高并发访问和海量数据处理的关键。典型的应用场景广泛,从应对电商大促的Web前端,到确保核心业务连续性的数据库,再到处理科学计算与大数据分析的后台。本文聚焦于负载均衡、高可用、高性能计算、分布式存储与计算、容器编排及数据库等主流集群

weixin_30425949的博客 296

SpringBoot(十九)集成Redis

如果有收获!!! 希望老铁们来个三连,点赞、收藏、转发。 创作不易,别忘点个赞,可以让更多的人看到这篇文章,顺便鼓励我写出更好的博客

星海IT学习之路 1436

Redis Pub/Sub 模式下的消息丢失问题与应对策略

本文深入分析了Redis Pub/Sub模式下的消息丢失问题,探讨了其核心特性与局限性,并提出了高可用架构设计策略。通过混合持久化方案、客户端缓冲队列设计和集群化部署等实践,有效应对消息丢失挑战,提升系统可靠性。文章还对比了不同技术方案的优劣,为开发者提供了实用的生产环境建议。

weixin_28396629的博客 308

uses ARM-Compiler ‘Default Compiler Version 5‘ which is not available. MDK5.37安装ARM_Compiler_5

MDK5.37安装ARM_Compiler_5 最后一个AC5编译器,从MDK5.37开始,不再默认安装,需要独立安装 ARMCompiler_506_Windows_x86_b960.zip (80.94MB) 否则使用AC5编译代码报错如下: Build started: Project: Project *** Target 'STM3210C_EVAL' uses ARM-Compiler 'Default Compiler Version 5' which is not available. *

mowwwcom的专栏 2万+

【Redis专题】RedisCluster集群运维与核心原理剖析

前面我们介绍过了Redis主从哨兵的方案。在redis3.0以前的版本要实现集群一般是借助哨兵sentinel工具来监控master节点的状态,如果master节点异常,则会做主从切换,将某一台slave作为master,哨兵的配置略微复杂,并且性能和高可用性等各方面表现一般,特别是在主从切换的瞬间存在【访问瞬断】的情况,而且哨兵模式只有一个主节点对外提供服务,没法支持很高的并发,且单个主节点内存也不宜设置得过大,否则会导致持久化文件过大,影响数据恢复或主从同步的效率 为了解决上面说的问题,Redis3,0

qq_32681589的博客 1343

VisionPro开发实战:CogRecordDisplay控件显示与保存图片的完整流程(附C#代码示例)

本文详细解析了VisionPro开发中CogRecordDisplay控件的图像处理全流程,包括图像加载、显示优化、动态清屏及结果保存等关键操作。通过C#代码示例,展示了如何高效使用该控件进行工业视觉应用开发,特别适合自动化检测系统的开发者参考。

weixin_42523792的博客 278

redis cluster 集群 HA 原理和实操(史上最全、面试必备)

文章很长,建议收藏起来慢慢读!疯狂创客圈总目录 语雀版 | 总目录 码云版| 总目录 博客园版 为您奉上珍贵的学习资源 : 免费赠送 经典图书:《Java高并发核心编程(卷1)》 面试必备 + 大厂必备 +涨薪必备 加尼恩免费领 免费赠送 经典图书:《Java高并发核心编程(卷2)》 面试必备 + 大厂必备 +涨薪必备 加尼恩免费领 免费赠送 经典图书:《Netty Zookeeper Redis 高并发实战》 面试必备 + 大厂必备 +涨薪必备 加尼恩免费领 免费赠送 经典图书:《

架构师尼恩 8059

ZYNQ:【1】深入理解PS端的TTC定时器(Part1:原理+官方案例讲解)

基于UG585详细讲解其中TTC的原理和使用案例。

Alex的技术博客 7889

WorkBuddy 技能指南:基础办公与文档处理

WorkBuddy 不仅仅是一个对话工具——它通过技能(Skills)系统,将通用 AI 助手转变为具备专业领域能力的智能助手。每个技能都是一套经过精心设计的"能力包",包含专业知识、工作流程和专用工具。本文聚焦于文档处理类技能——这是日常工作中使用频率最高、最实用的能力集合。

u011186532的专栏 705

【Redis】2026 互联网大厂 Redis 面试高频题

**Redis 面试高频题解析: 1. Redis为什么快? 内存操作:数据存储在内存,访问速度比磁盘快千倍。 单线程模型:避免多线程锁竞争和上下文切换,核心命令高效执行。 I/O多路复用:基于epoll实现高并发连接管理,单线程处理万级连接。 高效数据结构:如SDS字符串、跳表等,优化操作复杂度。 2. 单线程如何利用多核CPU? 多线程I/O(Redis 6.0+):网络收发包和协议解析由多线程处理。 多实例部署:绑定不同CPU核心,分散负载。 集群分片:通过Redis Cluster将数据分散到多节点

时光、疏离了记忆づ童话的博客 4057

Vibe Coding 实战指南:用 3 类社区资源实现每周高效追新

介绍一种分层技术雷达校准方法,通过领域过滤器(L1技术栈锚定、L2能力映射、L3场景收敛)精准筛选AI编程相关更新,结合可验证的Shell命令与CI任务卡,将信息过载压缩为可执行、可审计的工程实践。

weixin_27251469的博客 331

Redis集群模式深度解析:主从、哨兵与Cluster的选型与实践

在分布式系统架构中,缓存是提升应用性能的关键组件,而高可用与可扩展性是衡量缓存系统稳定性的核心指标。其原理在于通过数据复制、故障转移与分片等技术,在多个节点间协调工作,以应对单点故障与容量瓶颈。Redis作为主流的内存数据库,其提供的集群化方案为构建健壮的缓存层提供了技术基础,具有支撑高并发访问、保障服务连续性的重要价值。在实际的微服务、电商秒杀、实时推荐等应用场景中,合理选择集群模式直接关系到系统的吞吐能力与容错水平。本文聚焦于Redis的主从复制、哨兵模式与Cluster集群这三种主流方案,深入剖析其各

weixin_33726313的博客 467

Python实现商品价格监控与波动分析爬虫项目

本文通过完整的代码示例和详细的技术讲解,展示了如何实现商品价格的自动监控和波动分析。该项目不仅适用于个人购物助手,还可以扩展为商家的竞品监控工具。通过结合数据抓取、存储、分析与可视化,能够帮助我们更好地理解市场趋势并做出优化决策。

2201_76125261的博客 1744

某勾网之登录过程逆向

拉勾网的登录过程逆向,包含请求头(X-S-HEADER、X-K-HEADER、X-SS-REQ-HEADER等) 以及 请求参数/返回数据的加解密。

shanf7921的博客 3万+

Redis 知识体系(文档型 NoSQL)

本文深入解析Redis八大基础数据结构及其底层编码实现,涵盖String、List、Set、ZSet、Hash、Geo、Bitmap、HyperLogLog和Stream等核心结构。通过源码级分析,揭示了SDS、Ziplist、Dict等底层组件的设计原理,并详细探讨了Redis的高性能IO模型、持久化机制(RDB/AOF/混合模式)、内存管理策略及高可用架构(主从/哨兵/Cluster)。 重点剖析了Redis在工程实践中的典型问题与优化方案,包括缓存穿透/击穿/雪崩的解决方案、分布式锁的完整实现(含Re

专注 Java 后端开发,分享基础语法、JVM、并发、Spring 全家桶、微服务、分布式、性能优化等实战干货。坚持输出高质量技术笔记,用简单语言讲清复杂原理,助力每一位 Java 开发者稳步进阶。 800

YOLO系列算法改进 | C3k2改进篇 | 融合DEConv细节增强卷积模块 | 细节增强+多分支差分卷积融合,标准卷积的完美涨点替代! | TIP 2024

YOLO系列算法改进 | C3k2改进篇 | 融合DEConv细节增强卷积模块 | 细节增强+多分支差分卷积融合,标准卷积的完美涨点替代! | TIP 2024 (以YOLO26最新目标检测模型为基础,融合C3k2_DEConv创新模块进行改进)

2502_91881744的博客 311

Java程序员5面阿里终获offer,感慨:原来阿里面试这么严

坊间传言的阿里P6招聘需求 感觉面试还是主要围绕简历来问的,所以不熟悉的东西最好不要随便写上去。项目和基础都很重要,项目中最好有难点,能够体现自己解决问题的过程和思路。 电话面: 自我介绍 事务的特性 ACID , 数据库的死锁发生的情景 ...

chuanlan7921的博客 721

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Java后端面试八股文:从核心原理到实战技巧的全面指南

在Java后端开发领域,掌握核心原理是构建高性能、高可用系统的基石。理解JVM内存模型、垃圾回收机制以及并发编程中的锁与线程池原理,是优化应用性能、解决线上问题的关键。这些底层知识直接关系到系统的稳定性和扩展性,尤其在微服务架构和分布式系统中,对数据一致性、缓存策略和消息队列的深入理解,能有效应对高并发场景下的技术挑战。本文聚焦于Java集合框架、Spring生态、MySQL索引与事务、Redis缓存等高频考点,通过梳理HashMap扩容、Spring Bean生命周期、分布式锁实现等热词背后的技术细节,帮

weixin_33827731的博客 425

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

上一篇: Java中高级核心知识全面解析——从认识Linux操作系统开始(什么是操作系统?分类、内核、用户态与内核态)
下一篇: Java中高级核心知识全面解析——Redis([数据类型、编码、底层数据结构]、5种数据类型的编码和数据结构、内存回收和共享)6
JavaCaiy
博客等级 码龄6年 1万+粉丝 95原创
评论 8
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值