• 如何使用StringRedisTemplate操作Redis详解


    Redis简介

    Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。支持事务5.0版本新增stream数据类型。

    Spring boot单数据源配置

    Springboot的redis单数据源配置特别简单
    (1)配置appliation.properties文件

    spring.redis.host=x.x.x.x
    spring.redis.port=6379
    #redis的数据库号
    spring.redis.database=4
    spring.redis.timeout = 30000ms
    spring.redis.jedis.pool.max-active=200
    spring.redis.jedis.pool.max-idle=0
    spring.redis.lettuce.pool.max-idle=5
    spring.redis.jedis.pool.max-wait=20000ms
    

    (2)StringRedisTemplate的基本操作

    StringRedisTemplate自动关闭redis连接
    //注入对象     
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    
    #获取ValueOperations操作String数据
    ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
    valueOperations.set("strRedis","StringRedisTemplate");
    valueOperations.get("strRedis"); 
    
    #设置过期时间     
    set("timeStep", new Date().getTime()+"", 2 ,TimeUnit.MINUTES);
    
    #获取SetOperations操作Set数据
     SetOperations<String, String> set = stringRedisTemplate.opsForSet();
     set.add("set1","22");
     set.add("set1","33");
     set.add("set1","44");
     Set<String> resultSet =stringRedisTemplate.opsForSet().members("set1");
     stringRedisTemplate.opsForSet().add("set2", "1","2","3");//向指定key中存放set集合
     Set<String> resultSet1 =stringRedisTemplate.opsForSet().members("set2");
     log.info("resultSet:"+resultSet);
     log.info("resultSet1:"+resultSet1);
    
    #获取ListOperations操作List数据,list可以用来实现队列。
     //将数据添加到key对应的现有数据的左边
     Long redisList = stringRedisTemplate.opsForList().leftPush("redisList", "3");
     stringRedisTemplate.opsForList().leftPush("redisList", "4");
     //将数据添加到key对应的现有数据的右边
     Long size = stringRedisTemplate.opsForList().size("redisList");
     //从左往右遍历
     String leftPop = stringRedisTemplate.opsForList().leftPop("redisList");
     //从右往左遍历
     String rightPop = stringRedisTemplate.opsForList().rightPop("redisList");
     //查询全部元素
     List<String> range = stringRedisTemplate.opsForList().range("redisList", 0, -1);
     //查询前三个元素
     List<String> range1 = stringRedisTemplate.opsForList().range("redisList", 0, 3);
     //从左往右删除list中元素A  (1:从左往右 -1:从右往左 0:删除全部)
     Long remove = stringRedisTemplate.opsForList().remove("key", 1, "A");
     log.info("redisList----"+redisList);
     log.info("size----"+size);
     log.info("leftPop----"+leftPop);
     log.info("rightPop----"+rightPop);
     log.info("range----"+range);
     log.info("range1----"+range1);
     log.info("remove----"+remove);  
    
    //判断key对应的map中是否存在hash
    Boolean aBoolean = stringRedisTemplate.opsForHash().hasKey("hash", "hash1");
    //往key对应的map中新增(key1,value1)
    stringRedisTemplate.opsForHash().put("hash", "hash1", "value1");
    //获取key对应的map中hash1的值
    Object o = stringRedisTemplate.opsForHash().get("hash", "hash1");
    //删除key对应的map中多个子hash(可变参数)
    Long delete = stringRedisTemplate.opsForHash().delete("hash", "key1", "key2", "key3");
    //获取hash对应的map
    Map<Object, Object> hash = stringRedisTemplate.opsForHash().entries("hash");
    //获取hash对应的map中全部子hash集合
    Set<Object> hash1 = stringRedisTemplate.opsForHash().keys("hash");
    //获取hash对应的map中全部value集合
    List<Object> hash2 = stringRedisTemplate.opsForHash().values("hash");
    
    #删除键
    Boolean key = stringRedisTemplate.delete("key");  
    #数字加x
    Long count = stringRedisTemplate.boundValueOps("count").increment(1);//val +1 
    #获取过期时间,不设的话为-1
    Long time = stringRedisTemplate.getExpire("count")   
      
       
    

    Spring boot多数据源配置,配置一个1号库,一个4号库

    添加依赖

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

    修改application.properties配置文件

    #1号库
    spring.redis.redis-onedb.database=0
    spring.redis.redis-onedb.hostName=192.168.90.42
    spring.redis.redis-onedb.port=9110
    spring.redis.redis-onedb.timeout=5000
    #4号库
    spring.redis.redis-fourdb.database=4
    spring.redis.redis-fourdb.hostName=192.168.90.42
    spring.redis.redis-fourdb.port=9110
    spring.redis.redis-fourdb.timeout=5000
    

    创建RedisConfig.java文件

    @Configuration
    public class RedisConfig {
    @Bean
    @ConfigurationProperties(prefix = "spring.redis.lettuce.pool")
    @Scope(value = "prototype")
    public GenericObjectPoolConfig redisPool(){
        return new GenericObjectPoolConfig();
    }
    
    @Bean
    @ConfigurationProperties(prefix = "spring.redis.redis-fourdb")
    public RedisStandaloneConfiguration redisConfigA(){
        return new RedisStandaloneConfiguration();
    }
    
    @Bean
    @ConfigurationProperties(prefix = "spring.redis.redis-onedb")
    public RedisStandaloneConfiguration redisConfigB(){
        return new RedisStandaloneConfiguration();
    }
    
    @Primary
    @Bean
    public LettuceConnectionFactory factoryA(GenericObjectPoolConfig config, RedisStandaloneConfiguration redisConfigA){
        LettuceClientConfiguration clientConfiguration = LettucePoolingClientConfiguration.builder()
                .poolConfig(config).commandTimeout(Duration.ofMillis(config.getMaxWaitMillis())).build();
        return new LettuceConnectionFactory(redisConfigA, clientConfiguration);
    }
    
    @Bean
    public LettuceConnectionFactory factoryB(GenericObjectPoolConfig config, RedisStandaloneConfiguration redisConfigB){
        LettuceClientConfiguration clientConfiguration = LettucePoolingClientConfiguration.builder()
                .poolConfig(config).commandTimeout(Duration.ofMillis(config.getMaxWaitMillis())).build();
        return new LettuceConnectionFactory(redisConfigB, clientConfiguration);
    }
    
    
    @Bean(name = "fourRedis")
    public StringRedisTemplate redisBusTemplate(@Qualifier("factoryA") LettuceConnectionFactory factoryA){
        StringRedisTemplate template = getRedisTemplate();
        template.setConnectionFactory(factoryA);
        return template;
    }
    
    @Bean(name = "oneRedis")
    public StringRedisTemplate redisLoginTemplate(@Qualifier("factoryB")LettuceConnectionFactory factoryB){
        StringRedisTemplate template = getRedisTemplate();
        template.setConnectionFactory(factoryB);
        return template;
    }
    
    private StringRedisTemplate getRedisTemplate(){
        StringRedisTemplate template = new StringRedisTemplate();
        template.setValueSerializer(new GenericFastJsonRedisSerializer());
        template.setValueSerializer(new StringRedisSerializer());
        return template;
    }
    }
    

    在需要使用的类,注入就可以使用

    @Resource(name = "oneRedis")
    private StringRedisTemplate oneRedis;
    
    @Resource(name = "fourRedis")
    private StringRedisTemplate fourRedis;
    

    StringRedisTemplate实现事务

    stringRedisTemplate.setEnableTransactionSupport(true);
        try {
            stringRedisTemplate.multi();//开启事务
            stringRedisTemplate.opsForValue().increment("count", 1);
            stringRedisTemplate.opsForValue().increment("count1", 2);
            //提交
            stringRedisTemplate.exec();
        }catch (Exception e){
            log.error(e.getMessage(), e);
            //开启回滚
            stringRedisTemplate.discard();
        }
    

    注意:StringRedisTemplate开启事务之后,不释放连接。如果我们使用Spring事务管理不存在这个问题

    StringRedisTemplate实现乐观锁

    redisTemplate.watch("key"); // 1
    redisTemplate.multi();
    redisTemplate.boundValueOps("key").set(""+id);
    List<Object> list= redisTemplate.exec();
    System.out.println(list);
    if(list != null ){
        //操作成功
        System.out.println(id+"操作成功");
    }else{
        //操作失败
        System.out.println(id+"操作失败");
    }
    

    StringRedisTemplate实现pipe管道

    StringRedisTemplate实现分布式锁

    String lockKey = "key";
    String lockValue = lockKey+System.currentTimeMillis();
    // value需要记住用于解锁
    while (true){
    
       Boolean ifPresent = stringRedisTemplate.opsForValue().
                    setIfAbsent("redis-lock:" + lockKey, lockValue, 3, TimeUnit.SECONDS);
    
       if (ifPresent){
              log.info("get redis-lock success");
              break;
        }
     }
    //解锁
      String lockKey = "key";
     String lockValue = lockKey + System.currentTimeMillis();
     boolean result = false;
     // value需要记住用于解锁
     stringRedisTemplate.watch("redis-lock:" + lockKey);
     String value = stringRedisTemplate.opsForValue().get("redis-lock:" + lockKey);
     if (null == value){
         result = true;
     }else if (value.equals(lockValue)) {
         stringRedisTemplate.delete("redis-lock:" + lockKey);
         result = true;
     }
     stringRedisTemplate.unwatch();  
    

    Redis缓存击穿、穿透和雪崩

    缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进
    行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就
    像在一个屏障上凿开了一个洞
          
    缓存穿透,是指查询一个数据库一定不存在的数据。正常的使用缓存流程大致是,
    数据查询先进行缓存查询,如果key不存在或者key已经过期,再对数据库进行查
    询,并把查询到的对象,放进缓存。如果数据库查询对象为空,则不放进缓存。
    解决办法是即使查出的对象为空,也放入缓存时间设短一点。
    
    缓存雪崩,是指在某一个时间段,缓存集中过期失效。
    

    本文转自https://segmentfault.com/a/1190000019952021

  • 相关阅读:
    Java中net.sf.json包关于JSON与对象互转的坑
    Java IO(1)基础知识——字节与字符
    [Github]给已创建的GitHub项目添加LICENSE
    [MAC]激活Sublime Text
    [MAC]安装配置Charles
    [iOS]15个iOS视频播放控件
    [iOS]UIWindow详解
    [Swift]LeetCode1320. 二指输入的的最小距离 | Minimum Distance to Type a Word Using Two Fingers
    [Swift]LeetCode1319. 连通网络的操作次数 | Number of Operations to Make Network Connected
    [Swift]LeetCode1318. 或运算的最小翻转次数 | Minimum Flips to Make a OR b Equal to c
  • 原文地址:https://www.cnblogs.com/snake107/p/12143234.html
Copyright © 2020-2023  润新知