springboot2.x版本整合redis(单机/集群)(使用lettuce)
在springboot1.x
系列中,其中使用的是jedis
,但是到了springboot2.x
其中使用的是Lettuce
。 此处springboot2.x
,所以使用的是Lettuce
。
关于jedis
跟lettuce
的区别:
- 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:
maxWaitMillis: 5000
其中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; @Value("${spring.redis.cache.maxWaitMillis:}") private Long maxWaitMillis; @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); poolConfig.setMaxWaitMillis(maxWaitMillis == null ? 5000L : maxWaitMillis); 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);