redis哨兵模式介绍
哨兵模式本质上来说,就是redis的主从模式+一个分布式的监控集群(sentinel集群)。redis的主从模式可以解决数据的同步问题,设置完主从节点后数据会自动从master节点复制到slave节点,但是一旦主节点挂了,就无法写入了,这时候就需要哨兵进行投票,选出新的主节点并且自动切换过去。同时为了保证高可用,哨兵本身也需要做集群。
哨兵的主要能力如下:
- 监控(Monitoring):持续监控Redis主节点、从节点是否处于预期的工作状态。
- 通知(Notification):哨兵可以把Redis实例的运行故障信息通过API通知监控系统或者其他应用程序。
- 自动故障恢复(Automatic failover):当主节点运行故障时,哨兵会启动自动故障恢复流程:某个从节点会升级为主节点,其他从节点会使用新的主节点进行主从复制,通知客户端使用新的主节点进行。
- 配置中心(Configuration provider):哨兵可以作为客户端服务发现的授权源,客户端连接到哨兵请求给定服务的Redis主节点地址。如果发生故障转移,哨兵会通知新的地址。这里要注意:哨兵并不是Redis代理,只是为客户端提供了Redis主从节点的地址信息。
哨兵模式是天然的分布式系统,它被设计为基于一套配置,并在多个哨兵实例的配合下工作。多实例共同协作有以下优势:
- 主节点的系统故障是在多个实例共同认可的情况下完成的,大大降低了误报的概率。
- 即使不是所有的哨兵实例都正常运行哨兵集群也能正常工作,这大大增加了系统的鲁棒性。
环境搭建
我们需要启动6个进程,分别是1主2从的redis节点,和3个哨兵节点,为便于演示,均在一台机器上启动,分别启用不同端口号。
redis-server 配置文件(放置在~/redis/conf目录下):
主节点redis-6379.conf:
port 6379
daemonize yes
pidfile "/var/run/redis-6379.pid"
logfile "6379.log"
dir "/home/foo/redis/log"
dbfilename "dump-6379.rdb"
从节点redis-6380.conf:
port 6380
daemonize yes
pidfile "/var/run/redis-6380.pid"
logfile "6380.log"
dir "/home/foo/redis/log"
dbfilename "dump-6380.rdb"
slaveof 127.0.0.1 6379
从节点redis-6381.conf:
port 6381
daemonize yes
pidfile "/var/run/redis-6381.pid"
logfile "6381.log"
dir "/home/foo/redis/log"
dbfilename "dump-6381.rdb"
slaveof 127.0.0.1 6379
分别启动这三个节点
redis-server redis-6379.conf
redis-server redis-6380.conf
redis-server redis-6381.conf
执行redis-cli(不加端口号默认是连接6379端口),执行 info replication 可查询副本信息:
redis-cli
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=585842,lag=1
slave1:ip=127.0.0.1,port=6381,state=online,offset=585977,lag=1
master_replid:3ce09e64d04884dc94a441c776afd3fd0b3a47a2
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:585977
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:584987
repl_backlog_histlen:991
可以看到一主两从的节点都已经正常启动,6379为主节点,6380、6381为从节点,从主节点写入的数据会自动同步至从节点
接下来我们创建sentinel的配置文件:
sentinel-26379.conf:
port 26379
daemonize yes
dir "/home/foo/redis/log"
logfile "26379.log"
sentinel deny-scripts-reconfig yes
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 10000
sentinel-26380.conf:
port 26380
daemonize yes
dir "/home/foo/redis/log"
logfile "26380.log"
sentinel deny-scripts-reconfig yes
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 10000
sentinel-26381.conf:
port 26381
daemonize yes
dir "/home/foo/redis/log"
logfile "26381.log"
sentinel deny-scripts-reconfig yes
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 10000
注意哨兵的配置只需要配置主节点的信息,哨兵通过连接主节点进行“订阅”操作(pub/sub机制),即可以获取其他需要监控的副本节点信息以及其他正在监控主节点的哨兵信息,而哨兵的数量正是后面进行投票的依据
启动哨兵节点:
redis-sentinel sentinel-26379.conf
redis-sentinel sentinel-26380.conf
redis-sentinel sentinel-26381.conf
redis-cli -p 26379 进入节点,执行 info sentinel
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
可以看到是标准的1主2从3哨兵模式,至此哨兵集群搭建完毕
spring boot配置
我们以最常用的spring boot 连接redis哨兵进行说明,spring boot 2.x中默认客户端是lettuce,基于netty nio方式连接,比jedis性能更高,所以后面主要以lettuce进行说明。
引入redis starter:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
加入redis相关配置:
redis:
sentinel:
master: mymaster
nodes: 127.0.0.1:26379,127.0.0.1:26380,127.0.0.1:26381
lettuce支持哨兵模式配置,只要配置哨兵节点即可,哨兵会告诉客户端实际的redis-server的地址,实际请求不会经过sentinel节点
下面简单在controller里面加两段代码,一个是用来写入数据,一个用来读取数据:
@GetMapping("/redis/write/{name}")
public String redisWrite(@PathVariable String name) throws Exception {
redisTemplate.opsForValue().set("name",name);
return "redis write ok!";
}
@GetMapping("/redis/read")
public String redisRead() throws Exception {
return redisTemplate.opsForValue().get("name").toString();
}
这样基础配置就都完成了,下面来进行实际测试
可用性测试
故障检测
哨兵以集群方式工作,官方建议至少要有三个节点,每个节点都以相同的方式对主从节点进行监控与故障检测。由于网络抖动或者网络分区,单个哨兵对节点的故障检测可能无法代表其真实的状态,为了降低误判,哨兵之间还需要对节点的故障状态进行协商。所以这里需要引入两个概念:
- 主观宕机(Subjective Down, SDOWN):是指一个哨兵实例通过检测发现某个主节点发生故障的一种状态。
- 客观宕机(Objective Down, ODOWN):是指哨兵检测到某个主节点发生故障,通过命令SENTINEL is-master-down-by-addr与其他哨兵节点协商,并且在指定时间内接收到指定数量的其他哨兵的确认反馈时的一种状态。
简单来说,SDOWN是哨兵自己认为节点宕机,而ODOWN是不但哨兵自己认为节点宕机,而且该哨兵与其他节点沟通后,达到一定数量的哨兵都认为节点宕机了。
这里的“一定数量”是一个法定数量(Quorum),是由哨兵监控配置决定的,解释一下该配置:
# sentinel monitor <master-name> <master-host> <master-port> <quorum>
# 举例如下:
sentinel monitor mymaster 127.0.0.1 6379 2
这条配置项用于告知哨兵需要监听的主节点:
- sentinel monitor:代表监控。
- mymaster:代表主节点的名称,可以自定义。
- 127.0.0.1:代表监控的主节点ip,6379代表端口。
- 2:法定数量,代表只有两个或两个以上的哨兵认为主节点不可用的时候,才会把主节点设置为ODOWN状态,然后进行failover操作。
例子中quorum=2,也就是说:哨兵检测到主节点故障并设置其状态为SDOWN,然后至少得到一个其他哨兵的认可,即标记该主节点为ODWN状态。哨兵进行故障切换流程如下:
- 每个哨兵节点都会收到主节点的+sdown事件
- 该事件稍后将升级为+odown,这意味着多个哨兵一致认为无法访问主机
- Sentinel集群投票选出一个Sentinel,该Sentinel将启动第一次故障转移尝试
- 进行故障切换
故障注入
这里假设6380节点为当前主节点,通过使用
redis-cli -p 6380 DEBUG sleep 30
来注入故障,模拟主节点失联的情况,上面这条命令让主节点sleep了30秒,让我们来看看sentinel节点上发生了什么:
26379.log:
5921:X 20 Mar 2023 18:43:19.162 # +sdown master mymaster 127.0.0.1 6380
5921:X 20 Mar 2023 18:43:19.231 # +new-epoch 19
5921:X 20 Mar 2023 18:43:19.245 # +vote-for-leader 071577127e00a0d20ea2a7ab88e9c108d985a7a2 19
5921:X 20 Mar 2023 18:43:19.253 # +odown master mymaster 127.0.0.1 6380 #quorum 3/2
5921:X 20 Mar 2023 18:43:19.253 # Next failover delay: I will not start a failover before Mon Mar 20 18:49:19 2023
5921:X 20 Mar 2023 18:43:20.364 # +config-update-from sentinel 071577127e00a0d20ea2a7ab88e9c108d985a7a2 127.0.0.1 26381 @ mymaster 127.0.0.1 6380
5921:X 20 Mar 2023 18:43:20.364 # +switch-master mymaster 127.0.0.1 6380 127.0.0.1 6379
5921:X 20 Mar 2023 18:43:20.364 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
5921:X 20 Mar 2023 18:43:20.365 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
5921:X 20 Mar 2023 18:43:30.413 # +sdown slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
5921:X 20 Mar 2023 18:43:38.450 # -sdown slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
26380.log:
6019:X 20 Mar 2023 18:43:18.479 # +sdown master mymaster 127.0.0.1 6380
6019:X 20 Mar 2023 18:43:19.231 # +new-epoch 19
6019:X 20 Mar 2023 18:43:19.245 # +vote-for-leader 071577127e00a0d20ea2a7ab88e9c108d985a7a2 19
6019:X 20 Mar 2023 18:43:19.596 # +odown master mymaster 127.0.0.1 6380 #quorum 3/2
6019:X 20 Mar 2023 18:43:19.596 # Next failover delay: I will not start a failover before Mon Mar 20 18:49:19 2023
6019:X 20 Mar 2023 18:43:20.364 # +config-update-from sentinel 071577127e00a0d20ea2a7ab88e9c108d985a7a2 127.0.0.1 26381 @ mymaster 127.0.0.1 6380
6019:X 20 Mar 2023 18:43:20.364 # +switch-master mymaster 127.0.0.1 6380 127.0.0.1 6379
6019:X 20 Mar 2023 18:43:20.365 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
6019:X 20 Mar 2023 18:43:20.365 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
6019:X 20 Mar 2023 18:43:30.385 # +sdown slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
6019:X 20 Mar 2023 18:43:38.448 # -sdown slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
26381.log:
6025:X 20 Mar 2023 18:43:19.134 # +sdown master mymaster 127.0.0.1 6380
6025:X 20 Mar 2023 18:43:19.186 # +odown master mymaster 127.0.0.1 6380 #quorum 2/2
6025:X 20 Mar 2023 18:43:19.186 # +new-epoch 19
6025:X 20 Mar 2023 18:43:19.186 # +try-failover master mymaster 127.0.0.1 6380
6025:X 20 Mar 2023 18:43:19.210 # +vote-for-leader 071577127e00a0d20ea2a7ab88e9c108d985a7a2 19
6025:X 20 Mar 2023 18:43:19.246 # 0602b87e4c7deacc394ca107d67618e1cb6a31d9 voted for 071577127e00a0d20ea2a7ab88e9c108d985a7a2 19
6025:X 20 Mar 2023 18:43:19.246 # 1bac207ce45984f6c643495d5813154fbaa90c9f voted for 071577127e00a0d20ea2a7ab88e9c108d985a7a2 19
6025:X 20 Mar 2023 18:43:19.273 # +elected-leader master mymaster 127.0.0.1 6380
6025:X 20 Mar 2023 18:43:19.273 # +failover-state-select-slave master mymaster 127.0.0.1 6380
6025:X 20 Mar 2023 18:43:19.357 # +selected-slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
6025:X 20 Mar 2023 18:43:19.357 * +failover-state-send-slaveof-noone slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
6025:X 20 Mar 2023 18:43:19.434 * +failover-state-wait-promotion slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
6025:X 20 Mar 2023 18:43:20.330 # +promoted-slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
6025:X 20 Mar 2023 18:43:20.330 # +failover-state-reconf-slaves master mymaster 127.0.0.1 6380
6025:X 20 Mar 2023 18:43:20.364 * +slave-reconf-sent slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
6025:X 20 Mar 2023 18:43:21.317 * +slave-reconf-inprog slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
6025:X 20 Mar 2023 18:43:21.317 * +slave-reconf-done slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
6025:X 20 Mar 2023 18:43:21.418 # -odown master mymaster 127.0.0.1 6380
6025:X 20 Mar 2023 18:43:21.418 # +failover-end master mymaster 127.0.0.1 6380
6025:X 20 Mar 2023 18:43:21.418 # +switch-master mymaster 127.0.0.1 6380 127.0.0.1 6379
6025:X 20 Mar 2023 18:43:21.418 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
6025:X 20 Mar 2023 18:43:21.418 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
6025:X 20 Mar 2023 18:43:31.465 # +sdown slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
6025:X 20 Mar 2023 18:43:38.441 # -sdown slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
6025:X 20 Mar 2023 18:43:48.419 * +convert-to-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
时间线如下:
- 26379、26380、26381节点均检测出6380节点异常,确认后该节点进入odown状态
- 26381最先检测出6380宕机,经过三个节点投票选举出id为071577127e00a0d20ea2a7ab88e9c108d985a7a2(即26381)的节点作为本次failover的leader
- 26381接管本次failover操作,将6379切换为master节点,同时将6380、6381设置为从节点
- 6380节点上线(-sdown),sentinel将其转换为slave节点
关于quorun和majority参数的说明,可以参考官方文档这部分:
image.png
注意这里有一条日志:
6025:X 20 Mar 2023 18:43:21.418 # -odown master mymaster 127.0.0.1 6380
大家可能会疑惑这时候6380明明还没有恢复呀,怎么就显示-odown了呢?这是因为odown是master节点的专属状态,一旦这个节点变成slave之后,就没有odown这个状态了,只有sdown状态,所以会有一个-odown的状态。
同理,第二个主节点宕机也是一样的切换逻辑。这里要注意的是,如果三个节点全部宕机,sentinel会保留最后的那个主节点,此时不会有切换逻辑。举例:最后一个主节点是6381,这个节点也宕机后,sentinel的配置中这个节点还是主节点,此时启动6379,也不会把它选成主节点,必须把6381这个节点起来,此时整个哨兵集群的状态会再次同步,重新选出主节点。
sentinel集群高可用性设计
哨兵作为监控设施,本身也需要做高可用设计,你不会希望用于监控redis集群的哨兵本身是一个单点系统。哨兵集群的鲁棒性很高,以前面使用的java客户端为例,使用Java客户端连接成功后,即使三个哨兵节点全部挂了,也不影响对于redis的操作,因为此时lettuce客户端通过哨兵已经获取了全部三个redis实例的信息。但这仅限于java进程不重启,重启后需要重新连接哨兵节点,这时候如果三个哨兵都挂了会报错。
sentinel进程启动后,会把获取的其他sentinel及副本信息存储在它的配置文件中(通过重写配置文件),下面是一个例子:
# Generated by CONFIG REWRITE
protected-mode no
pidfile "/var/run/redis.pid"
user default on nopass ~* +@all
sentinel config-epoch mymaster 20
sentinel leader-epoch mymaster 20
sentinel known-replica mymaster 127.0.0.1 6379
sentinel known-replica mymaster 127.0.0.1 6381
sentinel known-sentinel mymaster 127.0.0.1 26379 0602b87e4c7deacc394ca107d67618e1cb6a31d9
sentinel known-sentinel mymaster 127.0.0.1 26381 071577127e00a0d20ea2a7ab88e9c108d985a7a2
sentinel current-epoch 20
该配置文件说明,sentinel 26380 除了监控主节点6380,还监控了6379、6381两个从节点,同时还知道有26379、26381两个兄弟都在监控主节点,这样在主节点odown之后,就需要超过半数(2票)投票来执行后续的failover操作。这里需要注意的是,sentinel节点一旦被其他节点感知后(known-sentinel),是不会被主动移除的。原因官方也有说明,不希望动态去改变故障转移的授权节点数量。所以说即使26379、26381这两个哨兵进程挂了,配置文件中也不会移除,具体可以参考官方文档这段:
由上述文档可知,如果不执行sentinel reset * 操作的话,sentinel节点信息是不会重置的,除非你真的想改变哨兵的数量。如果要知道实际连接过来有多少sentinel的话,可以直接在
__sentinel__:hello
这个channel进行订阅,就可以看到实时有多少sentinel连上来了:
127.0.0.1:6380> subscribe __sentinel__:hello
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "__sentinel__:hello"
3) (integer) 1
1) "message"
2) "__sentinel__:hello"
3) "127.0.0.1,26380,1bac207ce45984f6c643495d5813154fbaa90c9f,19,mymaster,127.0.0.1,6379,19"
1) "message"
2) "__sentinel__:hello"
3) "127.0.0.1,26380,1bac207ce45984f6c643495d5813154fbaa90c9f,19,mymaster,127.0.0.1,6379,19"
1) "message"
2) "__sentinel__:hello"
3) "127.0.0.1,26381,071577127e00a0d20ea2a7ab88e9c108d985a7a2,19,mymaster,127.0.0.1,6379,19"
1) "message"
2) "__sentinel__:hello"
3) "127.0.0.1,26381,071577127e00a0d20ea2a7ab88e9c108d985a7a2,19,mymaster,127.0.0.1,6379,19"
1) "message"
2) "__sentinel__:hello"
3) "127.0.0.1,26379,0602b87e4c7deacc394ca107d67618e1cb6a31d9,19,mymaster,127.0.0.1,6379,19"
1) "message"
2) "__sentinel__:hello"
3) "127.0.0.1,26379,0602b87e4c7deacc394ca107d67618e1cb6a31d9,19,mymaster,127.0.0.1,6379,19"
以上日志显示,三个sentinel节点都已经正常连接上来了,去slave节点也可以看到一样的日志。
下面还是结合具体场景来看:一个3节点的哨兵集群,quorum参数设置为2:
- 3个哨兵都正常,主节点挂了,3个哨兵监控到此事,同时确认3>2(#quorum 3/2),sdown转odown,故障转移leader投票数量3票大于半数,正常进行故障转移
- 3个哨兵挂了一个,主节点挂了,2个哨兵监控到此事,同时确认2=2,sdown转odown,故障转移leader投票数量2票大于半数,正常进行故障转移
- 3个哨兵挂了2个,主节点挂了,1个哨兵监控到此事,同时确认1<2,sdown无法转odown,不会进行后续failover操作
- 3个哨兵都挂了,自然不会进行failover操作
这里有人或许要问了,第三种情况,如果我把quorum设置为1,会怎么样?这样确实sdown可以转odown,但是故障转移leader投票数量不过半数,仍然不会进行failover操作。(还记得之前说的,sentinel节点不会主动移除吗?这种情况下sentinel节点数量仍然是3,majority为2,日志中显示failover abort了)
7658:X 20 Mar 2023 21:31:59.600 # +sdown master mymaster 127.0.0.1 6380
7658:X 20 Mar 2023 21:31:59.600 # +odown master mymaster 127.0.0.1 6380 #quorum 1/1
7658:X 20 Mar 2023 21:31:59.601 # +new-epoch 21
7658:X 20 Mar 2023 21:31:59.601 # +try-failover master mymaster 127.0.0.1 6380
7658:X 20 Mar 2023 21:31:59.629 # +vote-for-leader 0602b87e4c7deacc394ca107d67618e1cb6a31d9 21
7658:X 20 Mar 2023 21:32:09.788 # -failover-abort-not-elected master mymaster 127.0.0.1 6380
7658:X 20 Mar 2023 21:32:09.850 # Next failover delay: I will not start a failover before Mon Mar 20 21:37:59 2023
7658:X 20 Mar 2023 21:32:19.498 # -sdown master mymaster 127.0.0.1 6380
7658:X 20 Mar 2023 21:32:19.498 # -odown master mymaster 127.0.0.1 6380
集群架构设计
根据上述实验结果表明,无论你的quorum设置为多少,quorum仅能确定主节点是否能转入odown状态,不能实际进行故障转移操作,failover的授权永远需要超半数的sentinel进行投票表决(所以sentinel的数量必须为奇数)。下面以虚拟机部署为例来说明可用性(虚拟机假设都在不同可用区上):
-
redis主从和sentinel集群合并部署:需要三台虚拟机,每台虚拟机分别部署一个redis实例和一个sentinel实例,类似官网架构,最多只能挂一台虚拟机,现在其实大部分是这个架构
image.png -
redis主从和sentinel集群分离部署:需要6台虚拟机,redis实例可以挂两个,sentinel实例可以挂一个,总体来说可用性更佳,同时由于sentinel集群是标准分布式架构,可以通过简单增加节点数量增加可用性,比如部署5节点的哨兵。
image.png
读写分离
主从模式的redis集群,除了保证数据的备份,同时还可以使用读写分离的方式提高读取的性能。lettuce客户端默认全部走主节点进行读写操作,因为redis是一个高性能的内存数据库,一般情况下也足够使用了,但如果请求量比较大,对于读性能的要求比较高的话,可以设置读写分离,提高整个集群的吞吐量(目前只有lettuce客户端可以进行读写分离设置,jedis不行)。
首先我们在java项目中加入debug日志,方便我们查看请求走到了哪个节点:
logging:
level:
io.lettuce.core: debug
重启后访问之前开发的两个服务接口,发现请求全部走到了6380节点,说明lettuce默认都是走主节点的。接下来我们增加一个配置文件:
@Configuration
public class RedisConfiguration {
@Bean
public RedisConnectionFactory lettuceConnectionFactory(RedisProperties redisProperties) {
RedisSentinelConfiguration redisSentinelConfiguration = new RedisSentinelConfiguration(
redisProperties.getSentinel().getMaster(), new HashSet<>(redisProperties.getSentinel().getNodes())
);
LettuceClientConfiguration lettuceClientConfiguration = LettuceClientConfiguration.builder()
.readFrom(ReadFrom.ANY_REPLICA)
.build();
return new LettuceConnectionFactory(redisSentinelConfiguration, lettuceClientConfiguration);
}
}
注意这个ReadFrom参数,说明了我们希望read的方式,更多的配置方式请参考lettuce官网,这里列了一张表,还是比较容易理解的:
我这边设置的是
ANY_REPLICA
,说明read操作会随机选择一个从节点读取。重启后再重新请求一下read接口,发现read请求已经均匀分配到从节点上去了。这里需要注意一点,由于从节点在复制数据上存在延迟,如果设置读请求全部走从节点,则可能有数据延迟的情况,对延时要求比较敏感的场景需谨慎使用。
网友评论