SSM+redis Cluster Integration

Posted by Kwakhed on Mon, 07 Oct 2019 20:34:14 +0200

Combine redis cluster with java (see previous blog for redis cluster)

First: Non-use of frameworks
1. Introducing jar (a jedis jar is enough)

2. Create the node object, add the node object to the JedisCluster object, and then use it properly.

public static void main(String[] args) {
		// Create and populate node information 
		Set<HostAndPort> nodes = new HashSet<>(); 
		nodes.add(new HostAndPort("127.0.0.1", 7001)); 
		nodes.add(new HostAndPort("127.0.0.1", 7002)); 
		nodes.add(new HostAndPort("127.0.0.1", 7003)); 
		nodes.add(new HostAndPort("127.0.0.1", 7004)); 
		nodes.add(new HostAndPort("127.0.0.1", 7005)); 
		nodes.add(new HostAndPort("127.0.0.1", 7006)); 
		// Creating JedisCluster objects 
		JedisCluster jedisCluster = new JedisCluster(nodes); 
		// Using jedisCluster to operate redis 
		String key = "jedisCluster"; 
		String setResult = jedisCluster.set(key, "hello redis!");
		System.out.println(setResult); 
		String getResult = jedisCluster.get(key); System.out.println(getResult); 
		// Close jedisCluster (the program can not be closed until it has been executed, and the connection pool is encapsulated internally). jedisCluster.close(); 

	}

Second: redis cluster combined with SSM framework

1. New redis configuration properties file redis.properties

redis.pool.maxTotal=30(Maximum number of connections
redis.pool.maxIdle=10(Maximum free time)
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.host1=127.0.0.1(Host of Cluster ip)
redis.port1=7001(Host Port of Cluster)
redis.host2=127.0.0.1
redis.port2=7002
redis.host3=127.0.0.1
redis.port3=7003
redis.host4=127.0.0.1
redis.port4=7004
redis.host5=127.0.0.1
redis.port5=7005
redis.host6=127.0.0.1
redis.port6=7006

2. Adding dependencies to POM files

<dependencies>
 	 <dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
      <version>2.9.0</version>
 	 </dependency>
 	 
 <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
   	<version>4.3.18.RELEASE</version>
</dependency>

<dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-redis</artifactId>
        <version>1.7.1.RELEASE</version>
</dependency>

No need to ask me why I want to add so many other things, this is a pit.
3. New spring-redis.xml configuration file
For the sake of convenience, I posted the code.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:task="http://www.springframework.org/schema/task" xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:cache="http://www.springframework.org/schema/cache"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
    http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
    http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
 
<!--  redis The connection pool refers to jedis Functions in packages  -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="${redis.maxActive:1024}" />
<property name="maxIdle" value="${redis.maxIdle:1024}" />
<property name="maxWaitMillis" value="${redis.maxWait:10000}" />
<property name="testOnBorrow" value="${redis.testOnBorrow:true}" />
<property name="testOnReturn" value="${redis.testOnReturn:true}" />
</bean>
 
<!-- Redis Cluster configuration     Here we use the spring-data-redis  Contents in packages -->


<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>classpath*:redis.properties</value>
			</list>
		</property>
		<property name="ignoreUnresolvablePlaceholders" value="true" /> 
	</bean>
<bean id="redisClusterConfig" class="org.springframework.data.redis.connection.RedisClusterConfiguration">
        <property name="maxRedirects" value="6"></property>
        <property name="clusterNodes">
            <set>
                <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="${redis.host1}"></constructor-arg>
                    <constructor-arg name="port" value="${redis.port1}"></constructor-arg>
                </bean>
 
                <bean class="org.springframework.data.redis.connection.RedisNode">
                     <constructor-arg name="host" value="${redis.host2}"></constructor-arg>
                     <constructor-arg name="port" value="${redis.port2}"></constructor-arg>
                </bean>
                <bean class="org.springframework.data.redis.connection.RedisNode">
                     <constructor-arg name="host" value="${redis.host3}"></constructor-arg>
                     <constructor-arg name="port" value="${redis.port3}"></constructor-arg>
                </bean>
                <bean class="org.springframework.data.redis.connection.RedisNode">
                     <constructor-arg name="host" value="${redis.host4}"></constructor-arg>
                     <constructor-arg name="port" value="${redis.port4}"></constructor-arg>
                </bean>
                 <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="${redis.host1=5}"></constructor-arg>
                    <constructor-arg name="port" value="${redis.port5}"></constructor-arg>
                </bean>
                 <bean class="org.springframework.data.redis.connection.RedisNode">
                     <constructor-arg name="host" value="${redis.host6}"></constructor-arg>
                     <constructor-arg name="port" value="${redis.port6}"></constructor-arg>
                </bean>
            </set>
        </property>
    </bean> 
    <!-- Redis Connection factory     -->
    <bean id="redis4CacheConnectionFactory"
        class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <constructor-arg name="clusterConfig" ref="redisClusterConfig" />
        <property name="timeout" value="${redis.timeout:10000}" />
        <property name="poolConfig" ref="jedisPoolConfig" />
    </bean>
    <!-- Storage serialization -->
    <bean name="stringRedisSerializer"
        class="org.springframework.data.redis.serializer.StringRedisSerializer" />
 
    <!-- colony Resis Using templates -->
    <bean id="clusterRedisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="redis4CacheConnectionFactory" />
        <property name="keySerializer" ref="stringRedisSerializer" />
        <property name="hashKeySerializer" ref="stringRedisSerializer" />
        <property name="valueSerializer" ref="stringRedisSerializer" />
        <property name="hashValueSerializer" ref="stringRedisSerializer" />
    </bean>
</beans>

Note: When there are multiple attribute files. properties in a project, use the following before loading each file

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>classpath*:So-and-so.properties</value>
			</list>
		</property>
		<property name="ignoreUnresolvablePlaceholders" value="true" /> 
	</bean>

The reason for this is that the class loading the properties file in spring is singleton, and when it is loaded, it is considered to be over and needs to be opened many times.
4. Write RedisClusterClient service class in service layer

package cn.zds.service.impl;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
@Service
public class RedisClusterClient {
           @Autowired
       private RedisTemplate<String,String> clusterRedisTemplate;
     
       //Add data
        public void put(Object key, Object value) {
            if(null == value) {
                return;
            }
     
            if(value instanceof String) {
                if(StringUtils.isEmpty(value.toString())) {
                    return;
                }
            }
     
            // TODO Auto-generated method stub
            final String keyf = key + "";
            final Object valuef = value;
            final long liveTime = 86400;
     
            clusterRedisTemplate.execute(new RedisCallback<Long>() {
                public Long doInRedis(RedisConnection connection)
                        throws DataAccessException {
                    byte[] keyb = keyf.getBytes();
                    byte[] valueb = toByteArray(valuef);
                    connection.set(keyb, valueb);
                    if (liveTime > 0) {
                        connection.expire(keyb, liveTime);
                    }
                    return 1L;
                }
            });
        }
     
         // get data
        public Object get(Object key) {
            final String keyf = (String) key;
            Object object;
            object = clusterRedisTemplate.execute(new RedisCallback<Object>() {
                public Object doInRedis(RedisConnection connection)
                        throws DataAccessException {
     
                    byte[] key = keyf.getBytes();
                    byte[] value = connection.get(key);
                    if (value == null) {
                        return null;
                    }
                    return toObject(value);
     
                }
            });
     
            return object;
        }
     
        /**
         * Description: < byte [] to Object >. < br >
         * <p>
         * <Instructions for Use >
         * </p>
         *
         * @param bytes
         * @return
         */
        private Object toObject(byte[] bytes) {
            Object obj = null;
            try {
                ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
                ObjectInputStream ois = new ObjectInputStream(bis);
                obj = ois.readObject();
                ois.close();
                bis.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            } catch (ClassNotFoundException ex) {
                ex.printStackTrace();
            }
            return obj;
        }
     
        private byte[] toByteArray(Object obj) {
            byte[] bytes = null;
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            try {
                ObjectOutputStream oos = new ObjectOutputStream(bos);
                oos.writeObject(obj);
                oos.flush();
                bytes = bos.toByteArray();
                oos.close();
                bos.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            return bytes;
        }
    
}

5. test
Redis general usage method:
Put the commonly used information (often read and content does not change much, here I use the data on the home page) into redis, and when requesting it, first go to redis to read, and then return. If you don't read it, read it in mysql. Synchronize the data to redis before returning the result to the client. When requesting to modify the information to mysql, MySQL modifies the information and synchronizes the information to redis.

package cn.zds.controller;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import cn.zds.pojo.Shop;
import cn.zds.service.impl.RedisClusterClient;
import cn.zds.service.impl.ShopServiceImpl;

@Controller
public class TestController {
	@Resource 
	private RedisClusterClient redisClusterClient;
	@Resource 
	private ShopServiceImpl shopServiceImpl;
	
	@RequestMapping("/getUserFromTable")
    @ResponseBody
    public List getUserFromTable(){
		Object object=redisClusterClient.get("FIRST_PAGE");//Read information directly from redis
		System.out.println(object);
		if(object!=null){//Read the message
			return (List) object;//Return
		}else {//No information read
			//Read from mysql database
			  List<Shop> firstShopList = shopServiceImpl.selFirstPageShop(1, 8);//Look up the first page. From the beginning, the number of pages is 8 shop s.
			  //Synchronize to redis
		        redisClusterClient.put("FIRST_PAGE", firstShopList);
		        return firstShopList;
		}
        
       
    }
}

6. Project catalog structure:

Topics: Redis Spring Java Jedis