Spring Boot(十三):整合Redis哨兵,集群模式实践

前面的两篇文章(Redis的持久化方案, 一文掌握Redis的三种集群方案)分别介绍了Redis的持久化与集群方案 —— 包括主从复制模式、哨兵模式、Cluster模式,其中主从复制模式由于不能自动做故障转移,当节点出现故障时需要人为干预,不满足生产环境的高可用需求,所以在生产环境一般使用哨兵模式或Cluster模式。那么在Spring Boot项目中,如何访问这两种模式的Redis集群,可能遇到哪些问题,是本文即将介绍的内容。

Spring Boot 2 整合Redis

spring boot中整合Redis非常简单,在pom.xml中添加依赖

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

spring boot 2的spring-boot-starter-data-redis中,默认使用的是lettuce作为redis客户端,它与jedis的主要区别如下:

Jedis是同步的,不支持异步,Jedis客户端实例不是线程安全的,需要每个线程一个Jedis实例,所以一般通过连接池来使用Jedis

Lettuce是基于Netty框架的事件驱动的Redis客户端,其方法调用是异步的,Lettuce的API也是线程安全的,所以多个线程可以操作单个Lettuce连接来完成各种操作,同时Lettuce也支持连接池

如果不使用默认的lettuce,使用jedis的话,可以排除lettuce的依赖,手动加入jedis依赖,配置如下

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <exclusions> <exclusion> <groupId>io.lettuce</groupId> <artifactId>lettuce-core</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency>

在配置文件application.yml中添加配置(针对单实例)

spring: redis: host: 192.168.40.201 port: 6379 password: passw0rd database: 0 # 数据库索引,默认0 timeout: 5000 # 连接超时,单位ms jedis: # 或lettuce, 连接池配置,springboot2.0中使用jedis或者lettuce配置连接池,默认为lettuce连接池 pool: max-active: 8 # 连接池最大连接数(使用负值表示没有限制) max-wait: -1 # 连接池分配连接最大阻塞等待时间(阻塞时间到,抛出异常。使用负值表示无限期阻塞) max-idle: 8 # 连接池中的最大空闲连接数 min-idle: 0 # 连接池中的最小空闲连接数

然后添加配置类。其中@EnableCaching注解是为了使@Cacheable、@CacheEvict、@CachePut、@Caching注解生效

@Configuration @EnableCaching public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(factory); // 使用Jackson2JsonRedisSerialize 替换默认的jdkSerializeable序列化 Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); // key采用String的序列化方式 template.setKeySerializer(stringRedisSerializer); // hash的key也采用String的序列化方式 template.setHashKeySerializer(stringRedisSerializer); // value序列化方式采用jackson template.setValueSerializer(jackson2JsonRedisSerializer); // hash的value序列化方式采用jackson template.setHashValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; } }

上述配置类注入了自定义的RedisTemplate<String, Object>, 替换RedisAutoConfiguration中自动配置的RedisTemplate<Object, Object>类(RedisAutoConfiguration另外还自动配置了StringRedisTemplate)。

此时,我们可以通过定义一个基于RedisTemplate的工具类,或通过在Service层添加@Cacheable、@CacheEvict、@CachePut、@Caching注解来使用缓存。比如定义一个RedisService类,封装常用的Redis操作方法,

@Component @Slf4j public class RedisService { @Autowired private RedisTemplate<String, Object> redisTemplate; /** * 指定缓存失效时间 * * @param key 键 * @param time 时间(秒) * @return */ public boolean expire(String key, long time) { try { if (time > 0) { redisTemplate.expire(key, time, TimeUnit.SECONDS); } return true; } catch (Exception e) { log.error("exception when expire key {}. ", key, e); return false; } } /** * 根据key获取过期时间 * * @param key 键 不能为null * @return 时间(秒) 返回0代表为永久有效 */ public long getExpire(String key) { return redisTemplate.getExpire(key, TimeUnit.SECONDS); } /** * 判断key是否存在 * * @param key 键 * @return true 存在 false不存在 */ public boolean hasKey(String key) { try { return redisTemplate.hasKey(key); } catch (Exception e) { log.error("exception when check key {}. ", key, e); return false; } } ... }

出于篇幅,完整代码请查阅本文示例源码: https://github.com/ronwxy/springboot-demos/tree/master/springboot-redis-sentinel

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwsjxg.html