redis作为第三方缓存插件,redisson作为分布式锁处理高并发场景数据不一致的问题
完整测试代码地址:https://gitee.com/rjenjoylife/leduo/tree/master/parent/redisson_test
引入第三方jar包
<!-- springboot2.X集成redis需要commons-pool2 --> <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> <!-- 分布式锁 --> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.12.2</version> </dependency> <!-- 序列化 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> </dependency> <!-- 使用注解方式获取yml属性文件内容是,需要引入该包,否则会报下述错误: --> <!-- Spring Boot configuration annotation processor not found in classpath --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
创建redis的配置类,因为springboot在集成redis的时候提供的默认模板是<Object, Object>类型的,为了使用方便重写序列化方式
@Configuration @EnableCaching public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<String, Object>(); template.setConnectionFactory(factory); //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式) Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有,包括private和public om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会抛出异常 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; } }
redisson配置
# 集群环境配置 redis: open: true # 是否开启redis缓存 true开启 false关闭 #password: # 密码(默认为空) timeout: 6000 # 连接超时时长(毫秒) cluster: nodes: 192.168.1.101:7001,192.168.1.101:7002,192.168.1.101:7003,192.168.1.101:7004,192.168.1.101:7005,192.168.1.101:7006 max-redirects: 3 # 单机环境配置 redis: open: true # 是否开启redis缓存 true开启 false关闭 database: 0 host: 192.168.1.101 port: 7000 password: '123456' # 密码(默认为空) timeout: 6000 # 连接超时时长(毫秒) pool: max-active: 1000 # 连接池最大连接数(使用负值表示没有限制) max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制) max-idle: 10 # 连接池中的最大空闲连接 min-idle: 5 # 连接池中的最小空闲连接
@Configuration public class RedissonConfig { @Resource private RedisConfigProperties redisConfigProperties; @Bean public RedissonClient getRedisson(){ Config config = new Config(); if(!StringUtils.isEmpty(redisConfigProperties.getCluster())){ // 集群版 redis List<String> clusterNodes = new ArrayList<>(); for (int i = 0; i < redisConfigProperties.getCluster().getNodes().size(); i++) { clusterNodes.add("redis://" + redisConfigProperties.getCluster().getNodes().get(i)); } ClusterServersConfig clusterServersConfig = config.useClusterServers(); //设置集群状态扫描时间 clusterServersConfig.setScanInterval(2000); clusterServersConfig.addNodeAddress(clusterNodes.toArray(new String[clusterNodes.size()])); if(!StringUtils.isEmpty(redisConfigProperties.getPassword())){ clusterServersConfig.setPassword(redisConfigProperties.getPassword()); } }else{ // 单机版 redis SingleServerConfig singleServerConfig = config.useSingleServer(); singleServerConfig.setAddress("redis://" + redisConfigProperties.getHost() + ":" + redisConfigProperties.getPort()); if(!StringUtils.isEmpty(redisConfigProperties.getPassword())){ singleServerConfig.setPassword(redisConfigProperties.getPassword()); } } return Redisson.create(config); } }
@Component @ConfigurationProperties(prefix = "spring.redis") public class RedisConfigProperties { private String password; private cluster cluster; private String host; private String port; public static class cluster { private List<String> nodes; public List<String> getNodes() { return nodes; } public void setNodes(List<String> nodes) { this.nodes = nodes; } } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public RedisConfigProperties.cluster getCluster() { return cluster; } public void setCluster(RedisConfigProperties.cluster cluster) { this.cluster = cluster; } public String getHost() { return host; } public void setHost(String host) { this.host = host; } public String getPort() { return port; } public void setPort(String port) { this.port = port; } }