spring 快速搭建 redis集群

好记性不如烂笔头

首先你的redis集群必须能正常启动

1.引用包

<!-- redis依赖 -->
		<dependency>
			<groupId>redis.clients</groupId>
			<artifactId>jedis</artifactId>
			<version>${redis.version}</version>
		</dependency>
		<dependency>
        	<groupId>org.springframework.data</groupId>
        	<artifactId>spring-data-redis</artifactId>
        	<version>2.1.9.RELEASE</version>
    	</dependency>
		<!-- redis分布式锁架构(本文与此扎包无关除非你用到分布式锁) -->
		<dependency>
			<groupId>org.redisson</groupId>
			<artifactId>redisson</artifactId>
			<version>${redisson.version}</version>
		</dependency>

2.在项目中编写JedisClusterFactory

package com.eprintServer.util.redis;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Pattern;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
//import org.springframework.core.io.Resource;

import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigService;

import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;

/**
 * Jedis集群工厂
 * @author mj
 * @Date 2020-04-14
 */
public class JedisClusterFactory implements InitializingBean,FactoryBean<JedisCluster>{
	//对应spring redis配置文件中的 property的name
//    private Resource addressConfig;
    
    private JedisCluster jedisCluster;
    /**
     * 读取数据超时时间
     */
    private int soTimeout;
    /**
     * 代表集群有几台redis
     */
    private int maxRedirections;
    /**
     * 最大空闲数
     */
	private int maxIdle;
	/**
	 *最小空闲数 
	 */
	private int minIdle;
	/**
	 * 连接池最大连接数
	 */
	private int maxTotal;
	/**
	 * 最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。 
	 */
	private long maxWaitMillis;
	/**
	 * 连接最小空闲时间默认1000L * 60L * 30L --30分钟  
	 */
	private long minEvictableIdleTimeMillis;
	/**
	 * 空闲连接检测周期但闻毫秒  -1不检测
	 */
	private long timeBetweenEvictionRunsMillis;
	/**
	 * 连接超时时间
	 */
	private int connectionTimeout;
	/**
	 * 密码
	 */
	private String password;
    /**
     * 实现 InitializingBean 的接口,初始化的 得到 jedisCluster
     */
    public void afterPropertiesSet() throws Exception {
    	Set<HostAndPort> jedisClusterNode= this.parseHostAndPort();
    	//配置连接池作用
    	GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();
//    	#最大空闲数,数据库连接的最大空闲时间。超过空闲时间,数据库连接将被标记为不可用,然后被释放。设为0表示无限制。 默认8  
    	if(maxIdle > 0)genericObjectPoolConfig.setMaxIdle(maxIdle);
//    	#最小空闲数,数据库连接的最大空闲时间。超过空闲时间,数据库连接将被标记为不可用,然后被释放。设为0表示无限制。  默认0
    	if(minIdle > 0)genericObjectPoolConfig.setMinIdle(minIdle);
//    	#(连接池最大连接数)在指定时刻通过pool能够获取到的最大的连接的jedis个数,默认值8
    	if(maxTotal > 0)genericObjectPoolConfig.setMaxTotal(maxTotal);
//    	#最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。 
    	if(maxWaitMillis > 0 || maxWaitMillis == -1)genericObjectPoolConfig.setMaxWaitMillis(maxWaitMillis);
//    	#连接最小空闲时间默认1000L * 60L * 30L --30分钟  
    	if(minEvictableIdleTimeMillis > 0)genericObjectPoolConfig.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
//    	#在空闲时检查有效性, 默认false
//    	genericObjectPoolConfig.setTestWhileIdle(true);
//    	#空闲连接检测周期但闻毫秒 默认-1不检测
//    	genericObjectPoolConfig.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
    	//是否打开jmx监控。这样就可以jvm调优时。通过jconsole 或者 jvisualvm 看到详细使用情况:默认是true
//    	genericObjectPoolConfig.setJmxEnabled(false);
//    	#在borrow一个jedis实例时,是否提前进行alidate操作;如果为true,则得到的jedis实例均是可用的;默认fasle  
//    	genericObjectPoolConfig.setTestOnBorrow(false);
    	if(!isNull(password)) {
    		jedisCluster = new JedisCluster(jedisClusterNode, connectionTimeout, soTimeout, maxRedirections, password, genericObjectPoolConfig);
    	}else {
    		jedisCluster = new JedisCluster(jedisClusterNode, soTimeout, maxRedirections, genericObjectPoolConfig);
    	}
    }

    /**
     * 实现 FactoryBean 的接口
     * 获取 jedisCluster对象
     */
    public JedisCluster getObject() throws Exception {
        return jedisCluster;
    }

    /**
     * 实现 FactoryBean 的接口
     * 获取 jedisCluster的类型
     */
    public Class<? extends JedisCluster> getObjectType() {
        return (jedisCluster != null ? this.jedisCluster.getClass() : JedisCluster.class);
    }

    /**
     * 实现 FactoryBean 的接口
     */
    public boolean isSingleton() {
        return true;
    }
    
    /**
     * 解析Jedis配置文件,看是否满足 IP和端口
     * @return
     */
    private Set<HostAndPort> parseHostAndPort() throws Exception{
    	// 正则表达式 匹配 ip和port
        Pattern p = Pattern.compile("^.+[:]\\d{1,5}\\s*$");
        Set<HostAndPort> hostAndPorts = new HashSet<HostAndPort>();
        //到时间采用配置中心获取配置参数
        InputStream ins = JedisClusterFactory.class.getResourceAsStream("/redis.properties");
        if(ins!=null) {
        	try {
        		Properties properties = new Properties();
//            properties.load(this.addressConfig.getInputStream());
        		properties.load(ins);
        		for(Object key : properties.keySet()){
        			// 如果key不是以 address的值 开头,则continue
        			if(!((String)key).startsWith("address")){
        				continue;
        			}
        			// 根据 key从properties中取出值
        			String valus = (String) properties.get(key);
        			// 判断取出的value是否是ip和port
        			boolean isIPProt = p.matcher(valus).matches();
        			if(!isIPProt){
        				throw new IllegalArgumentException("ip和port不合法!");
        			}
        			String[] ipAndPort = valus.split(":");
        			HostAndPort hostAndPort = new HostAndPort(ipAndPort[0], Integer.parseInt(ipAndPort[1]));
        			hostAndPorts.add(hostAndPort);
        		}
        		
        		if(!isNull(properties.getProperty("redis.soTimeout")))soTimeout = Integer.valueOf(properties.getProperty("redis.soTimeout").trim());
        		if(!isNull(properties.getProperty("redis.maxRedirections")))maxRedirections = Integer.valueOf(properties.getProperty("redis.maxRedirections").trim());
        		if(!isNull(properties.getProperty("redis.maxIdle")))maxIdle = Integer.valueOf(properties.getProperty("redis.maxIdle").trim());
        		if(!isNull(properties.getProperty("redis.minIdle")))minIdle = Integer.valueOf(properties.getProperty("redis.minIdle").trim());
        		if(!isNull(properties.getProperty("redis.maxTotal")))maxTotal = Integer.valueOf(properties.getProperty("redis.maxTotal").trim());
        		if(!isNull(properties.getProperty("redis.maxWaitMillis")))maxWaitMillis = Long.valueOf(properties.getProperty("redis.maxWaitMillis").trim());
        		if(!isNull(properties.getProperty("redis.minEvictableIdleTimeMillis")))minEvictableIdleTimeMillis = Long.valueOf(properties.getProperty("redis.minEvictableIdleTimeMillis").trim());
        		if(!isNull(properties.getProperty("redis.connectionTimeout")))connectionTimeout = Integer.valueOf(properties.getProperty("redis.connectionTimeout").trim());
        		if(!isNull(properties.getProperty("redis.password")))password = properties.getProperty("redis.password").trim();
        	} catch (Exception e) {
        		e.printStackTrace();
        		throw new Exception("解析 jedis 配置文件失败!");
        	}
        }else {
        	try{
        		//此 方法使用的是 apollo 配置中心调用参数 
        		Config config = ConfigService.getConfig("public_dubbo");
        		if(!isNull(config.getProperty("redis.soTimeout",null)))soTimeout = Integer.valueOf(config.getProperty("redis.soTimeout",null).trim());
        		if(!isNull(config.getProperty("redis.maxRedirections",null)))maxRedirections = Integer.valueOf(config.getProperty("redis.maxRedirections",null).trim());
        		if(!isNull(config.getProperty("redis.maxIdle",null)))maxIdle = Integer.valueOf(config.getProperty("redis.maxIdle",null).trim());
        		if(!isNull(config.getProperty("redis.minIdle",null)))minIdle = Integer.valueOf(config.getProperty("redis.minIdle",null).trim());
        		if(!isNull(config.getProperty("redis.maxTotal",null)))maxTotal = Integer.valueOf(config.getProperty("redis.maxTotal",null).trim());
        		if(!isNull(config.getProperty("redis.maxWaitMillis",null)))maxWaitMillis = Long.valueOf(config.getProperty("redis.maxWaitMillis",null).trim());
        		if(!isNull(config.getProperty("redis.minEvictableIdleTimeMillis",null)))minEvictableIdleTimeMillis = Long.valueOf(config.getProperty("redis.minEvictableIdleTimeMillis",null).trim());
        		if(!isNull(config.getProperty("redis.connectionTimeout",null)))connectionTimeout = Integer.valueOf(config.getProperty("redis.connectionTimeout",null).trim());
        		if(!isNull(config.getProperty("redis.password",null)))password = config.getProperty("redis.password",null);
        		String address = config.getProperty("redis.address",null);
        		if(!isNull(address)) {
        			String[] ip = address.split(",");
        			for (String str : ip) {
        				boolean isIPProt = p.matcher(str).matches();
            			if(!isIPProt){
            				throw new IllegalArgumentException("ip和port不合法!");
            			}
            			String[] ipAndPort = str.split(":");
            			HostAndPort hostAndPort = new HostAndPort(ipAndPort[0], Integer.parseInt(ipAndPort[1]));
            			hostAndPorts.add(hostAndPort);
					}
        		}
        		}catch(Exception ex){
        			ex.printStackTrace();
        		}
        }
        return hostAndPorts;
    }
    
	public static boolean isNull(String arg) {
		if (arg == null)
			return true;
		if ("".equals(arg))
			return true;
		if ("".equals(arg.trim()))
			return true;
		return false;
	}
    // set方法
    public void setJedisCluster(JedisCluster jedisCluster) {
        this.jedisCluster = jedisCluster;
    }
//    public void setAddressConfig(Resource addressConfig) {
//        this.addressConfig = addressConfig;
//    }
	public void setSoTimeout(int soTimeout) {
		this.soTimeout = soTimeout;
	}

	public void setMaxRedirections(int maxRedirections) {
		this.maxRedirections = maxRedirections;
	}
	public void setConnectionTimeout(int connectionTimeout) {
	}
	public void setMaxIdle(int maxIdle) {
		this.maxIdle = maxIdle;
	}
	public void setMinIdle(int minIdle) {
		this.minIdle = minIdle;
	}
	public void setMaxTotal(int maxTotal) {
		this.maxTotal = maxTotal;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public void setMaxWaitMillis(long maxWaitMillis) {
		this.maxWaitMillis = maxWaitMillis;
	}
    
}

3.在你的ApplicationContext-main.xml 中 添加指定你新建的类地址

 <!-- 配置reids 集裙工厂 -->
	<bean id="jedisCluster" class="com.eprintServer.util.redis.JedisClusterFactory">  
    </bean> 

4.在你的action 类或者 Controller 类注入进来就可以了

@Resource
	private JedisCluster jedisCluster;

这是我的redis 配置

#注意,如果没有password,此处不设置值
redis.password=
#最大空闲数,数据库连接的最大空闲时间。超过空闲时间,数据库连接将被标记为不可用,然后被释放。设为0表示无限制。  
redis.maxIdle=300
#最小空闲数,数据库连接的最大空闲时间。超过空闲时间,数据库连接将被标记为不可用,然后被释放。设为0表示无限制。  
redis.minIdle=8
#最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。  
redis.maxWaitMillis=1000
#在borrow一个jedis实例时,是否提前进行alidate操作;如果为true,则得到的jedis实例均是可用的;默认fasle  
redis.testOnBorrow=true
#在指定时刻通过pool能够获取到的最大的连接的jedis个数,默认值8
redis.maxTotal=100
#在空闲时检查有效性, 默认false
redis.testWhileIdle=false
#连接最小空闲时间(毫秒)默认 1000L * 60L * 30L 
redis.minEvictableIdleTimeMillis=900000
#读取数据超时时间(毫秒)
redis.soTimeout=300000
# 连接超时时间
redis.connectionTimeout=300000
#总共有多少台redis集裙
redis.maxRedirections=6
#//        Adding replica 192.168.41.30:6380 to 192.168.41.65:6379
#//        Adding replica 192.168.41.40:6380 to 192.168.41.42:6379
#//        Adding replica 192.168.41.20:6380 to 192.168.41.70:6379
#集裙地址以及端口
address1=192.168.41.40:6379
address2=192.168.41.65:6379
address3=192.168.41.70:6379
address4=192.168.41.20:6380
address5=192.168.41.30:6380
address6=192.168.41.40:6380

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章