SpringBoot基于哨兵模式的Redis(7.2)集群实现读写分离
环境
- docker desktop for windows 4.23.0
- redis 7.2
- Idea
一、前提条件
先根据以下文章搭建一个Redis集群
部署完后,redis集群看起来大致如下图
 
二、SpringBoot访问Redis集群
1. 引入依赖
需要注意的是lettuce-core版本问题,不能太旧,否则不兼容新版的Redis。
| 1 | <dependency> | 
2. yaml配置
在application.yml加入以下配置。第一个password是用于sentinel节点验证,第二个password用于数据节点验证。
| 1 | spring: | 
这里关于sentinel的ip问题后面会讲解。
3. 设置读写分离
在任意配置类中写一个Bean,本文简单起见,直接写在SpringBoot启动类了。
| 1 | @Bean | 
这里的ReadFrom是配置Redis的读取策略,是一个枚举,包括下面选择:
- MASTER:从主节点读取
- MASTER_PREFERRED:优先从master节点读取,master不可用才读取replica
- REPLICA:从slave (replica)节点读取
- REPLICA_PREFERRED:优先从slave (replica)节点读取,所有的slave都不可用才读取master
至于哪些节点支持读,哪些支持写,因为redis 7 默认给从节点设置为只读,所以可以认为只有主节点有读写权限,其余只有读权限。如果情况不一致,就手动给每一个redis-server的配置文件都加上这一行。
| 1 | replica-read-only yes | 
4. 简单的controller
写一个简单的controller,等会用于测试。
| 1 | @RestController | 
三、运行
首先,因为所有redis节点都在一个docker bridge网络中,所以基于Idea编写的项目在宿主机(Windows)中运行spirngboot程序,不好去和redis集群做完整的交互。
虽然说无论是sentinel还是redis-server都暴露了端口到宿主机,我们可以通过映射的端口分别访问它们,但是我们的程序只访问sentinel,sentinel管理redis-server,sentinel会返回redis-server的ip来让我们的程序来访问redis-server,这里的ip是docker bridge网络里的ip,所以即使我们的程序拿到ip也访问不了redis-server。
这个时候就需要将我们的项目放到一个docker容器中运行,然后把这个容器放到和redis同一网络下,就像下图。  
 
  
具体如何快捷让Idea结合Docker去运行SpringBoot程序,可以参考下面这篇文章。
记得要暴露你的程序端口到宿主机,这样才方便测试。
四、测试
1. 写
浏览器访问localhost:8080/set/num/7799  
 
  
查看SpringBoot容器日志,可以看到向主节点172.30.1.2:6379发送写请求。
| 1 | 01-06 07:23:59:848 DEBUG 1 --- [nio-8080-exec-6] io.lettuce.core.RedisChannelHandler : dispatching command AsyncCommand [type=SET, output=StatusOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command] | 
2. 读
浏览器访问localhost:8080/get/num  
 
  
查看SpringBoot容器日志,会向两个从节点之一发送读请求。
| 1 | 01-06 07:25:45:342 DEBUG 1 --- [io-8080-exec-10] io.lettuce.core.RedisChannelHandler : dispatching command AsyncCommand [type=GET, output=ValueOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command] | 
3. 额外测试
以及还有一些额外的测试,可以自行去尝试,检验,这里列举一些,但具体不再赘述。
- 关闭两个从节点容器,等待sentinel完成维护和通知后,测试读数据和写数据会请求谁?
- 再次开启两个从节点,等待sentinel完成操作后,再关闭主节点,等待sentinel完成操作后,测试读数据和写数据会请求谁?
- 再次开启主节点,等待sentinel完成操作后,测试读数据和写数据会请求谁?

 
 
 
  
 
  
 
 
  
 
  
 
 
  







