redis实战第五篇 jedis 连接 redis sentinel详解

时间:2022-07-23
本文章向大家介绍redis实战第五篇 jedis 连接 redis sentinel详解,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

jedis针对redis sentinel给出了一个JedisSentinelPool,jedis给出了很多的构造方法,其中比较全的是下面这个,注意:这个连接池争对的连接还是主节点:

public JedisSentinelPool(String masterName, Set<String> sentinels,final GenericObjectPoolConfig poolConfig, final int connectionTimeout,final int soTimeout,final String password, final int database,final String clientName)

具体参数含义如下: masterName——主节点名。 sentinels——Sentinel节点集合。 poolConfig——common-pool连接池配置。 connectTimeout——连接超时。 soTimeout——读写超时。 password——主节点密码。(这个是主节点密码,而不是redis sentinel的密码) database——当前数据库索引 clientName——客户端名

但是通常我们会使用更简单的构造方法:

JedisSentinelPool jedisSentinelPool = new JedisSentinelPool(masterName,sentinelSet, poolConfig, timeout, password);

此时timeout既代表连接超时又代表读写超时。

样例代码如下所示:

package com.gildata.duplicateandtagtest.redis;

import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;
import java.util.HashSet;
import java.util.Set;

/**
 * Created by LiChao on 2019/2/11
 */
public class SentinelJedisPool {

    private static JedisSentinelPool pool = null;

    //可用连接实例的最大数目,默认为8;
    //如果赋值为-1,则表示不限制,如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)
    private static Integer MAX_TOTAL = 1024;
    //控制一个pool最多有多少个状态为idle(空闲)的jedis实例,默认值是8
    private static Integer MAX_IDLE = 200;
    //等待可用连接的最大时间,单位是毫秒,默认值为-1,表示永不超时。
    //如果超过等待时间,则直接抛出JedisConnectionException
    private static Integer MAX_WAIT_MILLIS = 10000;
    //客户端超时时间配置
    private static Integer TIMEOUT = 10000;
    //在borrow(用)一个jedis实例时,是否提前进行validate(验证)操作;
    //如果为true,则得到的jedis实例均是可用的
    private static Boolean TEST_ON_BORROW = true;
    //在空闲时检查有效性, 默认false
    private static Boolean TEST_WHILE_IDLE = true;
    //是否进行有效性检查
    private static Boolean TEST_ON_RETURN = true;

    /**
     * 创建连接池
     */
    private static void createJedisPool() {
        JedisPoolConfig config = new JedisPoolConfig();
        /*注意:
            在高版本的jedis jar包,比如本版本2.9.0,JedisPoolConfig没有setMaxActive和setMaxWait属性了
            这是因为高版本中官方废弃了此方法,用以下两个属性替换。
            maxActive  ==>  maxTotal
            maxWait==>  maxWaitMillis
         */
        config.setMaxTotal(MAX_TOTAL);
        config.setMaxIdle(MAX_IDLE);
        config.setMaxWaitMillis(MAX_WAIT_MILLIS);
        config.setTestOnBorrow(TEST_ON_BORROW);
        config.setTestWhileIdle(TEST_WHILE_IDLE);
        config.setTestOnReturn(TEST_ON_RETURN);
        String masterName = "mymaster";
        Set<String> sentinels = new HashSet<String>();
        sentinels.add(new HostAndPort("192.168.0.31",26379).toString());
        sentinels.add(new HostAndPort("192.168.0.32",26379).toString());
        sentinels.add(new HostAndPort("192.168.0.33",26379).toString());
        String password = "1234@abcd";
        pool = new JedisSentinelPool(masterName, sentinels, config, TIMEOUT,password);
    }

    private static synchronized void poolInit() {
        if (pool == null)
            createJedisPool();
    }


    /**
     * 获取一个redis对象
     * @return
     */
    public static Jedis getJedis() {
        if (pool == null)
            poolInit();
        return pool.getResource();
    }

}

注意: 样例代码中的password是主节点的密码,而不是redis sentinel的密码,之前讲过redis sentinel也可以设置密码(传送门),如果使用jedis去连接的redis sentinel带有密码,那么会出现权限不足的问题,因为jedis预留的password参数时争对主节点的,所以如果主节点存在密码,切记在安装redis sentinel的时候不要给redis sentinel设置密码,否则jedis是连接不上的。

测试代码:

    @Test
    public void testSentinel(){
        Jedis jedis = null;
        try{
            jedis = SentinelJedisPool.getJedis();
            jedis.set("sentinel","hello sentinel");
        }catch (Exception e){
            e.printStackTrace();
        } finally {
            if(jedis!=null){
                jedis.close();
            }
        }
    }

执行日志可以看出,此时的主节点是192.168.0.33

16:15:37.121 [main] INFO redis.clients.jedis.JedisSentinelPool - Trying to find master from available Sentinels...
16:15:37.125 [main] DEBUG redis.clients.jedis.JedisSentinelPool - Connecting to Sentinel 192.168.0.31:26379
16:15:37.170 [main] DEBUG redis.clients.jedis.JedisSentinelPool - Found Redis master at 192.168.0.33:6380
16:15:37.171 [main] INFO redis.clients.jedis.JedisSentinelPool - Redis master running at 192.168.0.33:6380, starting Sentinel listeners...
16:15:37.261 [main] INFO redis.clients.jedis.JedisSentinelPool - Created JedisPool to master at 192.168.0.33:6380
hello sentinel

通过info sentinel查看主节点确实是192.168.0.33

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=192.168.0.33:6380,slaves=2,sentinels=3

手动切换主节点

127.0.0.1:26379> sentinel failover mymaster
OK
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=192.168.0.31:6380,slaves=2,sentinels=3

此时主节点变为了192.168.0.31,再次执行测试用例,执行日志如下:

16:32:53.315 [main] INFO redis.clients.jedis.JedisSentinelPool - Trying to find master from available Sentinels...
16:32:53.320 [main] DEBUG redis.clients.jedis.JedisSentinelPool - Connecting to Sentinel 192.168.0.31:26379
16:32:53.369 [main] DEBUG redis.clients.jedis.JedisSentinelPool - Found Redis master at 192.168.0.31:6380
16:32:53.370 [main] INFO redis.clients.jedis.JedisSentinelPool - Redis master running at 192.168.0.31:6380, starting Sentinel listeners...
16:32:53.463 [main] INFO redis.clients.jedis.JedisSentinelPool - Created JedisPool to master at 192.168.0.31:6380
hello sentinel

主节点变为了192.168.0.31,这就是redis sentinel的好处,它能够主动通知应用程序主节点发生了变更,应用程序不需要做任何变化。