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

 

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