redis哨兵モード-sentinel,javaクライアント動的切替master

4955 ワード

redisの構築モード
  • スタンドアロンモード:スタンドアロンサービス
  • マスタスレーブモード:バックアップを提供するバックアップ、および読み書きを分離する機能
  • 哨兵モード:masterダウン後、哨兵会選挙予備機がmaster
  • に置き換えられる
  • クラスタモード:クラスタは分布式を行うことができ、masterはダウンタイムし、準備機会はmaster
  • にアップグレードされる.
    redis哨兵モードの使用
    単機モードと主備モードは実は差が少なく、哨兵モードのサービスアーキテクチャ:master 1つ、複数のslave、複数の哨兵.
    redisを配備したら、master./redis-4.0/src/redis-server.../conf/redis-master-6379.confをオンにします.
    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #   ip   ,   
    bind 192.168.23.11 127.0.0.1
    
    #   
    port 6379
    
    tcp-backlog 511
    
    timeout 0
    
    tcp-keepalive 300
    
    #       
    daemonize yes
    
    
    
    #pid    
    pidfile "/var/run/redis_6379.pid"
    
    loglevel notice
    #      
    logfile "/home/smkapp/redislog/log6379.log"
    
    #       
    databases 2
    
    always-show-logo yes
    

    slave./redis-4.0/src/redis-server.../conf/redis-slave-6380.conf
    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #   ip   ,   
    bind 192.168.23.11 127.0.0.1
    
    #   
    port 6380
    
    tcp-backlog 511
    
    timeout 0
    
    tcp-keepalive 300
    
    #       
    daemonize yes
    
    #pid    
    pidfile "/var/run/redis_6380.pid"
    
    loglevel notice
    #      
    logfile "/home/smkapp/redislog/log6380.log"
    
    #       
    databases 2
    
    slaveof  192.168.23.11 6379
    always-show-logo yes
    

    歩哨を開く./redis-4.0/src/redis-sentinel.../conf/redis-sentinel-26379.conf
    #   ip   ,   
    bind 192.168.23.11 127.0.0.1
    
    #   
    port 26380
    
    tcp-backlog 511
    
    timeout 0
    
    tcp-keepalive 300
    
    #       
    daemonize yes
    
    #pid    
    pidfile "/var/run/redis_6380.pid"
    
    loglevel notice
    #      
    logfile "/home/smkapp/redislog/log6380.log"
    
    #  master
    sentinel monitor luoyangmaster 192.168.23.11 6381 1
    
    #       5 
    sentinel down-after-milliseconds luoyangmaster 5000
    

    JAvaクライアント
    ネット上でいくつかの歩哨モードのJAVAクライアントを探して、適当なことを探し当てていません.自分で1つのサンプルを書いて、基本的に走ることができて、マスターを切り替える時、やはり一定量の要求があって間違いを報告します
    package com.redis;
    
    import java.util.HashSet;
    import java.util.Set;
    
    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.JedisPoolConfig;
    import redis.clients.jedis.JedisSentinelPool;
    
    public class RedisClientSentinel {
    
    	public static final int default_seconds = 300;
    
    	private static RedisClientSentinel client = null;
    
    	private JedisSentinelPool poolConfig = null;
    
    	private RedisClientSentinel() {
    		try {
    			getPool();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    
    	public static synchronized RedisClientSentinel getInstance() {
    		if (null == client) {
    			client = new RedisClientSentinel();
    		}
    		return client;
    	}
    
    	/**
    	 *     
    	 * 
    	 * @return
    	 */
    	private  JedisSentinelPool getPool() {
    		if (poolConfig == null || poolConfig.isClosed()) {
    			Set sentinels = new HashSet<>();
    			sentinels.add("192.168.23.11:26379");
    			sentinels.add("192.168.23.11:26380");
    
    			JedisPoolConfig ab = new JedisPoolConfig();
    			ab.setMinIdle(Integer.parseInt("5"));
    			ab.setMaxTotal(5);
    			ab.setMaxIdle(5);
    			poolConfig = new JedisSentinelPool("luoyangmaster", sentinels, ab);
    		}
    		return poolConfig;
    	}
    
    	private Jedis getJedis() {
    		//        master  ip    
    		System.out.println(poolConfig.getCurrentHostMaster());
    		//           
    		return getPool().getResource();
    	}
    
    	/**
    	 *    
    	 * 
    	 * @param key
    	 * @return
    	 */
    	public String getStringValue(String key) {
    		Jedis j = getJedis();
    		String d = null;
    		try {
    			d = j.get(key);
    			//    OK          
    			poolConfig.returnResourceObject(j);
    		} catch (Exception e) {
    			//      
    			System.out.println("  ");
    			//     
    			j.close();
    		}
    //		j.close();
    		return d;
    	}
    
    	public static void main(String[] args) {
    		
    		new Thread(new Tre()).start();
    		new Thread(new Tre()).start();
    		new Thread(new Tre()).start();
    		new Thread(new Tre()).start();
    		new Thread(new Tre()).start();
    		new Thread(new Tre()).start();
    	}
    	
    	public static int i = 0;
    	
    	public  synchronized static  void add() {
    		i++;
    	}
    	
    	
    }
    
    class Tre implements Runnable{
    
    	@Override
    	public void run() {
    		RedisClientSentinel s = RedisClientSentinel.getInstance();
    		while (true) {
    			try {
    				String d = s.getStringValue("username");
    				if(d == null) {
    					RedisClientSentinel.add();
    				}
    				System.out.println(RedisClientSentinel.i);
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    
    			try {
    				Thread.sleep(1000);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		}
    		
    	}
    	
    }
    
    

    哨兵モードでは、取得した接続クライアントJedis、このクライアント接続はドッキングしたmasterですが、このmasterがダウンしたら、哨兵は新しいmasterを選出します.この時点で元のjedisクライアントは使用できません.
    この場合、JAVAクライアントは新しいマスターを取得してリンクします.
    そのため、使用するたびに、哨兵接続プールから新しいクライアントgetPool().getResource();
    使用時にエラーが発生した場合は、クライアントjedis.close()を閉じる必要があります.
    接続プール内のクライアントは数に制限があり、取り出して返さないと何度も操作するしかなく、その後も操作がブロックされます.したがって、jedisクライアントを使用するたびに、正常に接続されている場合は、poolConfig.returnResourceObject(jedis)に接続クライアントを返す必要があります.
    この哨兵モードの使い方を大まかに検討してみましたが、なんだかもっと優れた使い方があるような気がします.