redis cluster集群进行和SSM整合

23 篇文章 1 订阅

redis cluster集群和SSM整合,用两种方式来实现整合

手动方式(也是客户端(JedisCluster )的方式来实现)

关于手动方式请参考Spring+Mybatis+redis整合(用依赖注入的方式手动修改缓存)
redis.properties

redis.pool.maxTotal=30
redis.pool.maxIdle=10
redis.pool.numTestsPerEvictionRun=1024
redis.pool.timeBetweenEvictionRunsMillis=30000
redis.pool.minEvictableIdleTimeMillis=1800000
redis.pool.softMinEvictableIdleTimeMillis=10000
redis.pool.maxWaitMillis=1500
redis.pool.testOnBorrow=true
redis.pool.testWhileIdle=true
redis.pool.blockWhenExhausted=false
redis.maxRedirects=3
redis.host=127.0.0.1
redis.port=6383
redis.host2=127.0.0.1
redis.port2=6384
redis.host3=127.0.0.1
redis.port3=6385
redis.host4=127.0.0.1
redis.port4=6380
redis.host5=127.0.0.1
redis.port5=6381
redis.host6=127.0.0.1
redis.port6=6382

spring-redis.xml

	<!--扫描包-->
	<context:component-scan base-package="cn.qlq.Redis"/>
	<!--扫描配置文件-->
	<context:property-placeholder location="classpath:redis.properties" ignore-unresolvable="true"/>
	<!-- 连接池配置,下面值的注入有的是${},有的是直接写的值,因为这里有类型注入错误,redis.properties里的值注入是String类型,
	但是在JedisPoolConfig有的不是String类型,有in,long等,会报错 -->
	<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
		<!-- 最大连接数 -->
		<property name="maxTotal" value="${redis.pool.maxTotal}" />
		<!-- 最大空闲连接数 -->
		<property name="maxIdle" value="${redis.pool.maxIdle}" />
		<!-- 每次释放连接的最大数目 -->
	 	<property name="numTestsPerEvictionRun"  value="1024" />
		<!-- 释放连接的扫描间隔(毫秒) -->
		<property name="timeBetweenEvictionRunsMillis" value="30000" />
		<!-- 连接最小空闲时间 -->
		<property name="minEvictableIdleTimeMillis" value="1800000" />
		<!-- 连接空闲多久后释放, 当空闲时间>该值 且 空闲连接>最大空闲连接数 时直接释放 -->
		<property name="softMinEvictableIdleTimeMillis" value="${redis.pool.softMinEvictableIdleTimeMillis}" />
		<!-- 获取连接时的最大等待毫秒数,小于零:阻塞不确定的时间,默认-1 -->
		<property name="maxWaitMillis" value="${redis.pool.maxWaitMillis}" />
		<!-- 在获取连接的时候检查有效性, 默认false -->
		<property name="testOnBorrow" value="${redis.pool.testOnBorrow}" />
		<!-- 在空闲时检查有效性, 默认false -->
		<property name="testWhileIdle" value="${redis.pool.testWhileIdle}" />
		<!-- 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true -->
		<property name="blockWhenExhausted" value="${redis.pool.blockWhenExhausted}" />
	</bean>	
	<bean id="jedisCluster" class="redis.clients.jedis.JedisCluster">  
        <constructor-arg>  
            <set>  
                <bean class="redis.clients.jedis.HostAndPort">  
                    <constructor-arg name="host" value="${redis.host}"></constructor-arg>  
                    <constructor-arg name="port" value="${redis.port}"></constructor-arg>  
                </bean>  
                <bean class="redis.clients.jedis.HostAndPort">  
                    <constructor-arg name="host" value="${redis.host2}"></constructor-arg>  
                    <constructor-arg name="port" value="${redis.port2}"></constructor-arg>  
                </bean>  
                <bean class="redis.clients.jedis.HostAndPort">  
                    <constructor-arg name="host" value="${redis.host3}"></constructor-arg>  
                    <constructor-arg name="port" value="${redis.port3}"></constructor-arg>  
                </bean>  
                <bean class="redis.clients.jedis.HostAndPort">  
                    <constructor-arg name="host" value="${redis.host4}"></constructor-arg>  
                    <constructor-arg name="port" value="${redis.port4}"></constructor-arg>  
                </bean>  
                <bean class="redis.clients.jedis.HostAndPort">  
                    <constructor-arg name="host" value="${redis.host5}"></constructor-arg>  
                    <constructor-arg name="port" value="${redis.port5}"></constructor-arg>  
                </bean>  
                <bean class="redis.clients.jedis.HostAndPort">  
                    <constructor-arg name="host" value="${redis.host6}"></constructor-arg>  
                    <constructor-arg name="port" value="${redis.port6}"></constructor-arg>  
                </bean>  
            </set>  
        </constructor-arg>  
    </bean>  

redisDao接口

public interface RedisDao {
	/**
	 * show 获得缓存中的value
	 * */
	String get(String key) throws Exception;
	/**
	 * show 往缓存中添加value
	 * */
	void set(String key,String value) throws Exception;
	/**
	 * show 获取hash
	 * */
	String hget(String hkey,String key) throws Exception;
	/**
	 * show 插入一个hash
	 * */
	void hset(String hkey,String key,String value)throws Exception;
	/**
	 * show 插入一个列表
	 * */
	void lpush(String messageKey,String message)throws Exception;
	/**
	 * 取出一个列表,循环取出,用rpop
	 * */
	String rpop(String messageKey)throws Exception;
	/**
	 * 把列表中的元素取出,返回list集合,里面是列表的key和弹出的消息
	 * */
	List<String> brpop(String messageKey)throws Exception;
	/**
	 * show 发布/订阅 的发布者
	 * */
	void publish(String channel,String message)throws Exception;
	/**
	 * show 用subscribe订阅的订阅者
	 * */
	void subscribe(String channel)throws Exception;
}

RedisDaoImpl实现类

@Repository("redisDao")
public class RedisDaoImpl implements RedisDao{
	@Autowired
	
	private  JedisCluster jedisCluster;
	/**
	 * 处理订阅/发布的订阅者根据频道接收的信息
	 * */
	private MyJedisPubSub myJedisPubSub = new MyJedisPubSub();

	@Override
	public String get(String key) throws Exception {
		
		return jedisCluster.get(key);
	}

	@Override
	public void set(String key,String value) throws Exception {
		//获得6小时到9小时的随机时间
		int time=(int)(6+Math.random()*(4))*60*60;
		//添加键
		jedisCluster.set(key, value);
		 //给键添加生命周期
		jedisCluster.expire(key, time);
	}

	@Override
	public String hget(String hkey, String key) throws Exception {
		
		return jedisCluster.hget(hkey, key);
	}

	@Override
	public void hset(String hkey, String key,String value) throws Exception {
		int time=(int)(6+Math.random()*(4))*60*60;
		jedisCluster.hset(hkey, key,value);
		jedisCluster.expire(key, time);
	}

	@Override
	public void lpush(String messageKey, String message) {
		//这就不加生命周期了
		jedisCluster.lpush(messageKey, message);
		
	}

	@Override
	public String rpop(String messageKey) throws Exception {
		
		return jedisCluster.rpop(messageKey);
	}
	
	@Override
	public List<String> brpop(String messageKey) throws Exception {
		List<String> list = new ArrayList<String>();
		System.out.println("准备接受列表的全部数据");
		list = jedisCluster.brpop(5, messageKey);
		System.out.println("接收完成,返回");
		return list;
	}
	
	@Override
	public void publish(String channel, String message) throws Exception {
		jedisCluster.publish(channel, message);
		
	}

	@Override
	public void subscribe(String channel) throws Exception {
		jedisCluster.subscribe(myJedisPubSub, channel);
		
		System.out.println("取消订阅后返回主线程");
	}

	
}
/**
 * 继承JedisPubSub,重写接收消息的方法
 */
class MyJedisPubSub extends JedisPubSub {
	/**
	 * 结束程序的消息
	 * */
   private static final String EXIT_COMMAND = "exit";
    /** JedisPubSub类是一个没有抽象方法的抽象类,里面方法都是一些空实现
     * 所以可以选择需要的方法覆盖,这儿使用的是SUBSCRIBE指令,所以覆盖了onMessage
     * 如果使用PSUBSCRIBE指令,则覆盖onPMessage方法
     * 当然也可以选择BinaryJedisPubSub,同样是抽象类,但方法参数为byte[]
     **/
	 @Override
    public void onMessage(String channel, String message) {
        System.out.println("-接收到消息:channel=" + channel + ",message=" + message);
        //接收到exit消息后退出返回主线程
        if (EXIT_COMMAND.equals(message)) {
            unsubscribe(channel);
        }
    }
	 @Override
	public void unsubscribe(String... channels) {
		
		super.unsubscribe(channels);
	}
}

上面下半部分是关于消息队列订阅发布模式的(测试过了,一样可以执行)
关于发布/订阅模式可以参考redis实现消息队列(发布/订阅模式)
service接口

public interface UserService {
	/**
	 * show 获取所有的User
	 * */
	List<User> getUser()throws Exception;
	/**
	 * show 插入新的User
	 * */
	void insertUser(User user)throws Exception;
	
	
	/**
	 * 通过id查询用户
	 * 
	 * @param id
	 * @return
	 * @throws Exception
	 */
	 User findUserById(int id) throws Exception;
	 /**
	  *   show 列表生产者持续生产信息
	  * @param message 往缓存中添加的信息
	  * */
	 void putMessage(int message)throws Exception;
	 /**
	  * show 列表消费者准备消费,取出列表里的元素,不放回,用rpop
	  * */
	 String getMessage() throws Exception;
	 /**
	  * show 取出列表的元素(弹出一个),返回list集合(里面有key和value),用brpop
	  * */
	 List<String> getMessageList()throws Exception;
	 
	 
	 /**
	  * show 实现发布/订阅的发布者
	  * */
	 void publish(int i)throws Exception;
	 /**
	  * show 用subscribe订阅的订阅者
	  * */
	 void subscribe()throws Exception;
}

serviceImpl实现类

@Transactional(rollbackFor=Exception.class)
@Service("userService")
public class UserServiceImpl implements UserService {

	@Autowired
	private UserMapper userMapper=null; //这是往数据库也就是MySQL中查询的,如果不
	@Autowired
	private RedisDao redisDao =null;
	@Override
	public List<User> getUser() throws Exception {
		
		return userMapper.getUser();
	}

	@Override
	public void insertUser(User user) throws Exception {
		userMapper.insertUser(user);
		String userJson = redisDao.get("user_"+user.getId());
		if(StringUtils.isEmpty(userJson)) {
			System.out.println("插入缓存");
			//因为是缓存中存的是字符串,所以需要转成json字符串
			
			redisDao.set("user_"+user.getId(), JSON.toJSONString(user));	
		}
		
	}
	
	@Override
	public User findUserById(int id) throws Exception {
		String userjson = redisDao.get("user_"+id);
		User user =null;
		//判断缓存中存在对应的id的
		if(StringUtils.isEmpty(userjson)) {
			//不存在去数据库中取出,再放进缓存
			user = userMapper.findUserById(id);
			if(user != null) {
				redisDao.set("user_"+id, JSON.toJSONString(user));	
			}else {
				//数据库中也不存在就把这个id也存进缓存中标识,防止雪崩或者穿透
			}
		}else {
			//存在就直接把缓存里的json拿出来转换成对象
			System.out.println("从缓存拿是数据,不去数据库");
			user = JSON.parseObject(userjson,User.class);
		}
		return user;
	}

	@Override
	public void putMessage(int message) throws Exception {
			//把消息发布
			String messageKey = "message:queue";
			redisDao.lpush(messageKey, String.valueOf(message));
		
		
	}

	@Override
	public String getMessage() throws Exception {
		//把消息取出来
		String messageKey = "message:queue";
		return redisDao.rpop(messageKey);
	}
	@Override
	public List<String> getMessageList() throws Exception {
		String messageKey = "message:queue";
		return redisDao.brpop(messageKey);
	}
	@Override
	public void publish(int i) throws Exception {
		//频道号
		String channel = "channel:1";
		redisDao.publish(channel, String.valueOf(i));
		
	}

	@Override
	public void subscribe() throws Exception {
		String channel = "channel:1";
		redisDao.subscribe(channel);
	}

	
}

测试类

//根据id,存进一个对象,String类型,用fastjson把对象转换成String类型的json
 	@Test
 	public void testInsertUser() throws Exception{
 		ctx = new ClassPathXmlApplicationContext("spring-service.xml");
        userService = ctx.getBean(UserService.class);
 		User user = new User();
 		user.setId(11);
 		user.setName("第一个");
 		
 		userService.insertUser(user);
 	}
 	//通过id获得指定的String的对象(用fastjson转换成对象了)
 	@Test
 	public void testGetUserById() throws Exception{
 		ctx = new ClassPathXmlApplicationContext("spring-service.xml");
        userService = ctx.getBean(UserService.class);
 		System.out.println(userService.findUserById(11));
 		
 	}

结果
在这里插入图片描述
存进集群里了
在这里插入图片描述
在这里插入图片描述
也从redis cluster中把数据取出来了,这种方式完成

注解的方式(redisTemplate )

注解方式实现SSM和单机redis请参考Spring+Mybatis+redis整合(用注解的方式)
这个请参考java项目中配置redis-cluster集群的两种方式

上面用两种方式的第二种方式用redisTemplate的我还以为是用注解的呢,其实不是,现在我先学到这,redis方面的虽然还有很多方面没有解决,但是总算大体弄完了,下面继续学习MongonDB了

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值