zoukankan      html  css  js  c++  java
  • SpringBoot使用Redis

    1.添加Redis依赖

    <!-- spring boot redis 缓存引入 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    

    2.添加配置文件

    # Redis数据库索引(默认为0)
    spring.redis.database=0
    # Redis服务器地址
    spring.redis.host=localhost
    # Redis服务器连接端口
    spring.redis.port=6379
    # Redis服务器连接密码(默认为空)
    spring.redis.password=
    # 连接池最大连接数(使用负值表示没有限制)
    spring.redis.pool.max-active=8
    # 连接池最大阻塞等待时间(使用负值表示没有限制)
    spring.redis.pool.max-wait=-1
    # 连接池中的最大空闲连接
    spring.redis.pool.max-idle=8
    # 连接池中的最小空闲连接
    spring.redis.pool.min-idle=0
    # 连接超时时间(毫秒)
    spring.redis.timeout=0
    

    3.使用

    @Autowired
    private StringRedisTemplate<Object,Object> stringRedisTemplate;
    //StringRedisTemplate的构造器中,设置的序列化器是字符串,所以它只能存取字符串
    stringRedisTemplate.opsForValue().set("aaa", "111");
    

    4.存储对象

    将POJO类实现Serializable接口即可

    //redisTemplate 序列化使用的jdkSerializeable, 存储二进制字节码(可以自定义序列化)
    //使用Jackson2JsonRedisSerialize 替换默认序列化
    redisTemplate.opsForValue().set("user", user);
    User user1 = (User) redisTemplate.opsForValue().get("user");
    

    5.配置连接池(application.yml配置文件)

    SpringBoot2.0默认采用Lettuce客户端来连接Redis服务端的。
    默认是不使用连接池的,配置文件中添加lettuce.pool相关配置,则会使用到lettuce连接池,并将相关配置设置为连接池相关参数。

    Lettuce 和 Jedis 的都是连接Redis Server的客户端程序。Jedis在实现上是直连redis server,多线程环境下非线程安全,除非使用连接池,为每个Jedis实例增加物理连接。Lettuce基于Netty的连接实例(StatefulRedisConnection),可以在多个线程间并发访问,且线程安全,满足多线程环境下的并发访问

    SpringBoot会自动配置redis,注入相关bean

    spring:
      redis:
        host: localhost    #    reids的连接ip
        database: 0    # Redis默认情况下有16个分片,这里配置具体使用的分片,默认是0
        timeout: 10000ms    # 连接超时时间(毫秒)
        lettuce:    #  springboot2.0后默认使用lettuce连接redis,底层使用的是netty框架做支撑
          pool:    
            min-idle: 0    # 连接池中的最小空闲连接 默认 0
            max-wait: -1ms    # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
            max-active: 8    # 连接池最大连接数(使用负值表示没有限制) 默认 8
            max-idle: 8    # 连接池中的最大空闲连接 默认 8
    

    6.编写缓存配置类CacheConfig用于调优缓存默认配置

    默认提供的Redis集成使用起来会有几个问题:

    • 生成Key过于简单,容易出现冲突。
    • 无法设置过期时间,乃至无法个性化每个业务单独的过期时间。
    • 默认配置序列化采用JDK序列化,某些业务场景无法满足。
      考虑以上几个问题,我们通常在集成使用Redis时,会自定义一些配置,这里我们来看看如何做自定义配置。
    @Configuration
    @EnableCaching  //开启缓存支持
    public class RedisConfig extends CachingConfigurerSupport {
    
        /**
         * 重写key生成策略,缓存的key是包名+方法名+参数列表,这样就很难会冲突了
         */
        @Bean
        @Override
        public KeyGenerator keyGenerator() {
            return (target, method, objects) -> {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append("::" + method.getName() + ":");
                for (Object obj : objects) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            };
        }
    
        /**
         * 缓存配置管理器
         */
        @Bean
        public CacheManager cacheManager(LettuceConnectionFactory lettuceConnectionFactory) {
            //以锁写入的方式创建RedisCacheWriter对象
            RedisCacheWriter writer = RedisCacheWriter.lockingRedisCacheWriter(lettuceConnectionFactory);
            //创建默认缓存配置对象
            RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
            //设置默认过期时间是30秒
            config.entryTtl(Duration.ofSeconds(30));
            //自定义cacheConfig
            Map<String, RedisCacheConfiguration> initialCacheConfigurations = new HashMap<>();
            for (Map.Entry<String, Integer> entry : CacheExpiresMap.get().entrySet()) {
                String key = entry.getKey();
                Integer seconds = entry.getValue();
                LOGGER.info("key{},value{}", key, seconds);
                RedisCacheConfiguration initialCacheConfig = RedisCacheConfiguration.defaultCacheConfig();
                initialCacheConfigurations.put(key, initialCacheConfig.entryTtl(Duration.ofSeconds(seconds)));
            }
            //初始化RedisCacheManager
            RedisCacheManager cacheManager = new RedisCacheManager(writer, config,initialCacheConfigurations);
            return cacheManager;
        }
    
        /**
         * RedisTemplate配置
         */
        @Bean
        public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
            // 设置序列化
            Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer =
                    new Jackson2JsonRedisSerializer<Object>(Object.class);
            ObjectMapper om = new ObjectMapper();
            om.setVisibility(PropertyAccessor.ALL, Visibility.ANY);
            om.enableDefaultTyping(DefaultTyping.NON_FINAL);
            jackson2JsonRedisSerializer.setObjectMapper(om);
    
            // 配置redisTemplate
            RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
            redisTemplate.setConnectionFactory(lettuceConnectionFactory);
            RedisSerializer stringSerializer = new StringRedisSerializer();
    
            redisTemplate.setKeySerializer(stringSerializer);   // key序列化
            redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);  // value序列化
            redisTemplate.setHashKeySerializer(stringSerializer);   // Hash key序列化
            redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);  // Hash value序列化
            //redisTemplate.setEnableTransactionSupport(true);    //是否启用事务
            redisTemplate.afterPropertiesSet();
            return redisTemplate;
        }
    
        @Override
        @Bean
        public CacheErrorHandler errorHandler() {
            // 异常处理,当Redis发生异常时,打印日志,但是程序正常走
            LOGGER.info("初始化 -> [{}]", "Redis CacheErrorHandler");
            CacheErrorHandler cacheErrorHandler = new CacheErrorHandler() {
                @Override
                public void handleCacheGetError(RuntimeException e, Cache cache, Object key) {
                    LOGGER.error("Redis occur handleCacheGetError:key -> [{}]", key, e);
                }
    
                @Override
                public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) {
                    LOGGER.error("Redis occur handleCachePutError:key -> [{}];value -> [{}]", key, value, e);
                }
    
                @Override
                public void handleCacheEvictError(RuntimeException e, Cache cache, Object key)    {
                    LOGGER.error("Redis occur handleCacheEvictError:key -> [{}]", key, e);
                }
    
                @Override
                public void handleCacheClearError(RuntimeException e, Cache cache) {
                    LOGGER.error("Redis occur handleCacheClearError:", e);
                }
            };
            return cacheErrorHandler;
        }
    }
    
  • 相关阅读:
    TCP为什么是个可靠的协议
    socket网络编程快速上手(二)——细节问题(4)
    socket网络编程快速上手(二)——细节问题(3)
    socket网络编程快速上手(二)——细节问题(2)
    socket网络编程快速上手(二)——细节问题(1)
    socket网络编程快速上手(一)
    多线程编程中使用pthread_create内存泄露问题
    股市量化智能分析2035
    忘记mysql root密码的解决方法
    CentOS 下快速安装部署Nginx网站
  • 原文地址:https://www.cnblogs.com/loveer/p/11316564.html
Copyright © 2011-2022 走看看