Jedis连接池配置详解

写代码是日益精进的不是一蹴而就的,以前写代码就是各处借鉴,然后完成项目的需要就放在那里了,时间长了接触的多了,再来看之前代码总觉得哪里不太对劲(简直垃圾,这能是我写的?),觉得需要改变,这次顺便记录下来,也分享给大家,相当于优化轨迹、版本控制等等,以后还有可能改变,但是最终有迹可循~ 不会麻爪~

application.yml

redis:
  host: 127.0.0.1
  port: 6379
  password: yourpassword
  database: 1
  # 是否分布式
  isSharded: false
  # 最大连接数
  maxTotal: 5000
  # 最大空闲连接数
  maxIdle: 1000
  # 建立连接时,最大等待时间
  maxWaitMillis: 60000
  # 建立连接时,是否进行有效性检查
  testOnBorrow: true

JedisPool.java

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import redis.clients.jedis.*;
import redis.clients.jedis.exceptions.JedisConnectionException;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @Author: Wenx
 * @Description: Redis连接池
 * @Date: Created in 2019/12/15 16:35
 * @Modified By:
 */
@Configuration
public class JedisPool {
    private static Logger logger = LoggerFactory.getLogger(JedisPool.class);

    @Autowired
    private Environment env;
    private String[] hosts;
    private String[] ports;
    private String[] passwords;
    private String[] databases;
    private boolean isSharded;
    private int maxTotal;
    private int maxIdle;
    private long maxWaitMillis;
    private boolean testOnBorrow;

    /**
     * 单节点连接池
     */
    private static redis.clients.jedis.JedisPool jedisPool;
    /**
     * 分布式连接池
     */
    private static ShardedJedisPool shardedJedisPool;

    @Bean
    public void loadConfig() {
        String host = env.getProperty("redis.host");
        if (null != host) {
            hosts = host.split(",");
        }
        String port = env.getProperty("redis.port");
        if (null != port) {
            ports = port.split(",");
        }
        String password = env.getProperty("redis.password");
        if (null != password) {
            passwords = password.split(",");
        }
        String database = env.getProperty("redis.database");
        if (null != database) {
            databases = database.split(",");
        }
        isSharded = env.getProperty("redis.isSharded", Boolean.class);
        maxTotal = env.getProperty("redis.maxTotal", Integer.class);
        maxIdle = env.getProperty("redis.maxIdle", Integer.class);
        maxWaitMillis = env.getProperty("redis.maxWaitMillis", Long.class);
        testOnBorrow = env.getProperty("redis.testOnBorrow", Boolean.class);
    }

    @Bean
    public JedisPoolConfig jedisPoolConfig() {
        // 池基本配置
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(maxTotal);
        config.setMaxIdle(maxIdle);
        config.setMaxWaitMillis(maxWaitMillis);
        config.setTestOnBorrow(testOnBorrow);

        return config;
    }

    @Bean
    public String initial(@Qualifier("jedisPoolConfig") JedisPoolConfig config) {
        if (null != hosts && hosts.length > 0) {
            if (isSharded) {
                initShardedPool(config);
            } else {
                initPool(config);
            }
        } else {
            logger.warn("jedis pool initial host invalid.");
        }
        return null;
    }

    /**
     * 初始化单节点池
     *
     * @param config JedisPoolConfig
     */
    private void initPool(JedisPoolConfig config) {
        logger.info("one redis are:------------------------------{");
        logger.debug("host:[{}], port:[{}].", hosts[0], ports[0]);

        jedisPool = new redis.clients.jedis.JedisPool(config,
                hosts[0], Integer.parseInt(ports[0]), 2000,
                null == passwords ? null : passwords[0],
                null == databases ? 0 : Integer.parseInt(databases[0]));

        logger.info("}------------------------------");
    }

    /**
     * 初始化分布式池
     *
     * @param config JedisPoolConfig
     */
    private void initShardedPool(JedisPoolConfig config) {
        logger.info("shard redis are:------------------------------{");

        // slave连接
        List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();
        for (int i = 0; i < hosts.length; i++) {
            logger.debug("host:[{}], port:[{}].", hosts[i], ports[i]);
            JedisShardInfo jedisShardInfo = new JedisShardInfo(
                    hosts[i], Integer.parseInt(ports[i]), "master");
            jedisShardInfo.setPassword(null == passwords ? null : passwords[0]);
            shards.add(jedisShardInfo);
        }
        shardedJedisPool = new ShardedJedisPool(config, shards);

        logger.info("}------------------------------");
    }

    /**
     * 获取连接
     *
     * @return Jedis
     */
    public static Jedis getJedis() {
        int count = 20;
        while ((count--) > 0) {
            try {
                return jedisPool.getResource();
            } catch (JedisConnectionException e) {
                logger.warn("jedis connection failed, try reconnecting.");
                try {
                    TimeUnit.SECONDS.sleep(2L);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            } catch (Exception e) {
                logger.error("jedis pool get failed, jedisInfo ... NumActive=[{}], NumIdle=[{}], NumWaiters=[{}], isClosed=[{}], error:[{}].",
                        jedisPool.getNumActive(), jedisPool.getNumIdle(),
                        jedisPool.getNumWaiters(), jedisPool.isClosed(), e);
                break;
            }
        }

        return null;
    }

    /**
     * 获取连接
     *
     * @return ShardedJedis
     */
    public static ShardedJedis getShardedJedis() {
        if (shardedJedisPool != null) {
            return shardedJedisPool.getResource();
        }
        return null;
    }

    /**
     * 关闭连接
     *
     * @param jedis Jedis
     */
    public static void close(Jedis jedis) {
        try {
            if (jedis != null) {
                jedis.close();
            }
        } catch (Exception e) {
            logger.error("return jedis resource exception", e);
        }
    }

    /**
     * 关闭连接
     *
     * @param shardedJedis ShardedJedis
     */
    public static void close(ShardedJedis shardedJedis) {
        try {
            if (shardedJedis != null) {
                shardedJedis.close();
            }
        } catch (Exception e) {
            logger.error("return sharded jedis resource exception", e);
        }
    }

    /**
     * 销毁单节点池
     */
    public static void destroy() {
        try {
            jedisPool.destroy();
        } catch (Exception e) {
            logger.error("jedis pool destroy exception", e);
        }
    }

    /**
     * 销毁分布式池
     */
    public static void destroySharded() {
        try {
            shardedJedisPool.destroy();
        } catch (Exception e) {
            logger.error("sharded jedis pool destroy exception", e);
        }
    }

}