Jedis哨兵模式如何实现主从的读写分离

前言:redis的主从和哨兵模式,在官方的功能模式下,从实例只有数据备份和作为主实例的备机作用,并不具备我们想象中的主实例负责写,从实例负责读的职责分工

实际项目中不会使用单独的主从复制的模式的吧,哨兵模式还有使用的项目,那哨兵模式下如何实现读写分离呢?

废话不多说直接上demo,顺便看下原生的jedis哨兵是不是真的不支持读写分离,这可不是我在瞎说:

jedis版本:


      redis.clients
      jedis
      2.10.2

 我们使用jedis的JedisSentinelPool类来创建哨兵链接

Set 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哨兵模式的读写分离,要怎么做呢 ,来,直接上硬货:

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 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 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);
        }
    }
}

输出如下: 

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

你可能感兴趣的:(redis,python,java,开发语言)