zoukankan      html  css  js  c++  java
  • java中使用redis

    java中使用redis

    java-redis客户端

    http://www.redis.cn/clients.html#java

    常用的redis 客户端操作工具:

    Jedis   api 在线网址:http://tool.oschina.net/uploads/apidocs/redis/clients/jedis/Jedis.html

    redisson  官网地址:https://redisson.org/

    redisson  git项目地址:https://github.com/redisson/redisson

    lettuce  官网地址:https://lettuce.io/

    lettuce  git项目地址:https://github.com/lettuce-io/lettuce-core

    redis命令行文档: 

    http://redisdoc.com/

    概念:

      Jedis:是Redis的Java实现客户端,提供了比较全面的Redis命令的支持,

      Redisson:实现了分布式和可扩展的Java数据结构。

      Lettuce:高级Redis客户端,用于线程安全同步,异步和响应使用,支持集群,Sentinel,管道和编码器。

    优缺点:

     Jedis:比较全面的提供了Redis的操作特性,使用阻塞的I/O,且其方法调用都是同步的。程序流需要等到sockets处理完I/O才能执行,不支持异步。Jedis客户端实例不是线程安全的,所以需要通过连接池来使用Jedis。

     Redisson:促使使用者对Redis的关注分离,提供很多分布式相关操作服务,例如,分布式锁,分布式集合,可通过Redis支持延迟队列。基于Netty框架的事件驱动的通信层,其方法调用是异步的。Redisson的API是线程安全的,所以可以操作单个Redisson连接来完成各种操作。Redisson 对字符串的操作支持比较差。

     Lettuce:要在一些分布式缓存框架上使用比较多。基于Netty框架的事件驱动的通信层,其方法调用是异步的。Lettuce的API是线程安全的,所以可以操作单个Lettuce连接来完成各种操作

    4. 使用建议

    结论:lettuce + Redisson

    Jedis 和 lettuce 是比较纯粹的 Redis 客户端,几乎没提供什么高级功能。Jedis 的性能比较差,所以如果你不需要使用 Redis 的高级功能的话,优先推荐使用 lettuce。

    Redisson 的优势是提供了很多开箱即用的 Redis 高级功能,如果你的应用中需要使用到 Redis 的高级功能,建议使用 Redisson。具体 Redisson 的高级功能可以参考:https://redisson.org/

    下面我们使用SpringData提供的Spring-data-redis与SpringBoot项目实现完美的整合

    SpringData官网:https://docs.spring.io/spring-data/redis/docs/2.4.3/reference/html/#reference

    整合:

    1 maven依赖:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
        <!--<version>2.1.4.RELEASE</version>-->
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-pool2</artifactId>
    </dependency>
    <!-- fastjson -->
    <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.68</version>
    </dependency>

    2、yml:

    spring:
      redis:
        # Redis数据库索引(默认为0)
        database: 0
        # Redis服务器地址
        host: 192.168.252.128
        # Redis服务器连接端口
        port: 6379
        # Redis服务器连接密码(默认为空)
        password: 123456
        # 连接超时时间(毫秒)默认是2000ms
        timeout: 5000ms
      # 连接器客户端配置
        lettuce:
          pool:
            # 连接池最大连接数(使用负值表示没有限制)
            max-active: 200
            # 连接池中的最大空闲连接
            max-idle: 20
            # 连接池中的最小空闲连接
            min-idle: 0
            # 连接池最大阻塞等待时间(使用负值表示没有限制)
            max-wait: -1ms
      # 集群模式的redis配置
    #    cluster:
    #      max-redirects: 3
    #      nodes: 192.168.0.201:7001,192.168.0.201:7002,192.168.0.201:7003,192.168.0.201:7004,192.168.0.201:7005,192.168.0.201:7006
      # 主从模式的redis配置
    #    sentinel:
    #      #哨兵监听的 master名称
    #      master: mymaster
    #      # 哨兵地址列表,多个以,分割
    #      nodes: 192.168.0.201:7001,192.168.0.201:7002
    #      password: 123456

    配置RestTemplate 的序列化方式,默认使用jdk提供的序列化方式,不可读,配置自己的序列化方式 :

    @Configuration
    @EnableCaching //支持缓存注解
    public class MyRedisConfig extends CachingConfigurerSupport {
    
        @Bean
        public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory redisConnectionFactory) {
            RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
            redisTemplate.setKeySerializer(new StringRedisSerializer());                    // key序列化
            redisTemplate.setValueSerializer(new FastJsonRedisSerializer<>(Object.class));     // value序列化
            redisTemplate.setHashKeySerializer(new StringRedisSerializer());                // Hash key序列化
            redisTemplate.setHashValueSerializer(new StringRedisSerializer()); // Hash value序列化
            redisTemplate.setConnectionFactory(redisConnectionFactory);
            return redisTemplate;
        }
        
    }

     RedisTemplate操作Redis  Api 请参考: https://www.cnblogs.com/dw3306/p/12840012.html 

     springboot + spring cache + redis 实现缓存

            spring cache 是spring3版本之后引入的一项技术,可以简化对于缓存层的操作,spring cache与springcloud stream类似,都是基于抽象层,可以任意切换其实现。其核心是CacheManagerCache这两个接口,所有由spring整合的cache都要实现这两个接口、Redis的实现类则是 RedisCache 和 RedisManager。

     1. 首先认识几个用到的名称及注解

    @EnableCaching 开启基于注解的缓存,写在启动类上,这个注解会被spring发现,并且会创建一个切面(aspect) 并触发Spring缓存注解的切点(pointcut) 。 根据所使用的注解以及缓存的状态, 这个切面会从缓存中获取数据, 将数据添加到缓存之中或者从缓存中移除某个值。
    @Cacheable 标注在方法上,如果该方法结果存在缓存则使用缓存,否则执行方法并将结果缓存
    @CacheEvict 清除缓存
    @CachePut 不管有没有缓存都要执行方法,且把结果缓存,如果存在缓存就更新
    Cache 缓存接口,定义缓存操作
    CacheManager 缓存管理器,管理各种缓存组件
    keyGenerator 缓存数据时key的生成策略
    serialize 缓存数据时,value的序列化策略

    当然,缓存管理器除了RedisCacheManager还有一些其他的。例如

    1. SimpleCacheManager
    2. NoOpCacheManager
    3. ConcurrentMapCacheManager
    4. CompositeCacheManager
    5. EhCacheCacheManager

    默认缓存管理器:ConcurrentMapCacheManager,这个简单的缓存管理器使用java.util.concurrent.ConcurrentHashMap作为其缓存存储

    @Cacheable属性讲解

    @Cacheable 是一个既可以应用于方法级别,也可用于类级别的注解。自spring3.1开始就通过它实现了缓存管理。

    @Cacheable能干什么?
    为了通俗易懂的理解,举个栗子:一个方法,getBooksByUsernameAndLanguage(String username, int language),显然,是一个获取数据库里所有我的英文书对象的方法,返回应该是一个列表。如果这个函数的返回值很大,而且会在页面上被经常调用,那么每一次调用都要重新连接数据库并返回一个数据量庞大的list,可能页面响应和资源占用会比较大。而我们希望的是,第一次调用这个方法时,返回的数据能被放到服务器端的缓存里,以便于后面要调用这个方法时,能直接从缓存里取到,这样就不用再查数据库占用资源了。而@Cacheable的作用就是这个。
    @Cacheable怎么用?
    @Cacheable(value = "CACHE_BOOK",key = "#username", condition = "#language = 1")
    public List<Book> getBooksByUsernameAndLanguage(String username, int language) {
         // balabalabala...里面的代码不重要
         return bookList;
    }
    • value : 必须要的。就是个自己取的名字,通过它指明了第一次调用这个方法时返回的bookList将被存在内存的哪里。
    • key : 可选。要使用SpEL表达式,这里与参数username对应,当传入的username值变了的话就不去取缓存里的数据了,而是执行getBooksByUsernameAndLanguage方法。(这是必须的,因为username变了,返回值也就变了,缓存里的数据不符合了,因此这个选项很重要)。spring默认用方法的签名来当做key。
    • condition:方法返回的结果bookList,要不要缓存起来?condition就添加了一个限定条件。这个例子中,只有传入的语言代码是1,返回的bookList才会被缓存起来,如果给language传了别的值,那么bookList是不会缓存起来的。

     @Cacheable注解中参数详情见下表:

    参数名作用
    cacheNames  被缓存的时候的命名空间
    key 这里的key的优先级是最高的,可以覆盖掉全局配置的key,如果不配置的话使用的就是全局的key
    keyGenerator  指定的缓存的key的生成器,默认没有
    cacheManager  指定要使用哪个缓存管理器。默认是底层自动配置的管理器
    condition 满足什么条件会进行缓存,里面可以写简单的表达式进行逻辑判断
    unless 满足什么条件不进行缓存,里面可以写简单的表达式进行逻辑判断
    sync 加入缓存的这个操作是否是同步的
    value
    指定将方法的返回结果放在哪个缓存中,可以指定多个,用大括号保存

    @CacheEvict简单属性讲解
    @CacheEvict 的参数信息见下表:
    参数名描述
    allEntries 是否删除该命名空间下面的全部缓存,默认是false
    beforeInvocation 在执行删除方法前就执行清空缓存操作,默认是false,如果删除方法执行报错该注解则不执行
    @CacheConfig简化注解配置

    标注在类上,类中方法就不需要再指定该注解说配置好的属性

    在controller或者service的类上面添加 @CacheConfig ,注解里面的参数详情见下表:

    参数名参数值作用
    cacheNames 可以随意填写,一般是一个模块或者一个很重要的功能名称 无具体作用,只是用来区分缓存,方便管理
    keyGenerator 就是自己配置的KeyGenerator的名称 全局key都会以他的策略去生成
    cacheManager 自己配置的CacheManager 用来操作Cache对象的,很多对于缓存的配置也由他去管理

    在标有@CacheConfig的类里面编写一个查询单个对象的方法并添加 @Cacheable注解

     eg: 

    @Cacheable(key = "#id", unless = "#result == null") 
    @PatchMapping("/course/{id}")
    public Course courseInfo(@PathVariable Integer id) {
        log.info("进来了 .. ");
        return courseService.getCourseInfo(id);
    }

     #result是代表函数的返回值

    cache 配置:

    在上面的  MyRedisConfig 中添加如下配置:

      /**
         * key的生成策略的配置: 类名+方法名+参数列表的类型+参数值 再做 哈希散列 作为key
         *
         * @return
         */
        @Bean
        @Override
        public KeyGenerator keyGenerator() {
            log.info("RedisCacheConfig.keyGenerator()");
            return new KeyGenerator() {
                @Override
                public Object generate(Object o, Method method, Object... objects) {
                    StringBuilder sb = new StringBuilder();
                    sb.append(o.getClass().getSimpleName())
                            .append(":")
                            .append(method.getName())
                            .append(":");
                    for (Object obj : objects) {
                        if (null != obj) {// 替换字符串
                            String objKey = JSON.toJSONString(obj);
                            objKey = objKey.replace(":", "=");
                            sb.append(objKey);
                        }
                    }
                    return sb.toString();
                }
            };
        }
    
    
        //缓存生存时间
        private Duration timeToLive = Duration.ofHours(1);
    
        @Bean
        public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
            //redis缓存配置
            RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                    //缓存生存时间
                    .entryTtl(this.timeToLive)
                    // 配置序列化(解决乱码的问题)
                    .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))
                    .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new FastJsonRedisSerializer<>(Object.class)))
                    // 不缓存空值
                    .disableCachingNullValues();
            //根据redis缓存配置和reid连接工厂生成redis缓存管理器
            RedisCacheManager redisCacheManager = RedisCacheManager.builder(connectionFactory)
                    .cacheDefaults(config)
                    .build();
            log.debug("自定义RedisCacheManager加载完成");
            return redisCacheManager;
        }
    
        private RedisSerializer<String> keySerializer() {
            return new StringRedisSerializer();
        }

    启动类上添加: @EnableCaching //支持缓存注解

     

     

  • 相关阅读:
    Yarn和Mesos:资源管理调度平台
    链接、装载、库
    PostgreSQL查询优化简介
    STL内存管理
    jemalloc总结
    ptmalloc总结
    数据库查询优化
    Linux交换空间和内存不足
    Linux内存管理
    HBase:分布式列式NoSQL数据库
  • 原文地址:https://www.cnblogs.com/dw3306/p/9520741.html
Copyright © 2011-2022 走看看