Jedis,lettuce,RedisTemplate,Redission区别

1.Jedis:

Redis官方推荐使用Jedis操作Redis,Jedis的方法和Redis的指令一一对应。

Jedis和lettuce都是可以操作redis的平台

使用时:

导包

  1.  
    <dependency>
  2.  
    <groupId>redis.clients</groupId>
  3.  
    <artifactId>jedis</artifactId>
  4.  
    </dependency>

创建工具类 

  1.  
    public class JedisUtil {
  2.  
     
  3.  
    private static final JedisPool jedisPool;
  4.  
     
  5.  
    static {
  6.  
    //设置基本属性
  7.  
    GenericObjectPoolConfig<Jedis> poolConfig = new JedisPoolConfig();
  8.  
    //最大连接数
  9.  
    poolConfig.setMaxTotal(50);
  10.  
    //最大空闲数
  11.  
    poolConfig.setMaxIdle(10);
  12.  
     
  13.  
    jedisPool = new JedisPool(poolConfig, "XXX", 6379, 2000, "XXX");
  14.  
    }
  15.  
     
  16.  
    public static Jedis getJedis(){
  17.  
    return jedisPool.getResource();
  18.  
    }
  19.  
     
  20.  
    }

 

测试使用:

  1.  
    /**
  2.  
    * 测试 使用封装的工具类来使用redis
  3.  
    */
  4.  
    @Test
  5.  
    void test03(){
  6.  
    Jedis jedis = JedisUtil.getJedis();
  7.  
    jedis.lpush("lol","abc");
  8.  
    jedis.lpush("lol","def");
  9.  
    jedis.lpush("lol","ghj");
  10.  
    //弹出
  11.  
    System.out.println(jedis.lrange("lol", 0, -1));
  12.  
    }

 因为Jedis采用的直连,多个线程操作是不安全的,如果想要避免,得使用jedis pool连接池 ,并且不支持异步

2.lettuce

Lettuce基于Netty的连接实例(StatefulRedisConnection),可以在多个线程间并发访问,且线程安全,满足多线程环境下的并发访问,同时它是可伸缩的设计,一个连接实例不够的情况也可以按需增加连接实例

依赖:

  1.  
     
  2.  
    <dependency>
  3.  
    <groupId>io.lettuce</groupId>
  4.  
    <artifactId>lettuce-core</artifactId>
  5.  
    </dependency>

具体没咋用过

3.RedisTemplate 

redistemplate是spring框架对jedis和lettuce的封装。让spring框架体系能够更加方便的接入redis的功能。

依赖:

  1.  
    <dependency>
  2.  
    <groupId>org.springframework.boot</groupId>
  3.  
    <artifactId>spring-boot-starter-data-redis</artifactId>
  4.  
    </dependency>

这个依赖包中就包括了jedis 和 lettuce的依赖

基础使用:

先配置自定义RedisTemplate 因为底层默认JDK二进制序列化 不能跨平台使用 

  1.  
    @Bean
  2.  
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
  3.  
    RedisTemplate<String, Object> template = new RedisTemplate();
  4.  
    template.setConnectionFactory(redisConnectionFactory);
  5.  
    template.setKeySerializer(RedisSerializer.string());
  6.  
    template.setValueSerializer(RedisSerializer.json());
  7.  
    template.setHashKeySerializer(RedisSerializer.string());
  8.  
    template.setHashValueSerializer(RedisSerializer.json());
  9.  
    return template;
  10.  
    }

String Hash List Set Zset 基础使用:

  1.  
    /**
  2.  
    * String -- API
  3.  
    */
  4.  
    @Test
  5.  
    void test07(){
  6.  
    //通用指令
  7.  
    //exists
  8.  
    System.out.println(redisTemplate.hasKey("a"));
  9.  
    System.out.println(redisTemplate.hasKey("b"));
  10.  
    //ttl
  11.  
    System.out.println(redisTemplate.getExpire("a", TimeUnit.SECONDS));
  12.  
    System.out.println(redisTemplate.getExpire("b", TimeUnit.SECONDS));
  13.  
    //expire
  14.  
    System.out.println(redisTemplate.expire("a", 100,TimeUnit.SECONDS));
  15.  
    System.out.println(redisTemplate.getExpire("a", TimeUnit.SECONDS));
  16.  
    redisTemplate.persist("a");
  17.  
    System.out.println(redisTemplate.getExpire("a", TimeUnit.SECONDS));
  18.  
    }
  19.  
     
  20.  
    /**
  21.  
    * String -- API2
  22.  
    */
  23.  
    @Test
  24.  
    void test08(){
  25.  
    //keys
  26.  
    ValueOperations valueOperations = redisTemplate.opsForValue();
  27.  
    valueOperations.set("abc","456");
  28.  
     
  29.  
    System.out.println(redisTemplate.keys("*"));
  30.  
    //dbsize
  31.  
    System.out.println(redisTemplate.countExistingKeys(redisTemplate.keys("*")));
  32.  
    redisTemplate.delete("aaa");
  33.  
    System.out.println(redisTemplate.keys("*"));
  34.  
    System.out.println(redisTemplate.countExistingKeys(redisTemplate.keys("*")));
  35.  
    }
  36.  
     
  37.  
    /**
  38.  
    * Hash --API
  39.  
    */
  40.  
    @Test
  41.  
    void test09(){
  42.  
    HashOperations<String, Object, Object> hashOperations = redisTemplate.opsForHash();
  43.  
    //hset
  44.  
    hashOperations.put("number","NO1","金钱");
  45.  
    hashOperations.put("number","NO2","亲情");
  46.  
    hashOperations.put("number","NO3","爱情");
  47.  
     
  48.  
    //hmset
  49.  
    HashMap<Object, Object> hashMap = new HashMap<>();
  50.  
    hashMap.put("number","123");
  51.  
    hashMap.put("age","25");
  52.  
    hashOperations.putAll("hmset",hashMap);
  53.  
     
  54.  
    //hget
  55.  
    Object o = hashOperations.get("number", "NO1");
  56.  
    System.out.println("获取number集合中 no1-key的值:"+o);
  57.  
     
  58.  
    //hkeys
  59.  
    Set<Object> number = hashOperations.keys("number");
  60.  
    System.out.println("获取number集合中的所有keys:"+number);
  61.  
     
  62.  
    //hvals
  63.  
    List<Object> number1 = hashOperations.values("number");
  64.  
    System.out.println("获取number集合中的所有values:"+number1);
  65.  
     
  66.  
    //hdel
  67.  
    hashOperations.delete("hmset","age");
  68.  
    //获取键值对
  69.  
    System.out.println("获取hmset的键值对"+hashOperations.entries("hmset"));
  70.  
    hashOperations.put("hmset","age",20);
  71.  
    System.out.println("获取hmset的age-value值"+hashOperations.get("hmset","age"));
  72.  
     
  73.  
    //hincrby 使变量中的键以double值的大小进行自增长。
  74.  
    hashOperations.increment("hmset1","number",1);
  75.  
    System.out.println(hashOperations.get("hmset1","number"));
  76.  
    }
  77.  
     
  78.  
    /**
  79.  
    * LIST --API
  80.  
    */
  81.  
    @Test
  82.  
    void test(){
  83.  
    ListOperations<String, Object> opsForList= redisTemplate.opsForList();
  84.  
    //lpush rpush
  85.  
    opsForList.rightPushAll("rpush","a","b","c","d");
  86.  
     
  87.  
    //lrange
  88.  
    System.out.println("取rpush集合中的所有值:"+opsForList.range("rpush", 0, -1));
  89.  
     
  90.  
    //lpop rpop
  91.  
    /*Long size = opsForList.size("rpush");
  92.  
    for (int i = 0; i < size; i++) {
  93.  
    System.out.println("从rpush集合中弹出:"+opsForList.leftPop("rpush"));
  94.  
    }*/
  95.  
     
  96.  
    Object object = null;
  97.  
    while (opsForList.leftPop("rpush") != null){
  98.  
    System.out.println("从rpush集合中弹出:"+opsForList.leftPop("rpush"));
  99.  
    }
  100.  
     
  101.  
    }
  102.  
    /**
  103.  
    * Set --Api
  104.  
    */
  105.  
    @Test
  106.  
    void test105(){
  107.  
    SetOperations<String, Object> opsForSet = redisTemplate.opsForSet();
  108.  
    //sadd
  109.  
    opsForSet.add("set1", "a","b","c","d","c","a");
  110.  
    //smembers
  111.  
    System.out.println(opsForSet.members("set1"));
  112.  
    //scard
  113.  
    System.out.println(opsForSet.size("set1"));
  114.  
    //sismember
  115.  
    System.out.println(opsForSet.isMember("set1","a"));
  116.  
    System.out.println(opsForSet.isMember("set1","x"));
  117.  
    //随机选取
  118.  
    //srandrem
  119.  
    System.out.println(opsForSet.randomMembers("set1", 3));
  120.  
    System.out.println(opsForSet.randomMembers("set1", 3));
  121.  
    System.out.println(opsForSet.randomMembers("set1", 3));
  122.  
    System.out.println(opsForSet.members("set1"));
  123.  
    System.out.println(opsForSet.pop("set1", 1));
  124.  
    System.out.println(opsForSet.pop("set1", 1));
  125.  
    System.out.println(opsForSet.members("set1"));
  126.  
    }
  127.  
     
  128.  
    /**
  129.  
    * Zset --API
  130.  
    */
  131.  
    @Test
  132.  
    void test11(){
  133.  
    ZSetOperations<String, Object> opsForZset = redisTemplate.opsForZSet();
  134.  
    //zadd
  135.  
    opsForZset.add("zset","数学",80);
  136.  
    opsForZset.add("zset","物理",70);
  137.  
    opsForZset.add("zset","英语",140);
  138.  
    System.out.println("zset中的全部key:"+opsForZset.range("zset",0,-1));
  139.  
     
  140.  
    Set<ZSetOperations.TypedTuple<Object>> zset = opsForZset.rangeWithScores("zset", 0, -1);
  141.  
    for (ZSetOperations.TypedTuple<Object> o :zset) {
  142.  
    System.out.println(o.getValue());
  143.  
    System.out.println(o.getScore());
  144.  
    }
  145.  
     
  146.  
    }
  147.  
     
  148.  
    /**
  149.  
    * Zset --API 方式二:
  150.  
    * Arrays.asList()将数组转换为集合后,底层其实还是数组,它返回的是Arrays的一个内部类,体现了适配器模式。
  151.  
    * 传递的数组必须是对象数组,而不是基本类型。
  152.  
    */
  153.  
    @Test
  154.  
    void test12(){
  155.  
    ZSetOperations<String, Object> opsForZSet = redisTemplate.opsForZSet();
  156.  
    Set<ZSetOperations.TypedTuple<Object>> zset2 = new HashSet<>();
  157.  
    DefaultTypedTuple<Object> t1 = new DefaultTypedTuple<>("历史", 80.0);
  158.  
    DefaultTypedTuple<Object> t2 = new DefaultTypedTuple<>("政治", 68.0);
  159.  
    DefaultTypedTuple<Object> t3 = new DefaultTypedTuple<>("地理", 90.0);
  160.  
    opsForZSet.add("zset2",new HashSet<>(Arrays.asList(t1,t2,t3)));
  161.  
     
  162.  
    }

4.Redission

Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务。其中包括Bitset, Set, MultiMap, SortedSet, Map, List, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, AtomicLong, CountDownLatch, Publish/Subscribe, Bloom filter, Remote service, Spring cache, Executor service, Live Object service, Scheduler service。Redisson提供了使用Redis的最简单和最便捷的方法。Redisson的宗旨是促进使用者对Redis的关注分离(Separation of Concern),从而让使用者能够将精力更集中地放在处理业务逻辑上。(官话)

暂时我用的Redission还不多 只在使用分布式锁时用了下 

在一些场合中 比如在集群,多条指令,就需要分布式锁来进行控制Redis安全性

 

Redission依赖:

  1.  
    <dependency>
  2.  
    <groupId>org.springframework.session</groupId>
  3.  
    <artifactId>spring-session-data-redis</artifactId>
  4.  
    </dependency>

配置类:

  1.  
    /**
  2.  
    * Redisson 分布式锁
  3.  
    */
  4.  
     
  5.  
    @Configuration
  6.  
    public class RedissonConfiguration {
  7.  
    @Bean
  8.  
    public RedissonClient redissonClient(){
  9.  
    Config config=new Config();
  10.  
    config.useSingleServer().setAddress("redis://xxx");
  11.  
    config.useSingleServer().setPassword("xxx");
  12.  
    return Redisson.create(config);
  13.  
    }
  14.  
    }

 实际使用:

但是这样会使效率变低(比如秒杀)

  1.  
    /**
  2.  
    * 使用分布式锁
  3.  
    */
  4.  
    @RequestMapping("/lock")
  5.  
    public void incr2(){
  6.  
    RLock mylock = redissonClient.getLock("mylock");
  7.  
    mylock.lock();
  8.  
    //过期解锁 无需调用unlock
  9.  
    //mylock.lock(10, TimeUnit.SECONDS);
  10.  
    //尝试加锁 最多等待2秒 8s过期自动解锁
  11.  
    //boolean b = mylock.tryLock(2, 8, TimeUnit.SECONDS);
  12.  
    ValueOperations<String, Object> opsForValue = redisTemplate.opsForValue();
  13.  
    Object num = opsForValue.get("num");
  14.  
    if(num == null){
  15.  
    opsForValue.set("num","1");
  16.  
    }else{
  17.  
    int count=Integer.parseInt(num.toString());
  18.  
    count++;
  19.  
    opsForValue.set("num", count+"");
  20.  
    }
  21.  
    mylock.unlock();
  22.  
    }

在使用分布式锁时需要注意

    1.设置过期时间:当前应用加锁,如果宕机,可以正常解锁
    2.解锁只能解自己的锁,不能解别人的锁:线程id
    3.执行结束删除锁:判断+删除,两个指令中间可能会被打断执行,可能删除别人的锁。解决:Lua脚本:可以将多个Redis指令写成一组,一次发送,同时执行,保证原子性

posted @ 2022-09-14 17:10  甜菜波波  阅读(962)  评论(0编辑  收藏  举报