1. 程式人生 > >springboot2.x版本整合redis(單機/叢集)(使用lettuce)

springboot2.x版本整合redis(單機/叢集)(使用lettuce)

springboot1.x系列中,其中使用的是jedis,但是到了springboot2.x其中使用的是Lettuce。 此處springboot2.x,所以使用的是Lettuce
關於jedislettuce的區別:

  • Lettuce 和 Jedis 的定位都是Redis的client,所以他們當然可以直接連線redis server。
  • Jedis在實現上是直接連線的redis server,如果在多執行緒環境下是非執行緒安全的,這個時候只有使用連線池,為每個Jedis例項增加物理連線
  • Lettuce的連線是基於Netty的,連線例項(StatefulRedisConnection)可以在多個執行緒間併發訪問,應為StatefulRedisConnection是執行緒安全的,所以一個連線例項(StatefulRedisConnection)就可以滿足多執行緒環境下的併發訪問,當然這個也是可伸縮的設計,一個連線例項不夠的情況也可以按需增加連線例項。

新建一個springboot工程,新增如下pom依賴。

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</
groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <
scope>test</scope> </dependency> <!-- redis依賴commons-pool 這個依賴一定要新增 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency>

然後在application.yml配置一下redis伺服器的地址

server:
  port: 1015
spring:
  redis:
    cache:
      nodes: -192.168.159.129:7001
             -192.168.159.129:7002
             -192.168.159.129:7003
             -192.168.159.129:7004
             -192.168.159.129:7005
             -192.168.159.129:7006
      host: localhost:6379
      password:
      maxIdle:
      minIdle:
      maxTotal:

其中nodes為叢集redis的引數 host為單機redis的引數

 

redis配置類:

package webapp.conf;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashSet;
import java.util.Set;

@Configuration
public class RedisConfiguration {
    @Value("${spring.redis.cache.nodes:}")
    private String nodes;
    @Value("${spring.redis.cache.host:}")
    private String host;
    @Value("${spring.redis.cache.password:}")
    private String password;
    @Value("${spring.redis.cache.maxIdle:}")
    private Integer maxIdle;
    @Value("${spring.redis.cache.minIdle:}")
    private Integer minIdle;
    @Value("${spring.redis.cache.maxTotal:}")
    private Integer maxTotal;

    @Bean
    LettuceConnectionFactory lettuceConnectionFactory() {
        // 連線池配置
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
        poolConfig.setMaxIdle(maxIdle == null ? 8 : maxIdle);
        poolConfig.setMinIdle(minIdle == null ? 1 : minIdle);
        poolConfig.setMaxTotal(maxTotal == null ? 8 : maxTotal);
        LettucePoolingClientConfiguration lettucePoolingClientConfiguration = LettucePoolingClientConfiguration.builder()
                .poolConfig(poolConfig)
                .build();
        // 單機redis
        RedisStandaloneConfiguration redisConfig = new RedisStandaloneConfiguration();
        redisConfig.setHostName(host==null||"".equals(host)?"localhost":host.split(":")[0]);
        redisConfig.setPort(Integer.valueOf(host==null||"".equals(host)?"6379":host.split(":")[1]));
        if (password != null && !"".equals(password)) {
            redisConfig.setPassword(password);
        }

        // 哨兵redis
        // RedisSentinelConfiguration redisConfig = new RedisSentinelConfiguration();

        // 叢集redis
        /*RedisClusterConfiguration redisConfig = new RedisClusterConfiguration();
        Set<RedisNode> nodeses = new HashSet<>();
        String[] hostses = nodes.split("-");
        for (String h : hostses) {
            h = h.replaceAll("\\s", "").replaceAll("\n", "");
            if (!"".equals(h)) {
                String host = h.split(":")[0];
                int port = Integer.valueOf(h.split(":")[1]);
                nodeses.add(new RedisNode(host, port));
            }
        }
        redisConfig.setClusterNodes(nodeses);
        redisConfig.setMaxRedirects(3);
        redisConfig.setPassword(password);*/

        return new LettuceConnectionFactory(redisConfig, lettucePoolingClientConfiguration);
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(lettuceConnectionFactory);
        //序列化類
        MyRedisSerializer myRedisSerializer = new MyRedisSerializer();
        //key序列化方式
        template.setKeySerializer(myRedisSerializer);
        //value序列化
        template.setValueSerializer(myRedisSerializer);
        //value hashmap序列化
        template.setHashValueSerializer(myRedisSerializer);
        return template;
    }

    static class MyRedisSerializer implements RedisSerializer<Object> {

        @Override
        public byte[] serialize(Object o) throws SerializationException {
            return serializeObj(o);
        }

        @Override
        public Object deserialize(byte[] bytes) throws SerializationException {
            return deserializeObj(bytes);
        }

        /**
         * 序列化
         * @param object
         * @return
         */
        private static byte[] serializeObj(Object object) {
            ObjectOutputStream oos = null;
            ByteArrayOutputStream baos = null;
            try {
                baos = new ByteArrayOutputStream();
                oos = new ObjectOutputStream(baos);
                oos.writeObject(object);
                byte[] bytes = baos.toByteArray();
                return bytes;
            } catch (Exception e) {
                throw new RuntimeException("序列化失敗!", e);
            }
        }

        /**
         * 反序列化
         * @param bytes
         * @return
         */
        private static Object deserializeObj(byte[] bytes) {
            if (bytes == null){
                return null;
            }
            ByteArrayInputStream bais = null;
            try {
                bais = new ByteArrayInputStream(bytes);
                ObjectInputStream ois = new ObjectInputStream(bais);
                return ois.readObject();
            } catch (Exception e) {
                throw new RuntimeException("反序列化失敗!", e);
            }
        }
    }
}

 

以上已經完成整合教程,測試案例:

注入:

@Autowired
private RedisTemplate<String, Object> redisTemplate;

新增:

redisTemplate.opsForValue().set(key, value);

新增,設定過期時間:

redisTemplate.opsForValue().set(key, obj, expireTime, TimeUnit.SECONDS);

獲取:

Object o = redisTemplate.opsForValue().get(key);

刪除:

redisTemplate.delete(key);