前言:redis的主从和哨兵模式,在官方的功能模式下,从实例只有数据备份和作为主实例的备机作用,并不具备我们想象中的主实例负责写,从实例负责读的职责分工
实际项目中不会使用单独的主从复制的模式的吧,哨兵模式还有使用的项目,那哨兵模式下如何实现读写分离呢?
废话不多说直接上demo,顺便看下原生的jedis哨兵是不是真的不支持读写分离,这可不是我在瞎说:
jedis版本:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.10.2</version>
</dependency>
我们使用jedis的JedisSentinelPool类来创建哨兵链接
Set<String> sentinels = new HashSet<>();
sentinels.add("192.168.84.1:16379");
sentinels.add("192.168.84.1:16380");
sentinels.add("192.168.84.1:16381");
JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels);
// 永远返回的都是 Master 连接
Jedis master = pool.getResource();
看下getResource()源码:
public Jedis getResource() {
while(true) {
Jedis jedis = (Jedis)super.getResource();
jedis.setDataSource(this);
HostAndPort master = this.currentHostMaster;
HostAndPort connection = new HostAndPort(jedis.getClient().getHost(), jedis.getClient().getPort());
// 是主实例的连接信息,才会返回jedis连接
if (master.equals(connection)) {
return jedis;
}
this.returnBrokenResource(jedis);
}
}
没骗你吧?
那如果我们想实现jedis哨兵模式的读写分离,要怎么做呢 ,来,直接上硬货:文章来源:https://www.toymoban.com/news/detail-555654.html
package com.cjian.jedis;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisSentinelPool;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @Author: cjian
* @Date: 2023/7/13 13:49
* @Des:
*/
public class SentinelDemo {
public static void main(String[] args) {
Set<String> sentinels = new HashSet<>();
sentinels.add("192.168.84.1:16379");
sentinels.add("192.168.84.1:16380");
sentinels.add("192.168.84.1:16381");
JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels);
// 永远返回的都是 Master 连接
Jedis master = pool.getResource();
// 获取 Master 的地址信息
HostAndPort hostAndPort = pool.getCurrentHostMaster();
System.out.println("master = " + hostAndPort.getHost() + ":" + hostAndPort.getPort() + " " + master);
testRWSeparation(master);
}
private static void testRWSeparation(Jedis master){
// 构造我们自己的对象
MyJedis myJedis = new MyJedis();
myJedis.setMaster(master);
// 解析主从信息,提取从节点信息
Pattern pattern = Pattern.compile("^slave\\d+:ip=(.+),port=(\\d+),state=.+$");
String[] infos = master.info("replication").split("(\\r\\n)|(\\n)");
for (String info : infos) {
Matcher matcher = pattern.matcher(info);
if (matcher.find()) {
Jedis slave = new Jedis(matcher.group(1), Integer.valueOf(matcher.group(2)));
myJedis.addSlaves(slave);
}
}
// 写入数据
myJedis.set("name", "cjian");
// 读取数据
String result = myJedis.get("name");
System.out.println("result = " + result);
result = myJedis.get("name");
System.out.println("result = " + result);
}
static class MyJedis {
/**
* 主节点
*/
private Jedis master;
/**
* 从节点,可能会有多个
*/
private List<Jedis> slaves = new ArrayList<>();
public void setMaster(Jedis master) {
this.master = master;
}
public void addSlaves(Jedis slave) {
this.slaves.add(slave);
}
public String get(String key) {
Jedis jedis = slaves.get((int) (Math.random() * slaves.size()));
System.out.println(">> get:" + jedis);
return jedis.get(key);
}
public void set(String key, String value) {
master.set(key, value);
}
}
}
输出如下: 文章来源地址https://www.toymoban.com/news/detail-555654.html
14:36:09.426 [main] INFO r.clients.jedis.JedisSentinelPool - Trying to find master from available Sentinels...
14:36:09.437 [main] DEBUG r.clients.jedis.JedisSentinelPool - Connecting to Sentinel 192.168.84.1:16379
14:36:09.557 [main] DEBUG r.clients.jedis.JedisSentinelPool - Found Redis master at 192.168.84.1:6381
14:36:09.558 [main] INFO r.clients.jedis.JedisSentinelPool - Redis master running at 192.168.84.1:6381, starting Sentinel listeners...
14:36:09.765 [main] INFO r.clients.jedis.JedisSentinelPool - Created JedisPool to master at 192.168.84.1:6381
master = 192.168.84.1:6381 redis.clients.jedis.Jedis@783e6358
>> get:redis.clients.jedis.Jedis@735f7ae5
result = cjian
>> get:redis.clients.jedis.Jedis@180bc464
result = cjian
到了这里,关于Jedis哨兵模式如何实现主从的读写分离的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!