redis集群搭建,以及spring boot整合redis集群

redis的集群搭建非常简单,我使用的是redis 4.0.10在centos 7.2 上搭建的,按照配置文件搭建就可以,并且前面的博客收藏了集群搭建的链接。

搭建完以后就是项目中整合redis集群,这里有个小推荐,使用jedis整合redis集群非常简单,下面是整合的步骤:

一、单机版和集群版的redis整合

1)首先在pom.xml中导入jar包

<!-- redis -->
		<dependency>
			<groupId>redis.clients</groupId>
			<artifactId>jedis</artifactId>
			<version>2.9.0</version>
		</dependency>

说明:这里导入的jar包是2.9的jedis,由于我使用的是4.0.10版本,版本比较新,所以至少要使用2.9或以上版本,不然启动的过程中会报错,抛出的异常是 java.lang.NumberFormatException:   6004@16004    类似这样的异常。 

2)单机版的配置文件 需要写在  application.properties 如下

#Redis Pool ============================================================================================================

jedis.pool.host=127.0.0.1
jedis.pool.port=6379
jedis.pool.timeout=30000
jedis.pool.password=password123


jedis.pool.dbIndex=0
jedis.pool.maxTotal=300
jedis.pool.maxIdle=10
jedis.pool.maxWaitMillis=30000

3) 集群版的配置文件需要在  resources  下新建一个文件  redis.properties,内容如下

#redis cluster
xyy.redis.pool.nodes=192.168.3.141:6000,192.168.3.141:6001,192.168.3.141:6002,192.168.3.143:6003,192.168.3.143:6004,192.168.3.143:6005,192.168.3.144:6006,192.168.3.144:6007,192.168.3.144:6008
xyy.redis.pool.timeout=3000
xyy.redis.pool.soTimeout=1500
xyy.redis.pool.maxAttempts=5
xyy.redis.pool.password=password23

4)实现单机版的jedis连接 redis 代码

package com.qzt.common.redis;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import com.qzt.util.PubFunc;

import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

@Slf4j
@Configuration
public class RedisConfiguration {
	
	@Primary
	@Bean(name="jedisPool")
	public JedisPool jedisPool(@Qualifier("jedisPoolConfig") JedisPoolConfig config, 
			@Value("${jedis.pool.host}")String host, 
			@Value("${jedis.pool.port}")int port, 
			@Value("${jedis.pool.timeout}")int timeout, 
			@Value("${jedis.pool.password}")String passowrd, 
			@Value("${jedis.pool.dbIndex}")int dbIndex){
		log.info("init redis pool -------------->host:{},port:{},dbIndex",host,port,dbIndex);
		if(PubFunc.isNull(passowrd)){
			passowrd = null;
		}
		return new JedisPool(config,host,port,timeout,passowrd,dbIndex);
	}
	@Primary
	@Bean(name="jedisPoolConfig")
	public JedisPoolConfig jedisPoolConfig(@Value("${jedis.pool.maxTotal}")int maxTotal, 
			@Value("${jedis.pool.maxIdle}")int maxIdle, 
			@Value("${jedis.pool.maxWaitMillis}")int maxWaitMillis){
		JedisPoolConfig config = new JedisPoolConfig();
		config.setMaxTotal(maxTotal);
		config.setMaxIdle(maxIdle);
		config.setMaxWaitMillis(maxWaitMillis);
		return config;
	}
}

5)实现集群版的jedis连接 redis 代码,需要写两个类来实现 一个  RedisProperties.java  ,一个JedisClusterConfig.java

RedisProperties.java 类内容如下:

package com.qzt.common.redis;

import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * redis集群配置文件
 * @ClassName: RedisProperties
 * @author suziqing
 */
@Data
@Component
@ConfigurationProperties(prefix = "xyy.redis.pool")
@PropertySource("classpath:redis.properties")
public class RedisProperties {
    /** redis集群节点 */
    private String nodes;
    /** 连接超时时间 */
    private int timeout;
    /** 重连次数 */
    private int maxAttempts;
    private String password;
    //读取数据超时时间
    private int   soTimeout;
 
    public RedisProperties() {
    }
 
	public RedisProperties(String nodes, int timeout, int maxAttempts, String password, int soTimeout) {
	this.nodes = nodes;
	this.timeout = timeout;
	this.maxAttempts = maxAttempts;
	this.password = password;
	this.soTimeout = soTimeout;
}


}

JedisClusterConfig.java 代码如下:

package com.qzt.common.redis;

import java.util.HashSet;

/**
 * 生成JedisCluster对象
 * @ClassName: JedisClusterConfig
 * @author suziqing
 * @date 2018年7月10日18:07:04
 */
@Slf4j
@Configuration
public class JedisClusterConfig {
    @Autowired
    private RedisProperties redisProperties;
 
    /**
     * 注意:
     * 这里返回的JedisCluster是单例的,并且可以直接注入到其他类中去使用
     * @return
     */
    @Bean
    public JedisCluster getJedisCluster() {
    	log.info("---------getJedisCluster-----");
        String[] serverArray = redisProperties.getNodes().split(",");//获取服务器数组(这里要相信自己的输入,所以没有考虑空指针问题)
        Set<HostAndPort> nodes = new HashSet<HostAndPort>();
        log.info("---------getTimeout-----"+redisProperties.getTimeout()+"------getMaxAttempts-----"+redisProperties.getMaxAttempts());
        try{
        	for (String ipPort : serverArray) {
                String[] ipPortPair = ipPort.split(":");
                log.info("----ipPortPair[0]----------"+ipPortPair[0]+"----ipPortPair[1]----------"+ipPortPair[1]);
                nodes.add(new HostAndPort(ipPortPair[0].trim(), Integer.valueOf(ipPortPair[1].trim())));
            }
		}catch (Exception e){
			log.info("-------------exception--------222----------");
		}
//        soTime  读取数据超时间
        return new JedisCluster(nodes, redisProperties.getTimeout(), redisProperties.getSoTimeout(), redisProperties.getMaxAttempts(), redisProperties.getPassword(), new GenericObjectPoolConfig());
    }
}

 

6)集成单机版和集群版的工具类

package com.qzt.manager;

import java.io.IOException;

@Slf4j
@Component
public class JedisManager {

	@Autowired
	public JedisPool jedisPool;
	public static JedisManager jedisManager;
	
	@Autowired
	private  JedisClusterConfig jedisClusterConfig;

	@PostConstruct
	public void init() {
		jedisManager = this;
		if (PubPara.isCloud){//平台端就使用 集群版配置
			jedisManager.jedisClusterConfig = this.jedisClusterConfig;
		}else{//设备端就是用单机版
			jedisManager.jedisPool = this.jedisPool;
		}
		
	}

	public static void set(String key, String value) {
		JedisCluster jedisCluster = null;
		Jedis  jedis = null;
		try {
			if (PubPara.isCloud){
				log.info("-------jedisClusterConfig---------"+jedisManager.jedisClusterConfig);
				jedisCluster = jedisManager.jedisClusterConfig.getJedisCluster();
				jedisCluster.set(key, value);
			}else{
				log.info("-------jedis---333333333------"+jedisManager.jedisClusterConfig);
				jedis = jedisManager.jedisPool.getResource();
				jedis.set(key, value);
			}
			
		} catch (Exception e) {
			log.info("jedis error:", e);
		} finally {
			//这里不需要关闭,我们使用的是redis3.0的集群,
//			用jedis的JedisCluster.close()方法造成的集群连接关闭的情况。 
//			jedisCluster内部使用了池化技术,
//			每次使用完毕都会自动释放Jedis因此不需要关闭。如果调用close方法后再调用jedisCluster的api进行操作时就会出现如上错误
			if (!PubPara.isCloud){
				jedis.close();
			}
		}
	}

	public static String get(String key) {
		JedisCluster jedisCluster = null;
		Jedis  jedis = null;
		try {
			if (PubPara.isCloud){
				jedisCluster = jedisManager.jedisClusterConfig.getJedisCluster();
				return  jedisCluster.get(key);
			}else{
				jedis = jedisManager.jedisPool.getResource();
				return jedis.get(key);
			}
			 
		} catch (Exception e) {
			log.info("jedis error:", e);
		} finally {
			if (!PubPara.isCloud){
				jedis.close();
			}
		}
		return null;
	}

	public static void del(String key) {
		JedisCluster jedisCluster = null;
		Jedis  jedis = null;
		try {
			if (PubPara.isCloud){
			jedisCluster = jedisManager.jedisClusterConfig.getJedisCluster();
			if (jedisCluster.exists(key)) {
				jedisCluster.del(key);
			}
			}else{
				jedis = jedisManager.jedisPool.getResource();
				if (jedis.exists(key)){
					jedis.del(key);
				}
			}
		} catch (Exception e) {
			log.info("jedis error:", e);
		} finally {
			if (!PubPara.isCloud){
				jedis.close();
			}
		}
	}
	public static void hdel(String key,List<String> fields) {
		JedisCluster jedisCluster = null;
		Jedis  jedis = null;
		try {
			if (PubPara.isCloud){
			jedisCluster = jedisManager.jedisClusterConfig.getJedisCluster();
			if (jedisCluster.exists(key)) {
				for(String field:fields){
					jedisCluster.hdel(key, field);
				}
			}
			}else{
				jedis = jedisManager.jedisPool.getResource();
				if (jedis.exists(key)){
					for (String field : fields){
						jedis.hdel(key, field);
					}
				}
			}
		} catch (Exception e) {
			log.info("jedis error:", e);
		} finally {
			if (!PubPara.isCloud){
				jedis.close();
			}
		}
	}
	
	public static void hdelOne(String key,String fields) {
		JedisCluster jedisCluster = null;
		Jedis  jedis = null;
		try {
			if (PubPara.isCloud){
			jedisCluster = jedisManager.jedisClusterConfig.getJedisCluster();
			if (jedisCluster.exists(key)) {
				jedisCluster.hdel(key, fields);
			}
			}
			else{
				jedis = jedisManager.jedisPool.getResource();
				if (jedis.exists(key)){
					jedis.hdel(key, fields);
				}
			}
		} catch (Exception e) {
			log.info("jedis error:", e);
		} finally {
			if (!PubPara.isCloud){
				jedis.close();
			}
		}
	}
	
	public static void hmset(String key, Map<String, String> map) {
		JedisCluster jedisCluster = null;
		Jedis  jedis = null;
		try {
			if (PubPara.isCloud){
			jedisCluster = jedisManager.jedisClusterConfig.getJedisCluster();
			if (jedisCluster.exists(key)) {
				jedisCluster.del(key);
			}
			jedisCluster.hmset(key, map);
			}else{
				jedis = jedisManager.jedisPool.getResource();
				if (jedis.exists(key)){
					jedis.del(key);
				}
				jedis.hmset(key, map);
			}
		} catch (Exception e) {
			log.info("jedis error:", e);
		} finally {
			if (!PubPara.isCloud){
				jedis.close();
			}
		}
	}

	public static Map<String, String> hmget(String key) {
		Map<String, String> map = new HashMap<String, String>();
		JedisCluster jedisCluster = null;
		Jedis  jedis = null;
		try {
			if (PubPara.isCloud){
			jedisCluster = jedisManager.jedisClusterConfig.getJedisCluster();
			if (jedisCluster.exists(key)) {
				Set<String> keys = jedisCluster.hkeys(key);
				for (String k : keys) {
					map.put(k, jedisCluster.hmget(key, k).get(0));
				}
			}
			}else{
				jedis = jedisManager.jedisPool.getResource();
				if (jedis.exists(key)){
					Set<String> keys = jedis.hkeys(key);
					for (String k : keys){
						map.put(k, jedis.hmget(key, k).get(0));
					}
				}
			}
		} catch (Exception e) {
			log.info("jedis error:", e);
		} finally {
			if (!PubPara.isCloud){
				jedis.close();
			}
		}

		return map;
	}
	
	public static Map<String, String> hmget(String key,String name) {
		Map<String, String> map = new HashMap<String, String>();
		JedisCluster jedisCluster = null;
		Jedis  jedis = null;
		try {
			if (PubPara.isCloud){
			jedisCluster = jedisManager.jedisClusterConfig.getJedisCluster();
			if (jedisCluster.exists(key)) {
				Set<String> keys = jedisCluster.hkeys(key);
				for (String k : keys) {
					if(k.contains(name)){
						map.put(k, jedisCluster.hmget(key, k).get(0));
					}
				}
			}
			}else{
				jedis = jedisManager.jedisPool.getResource();
				if (jedis.exists(key)){
					Set<String> keys = jedis.hkeys(key);
					for (String k : keys){
						if (k.contains(name)){
							map.put(k, jedis.hmget(key, k).get(0));
						}
					}
				}
			}
		} catch (Exception e) {
			log.info("jedis error:", e);
		} finally {
			if (!PubPara.isCloud){
				jedis.close();
			}
		}

		return map;
	}

	public static boolean exists(String key) {
		boolean flag = false;
		JedisCluster jedisCluster = null;
		Jedis  jedis = null;
		try {
			if (PubPara.isCloud){
			jedisCluster = jedisManager.jedisClusterConfig.getJedisCluster();
			flag = jedisCluster.exists(key);
			}else{
				jedis = jedisManager.jedisPool.getResource();
				flag = jedis.exists(key);
			}
		} catch (Exception e) {
			log.info("jedis error:", e);
		} finally {
			if (!PubPara.isCloud){
				jedis.close();
			}
		}
		return flag;
	}
	public static boolean hexists(String key,String field) {
		boolean flag = false;
		JedisCluster jedisCluster = null;
		Jedis  jedis = null;
		try {
			if (PubPara.isCloud){
			jedisCluster = jedisManager.jedisClusterConfig.getJedisCluster();
			flag = jedisCluster.hexists(key, field);
			}else{
				jedis = jedisManager.jedisPool.getResource();
				flag = jedis.hexists(key, field);
			}
		} catch (Exception e) {
			log.info("jedis error:", e);
		} finally {
			if (!PubPara.isCloud){
				jedis.close();
			}
		}
		return flag;
	}
	
	public static void hmsetNoDel(String key, Map<String, String> map) {
		JedisCluster jedisCluster = null;
		Jedis  jedis = null;
		try {
			if (PubPara.isCloud){
			jedisCluster = jedisManager.jedisClusterConfig.getJedisCluster();
			jedisCluster.hmset(key, map);
			}else{
				jedis = jedisManager.jedisPool.getResource();
				jedis.hmset(key, map);
			}
		} catch (Exception e) {
			log.info("jedis error:", e);
		} finally {
			if (!PubPara.isCloud){
				jedis.close();
			}
		}
	}

	public static void subscribe(RedisMsgPubSubListener listener,
			String redisChat) {

		JedisCluster jedisCluster = null;
		Jedis  jedis = null;
		try {
			if (PubPara.isCloud){
			jedisCluster = jedisManager.jedisClusterConfig.getJedisCluster();
			/**
			 * 注意:subscribe是一个阻塞的方法,在取消订阅该频道前,会一直阻塞在这,只有当取消了订阅才会执行下面的other code,
			 * 参考上面代码,我在onMessage里面收到消息后,调用了this.unsubscribe();
			 * 来取消订阅,这样才会执行后面的other code redisChat 频道名称
			 */
			jedisCluster.subscribe(listener, redisChat);
			// 如果没有取消订阅,方法将一直堵塞在此处不会向下执行
			// to do others
			}else{
				jedis = jedisManager.jedisPool.getResource();
				jedis.subscribe(listener, redisChat);
			}
		} catch (Exception e) {
			log.error("bbbbbbbbbbberror:", e);
		} finally {
			if (!PubPara.isCloud){
				jedis.close();
			}
		}
	}

	public static void sendToC(String redisChat, String value) {
		JedisCluster jedisCluster = null;
		Jedis  jedis = null;
		try {
			if (PubPara.isCloud){
			jedisCluster = jedisManager.jedisClusterConfig.getJedisCluster();
			jedisCluster.publish(redisChat, value);
			}else{
				jedis = jedisManager.jedisPool.getResource();
				jedis.publish(redisChat, value);
			}
		} catch (Exception e) {
			log.error("error:", e);
		} finally {
			if (!PubPara.isCloud){
				jedis.close();
			}
		}
	}

	public static void hset(String key, String field, String value) {
		JedisCluster jedisCluster = null;
		Jedis  jedis = null;
		try {
			if (PubPara.isCloud){
			jedisCluster = jedisManager.jedisClusterConfig.getJedisCluster();
			jedisCluster.hset(key, field, value);
			}else{
				jedis = jedisManager.jedisPool.getResource();
				jedis.hset(key, field, value);
			}
		} catch (Exception e) {
			log.error("error:", e);
		} finally {
			if (!PubPara.isCloud){
				jedis.close();
			}
		}
	}

	public static String hget(String key, String field) {
		String result = "";
		JedisCluster jedisCluster = null;
		Jedis  jedis = null;
		try {
			if (PubPara.isCloud){
			jedisCluster = jedisManager.jedisClusterConfig.getJedisCluster();
			result = jedisCluster.hget(key, field);
			}else{
				jedis = jedisManager.jedisPool.getResource();
				result = jedis.hget(key, field);
			}
		} catch (Exception e) {
			log.error("error:", e);
		} finally {
			if (!PubPara.isCloud){
				jedis.close();
			}
		}
		return result;
	}

	public static long lpush(String key, String field) {
		long count = 0;
		JedisCluster jedisCluster = null;
		Jedis  jedis = null;
		try {
			if (PubPara.isCloud){
			jedisCluster = jedisManager.jedisClusterConfig.getJedisCluster();
			count = jedisCluster.lpush(key, field);
			}else{
				jedis = jedisManager.jedisPool.getResource();
				count = jedis.lpush(key, field);
			}
		} catch (Exception e) {
			log.error("error:", e);
		} finally {
			if (!PubPara.isCloud){
				jedis.close();
			}
		}
		return count;
	}

	public static List<String> lrange(String key, long start, long end) {
		List<String> result = null;
		JedisCluster jedisCluster = null;
		Jedis  jedis = null;
		try {
			if (PubPara.isCloud){
			jedisCluster = jedisManager.jedisClusterConfig.getJedisCluster();
			result = jedisCluster.lrange(key, start, end);
			}else{
				jedis = jedisManager.jedisPool.getResource();
				result = jedis.lrange(key, start, end);
			}
		} catch (Exception e) {
			log.error("error:", e);
		} finally {
			if (!PubPara.isCloud){
				jedis.close();
			}
		}
		return result;
	}

}

 

7)测试类测试  在一个controller中写如下代码进行测试

@RequestMapping("/jedis/test")
	public void testLicense(){
		
		JedisCluster jedisCluster = jedisClusterConfig.getJedisCluster();
		
//		 String className = jedisCluster.get("class");
//       log.info("班级="+className);
//       String age = jedisCluster.get("age");
//       log.info("年龄="+age);
//       jedisCluster.set("yanzhenma","87878");
//       String yanzhenma = jedisCluster.get("yanzhenma");
//       log.info("验证码="+yanzhenma);
//       List<String> list = jedisCluster.lrange("list", 0, -1);
//         for (String string : list){
//			log.info("-------result------"+string);
//		}
//		
         JedisManager.set("feiyi", "kunhua");
         String string = JedisManager.get("feiyi");
         log.info("---------string---------"+string);
         
         JedisManager.hset("qwe", "www", "eee");
         String hget = JedisManager.hget("qwe", "www");
         log.info("----hget-------"+hget);
}

注:在整合的过程中遇到一些问题:

1)第一个就是启动不了的问题,老是报 数字转化异常 ,日志打印出来都是数字没有问题得,上网找了以后明白了是jedis版本过低导致的,将jedis改为  2.9 就可以了

2)第二个问题就是使用集群版的时候  我写了这么一句:  jedisCluster.close(); 导致使用使用jedis操作redis的时候报错,抛出JedisNoReachableClusterNodeException异常(No reachable node in cluster)  ,通过网上查询明白jedisCluster内部使用了池化技术, 每次使用完毕都会自动释放Jedis因此不需要关闭。如果调用close方法后再调用jedisCluster的api进行操作时就会出现如上错误。 

3)第三个就是我们需要将单机版和集群版在一个项目中都还可以使用,通过配置文件来控制使用集群版还是单机版。为了这个需求就有了上面工具类中的判断是否为平台端的代码。

4)前面说了推荐使用jedis 来连接redis,好处就是连接方便简单,最后测试证明单机版和集群版都可以在一套代码中实现

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值