lettuce+pool+redisTemplate实现redis单机和集群的整合
lettuce+pool+redisTemplate实现redis单机和集群的整合
Springboot 整合redis是非常方便的,大致包含如下四部分
- pom start相关jar的引入
- properties/yaml 基础配置信息
- config bean的init
- bean的注入及使用
如果遇到网上的自动装配的实例直接跳过吧,哪怕再小的公司,密码也会加密处理,不可能自动装配。
1、pom
引入Springboot的redis相关组件
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency>
2、properties基础配置
这里主要配置数据源,其他配置项没有,暂时简化了配置,一切使用默认
为了适配真实业务,这里采用的是双数据源配置,亦真亦假,一单节点一集群。
redis.biz.alone.host=39.105.198.245:6379 redis.biz.alone.auth=hcgk&2022 redis.biz.cluster.host=10.22.251.21:6379,10.22.251.28:6379,10.22.251.23:6379 redis.biz.cluster.auth=7ujm*IK< lettuce.pool.max-total=12 # 最大活跃链接数 默认8(使用负值表示没有限制) lettuce.pool.max-active=12 # 最大空闲连接数 默认8 lettuce.pool.max-idle=12 # 最小空闲连接数 默认0 lettuce.pool.min-idle=0 # 连接池最大阻塞等待时间(使用负值表示没有限制) lettuce.pool.max-wait=-1
3、config
支持单击和集群
package com.wht.test.config; import io.lettuce.core.ReadFrom; import io.lettuce.core.TimeoutOptions; import io.lettuce.core.cluster.ClusterClientOptions; import io.lettuce.core.cluster.ClusterTopologyRefreshOptions; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Scope; 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.LettuceClientConfiguration; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration; import org.springframework.data.redis.core.StringRedisTemplate; import java.time.Duration; import java.util.HashSet; import java.util.Set; /** * 支持单机、集群和多实例 * * @Author 红尘过客 * @DateTime 2023-06-19 22:00:12 */ @Configuration public class LettuceRedisConfig { @Value("${redis.biz.alone.host}") private String bizAloneHost; @Value("${redis.biz.alone.auth}") private String bizAloneAuth; @Value("${redis.biz.cluster.host}") private String bizClusterHost; @Value("${redis.biz.cluster.auth}") private String bizClusterAuth; @Bean @ConfigurationProperties(prefix = "spring.redis.lettuce.pool") @Scope(value = "prototype") public GenericObjectPoolConfig redisPool() { return new GenericObjectPoolConfig(); } @Primary @Bean("bizAlone") public StringRedisTemplate bizAlone(GenericObjectPoolConfig redisPool) { return getStringRedisTemplate(bizAloneHost, bizAloneAuth, redisPool); } // @Primary // @Bean("bizCluster") // public StringRedisTemplate bizCluster(GenericObjectPoolConfig redisPool) { // return getStringRedisTemplate(bizClusterHost, bizClusterAuth,redisPool); // } /** * 封装单例配置 * * @param host * @param password * @return */ private RedisStandaloneConfiguration getRedisStandaloneConfiguration(String host, String password) { RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(); String[] redisNode = host.split(":"); if (redisNode.length == 2) { redisStandaloneConfiguration.setHostName(redisNode[0]); redisStandaloneConfiguration.setPort(Integer.parseInt(redisNode[1])); } if (password != null || password.trim().length() > 0) { redisStandaloneConfiguration.setPassword(password); } return redisStandaloneConfiguration; } /** * 把集群连接串拆分为redisNodes * * @param host * @return */ private Set<RedisNode> getClusterNodes(String host) { String[] nodesArray = host.split(","); Set<RedisNode> clusterNodes = new HashSet<>(); for (String node : nodesArray) { String[] redisNode = node.split(":"); clusterNodes.add(new RedisNode(redisNode[0], Integer.parseInt(redisNode[1]))); } return clusterNodes; } /** * 封装集群配置 * * @param host * @param password * @return */ private RedisClusterConfiguration getRedisClusterConfiguration(String host, String password) { RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration(); redisClusterConfiguration.setClusterNodes(getClusterNodes(host)); if (password != null || password.trim().length() > 0) { redisClusterConfiguration.setPassword(password); } return redisClusterConfiguration; } /** * 创建alone bean * 这里用LettucePoolingClientConfiguration 预留了连接池 * * @param host * @param password * @return */ private StringRedisTemplate getStringRedisTemplate(String host, String password, GenericObjectPoolConfig redisPool) { LettucePoolingClientConfiguration.LettucePoolingClientConfigurationBuilder builder = LettucePoolingClientConfiguration.builder(); builder.poolConfig(redisPool); LettuceConnectionFactory connectionFactory = null; // 集群要做拓扑刷新,应对准备切换,摸个节点挂掉等问题 if (host.contains(",")) { ClusterTopologyRefreshOptions topologyRefreshOptions = ClusterTopologyRefreshOptions.builder() .enablePeriodicRefresh(Duration.ofSeconds(10)) .enableAllAdaptiveRefreshTriggers() .build(); ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder() .timeoutOptions(TimeoutOptions.enabled(Duration.ofSeconds(60))) .topologyRefreshOptions(topologyRefreshOptions) .build(); LettuceClientConfiguration clientConfiguration = builder.commandTimeout(Duration.ofSeconds(60)) .readFrom(ReadFrom.REPLICA_PREFERRED) .clientOptions(clusterClientOptions) .build(); connectionFactory = new LettuceConnectionFactory(getRedisClusterConfiguration(host, password), clientConfiguration); } else { connectionFactory = new LettuceConnectionFactory(getRedisStandaloneConfiguration(host, password), builder.build()); } connectionFactory.afterPropertiesSet(); return getStringRedisTemplate(connectionFactory); } private StringRedisTemplate getStringRedisTemplate(LettuceConnectionFactory connectionFactory) { StringRedisTemplate stringRedisTemplate = new StringRedisTemplate(); stringRedisTemplate.setConnectionFactory(connectionFactory); return stringRedisTemplate; } }
4、使用
这里简单搞个schedule任务
package com.wht.test.schedule; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.time.Duration; /** * desc * * @Author 红尘过客 * @DateTime 2023-06-15 10:15:35 */ @Component public class RedisTestJob { @Resource(name = "bizAlone") private StringRedisTemplate stringRedisTemplate; @Scheduled(cron = "* * * * * * ") public void test() { for (int i = 0; i < 100; i++) { String key = "test_" + i; stringRedisTemplate.opsForValue().set(key, "test_value_" + i, Duration.ofHours(1)); String name = (String) stringRedisTemplate.opsForValue().get(key); System.out.println("value = " + name); } } }
可以正常写入数据到redis了
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战