IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> Jedis,lettuce,RedisTemplate,Redission区别 -> 正文阅读

[大数据]Jedis,lettuce,RedisTemplate,Redission区别

1.Jedis:

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

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

使用时:

导包

        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>

创建工具类?

public class JedisUtil {

    private  static final JedisPool jedisPool;

    static {
        //设置基本属性
        GenericObjectPoolConfig<Jedis> poolConfig = new JedisPoolConfig();
        //最大连接数
        poolConfig.setMaxTotal(50);
        //最大空闲数
        poolConfig.setMaxIdle(10);

        jedisPool = new JedisPool(poolConfig, "XXX", 6379, 2000, "XXX");
    }

    public static Jedis getJedis(){
        return jedisPool.getResource();
    }
    
}

测试使用:

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

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

2.lettuce

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

依赖:


        <dependency>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
        </dependency>

具体没咋用过

3.RedisTemplate?

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

依赖:

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

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

基础使用:

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

 @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        template.setKeySerializer(RedisSerializer.string());
        template.setValueSerializer(RedisSerializer.json());
        template.setHashKeySerializer(RedisSerializer.string());
        template.setHashValueSerializer(RedisSerializer.json());
        return template;
    }

String Hash List Set Zset 基础使用:

/**
     * String -- API
     */
    @Test
    void  test07(){
        //通用指令
        //exists
        System.out.println(redisTemplate.hasKey("a"));
        System.out.println(redisTemplate.hasKey("b"));
        //ttl
        System.out.println(redisTemplate.getExpire("a", TimeUnit.SECONDS));
        System.out.println(redisTemplate.getExpire("b", TimeUnit.SECONDS));
        //expire
        System.out.println(redisTemplate.expire("a", 100,TimeUnit.SECONDS));
        System.out.println(redisTemplate.getExpire("a", TimeUnit.SECONDS));
        redisTemplate.persist("a");
        System.out.println(redisTemplate.getExpire("a", TimeUnit.SECONDS));
    }

    /**
     * String -- API2
     */
    @Test
    void test08(){
        //keys
        ValueOperations valueOperations = redisTemplate.opsForValue();
        valueOperations.set("abc","456");

        System.out.println(redisTemplate.keys("*"));
        //dbsize
        System.out.println(redisTemplate.countExistingKeys(redisTemplate.keys("*")));
        redisTemplate.delete("aaa");
        System.out.println(redisTemplate.keys("*"));
        System.out.println(redisTemplate.countExistingKeys(redisTemplate.keys("*")));
    }

    /**
     * Hash --API
     */
    @Test
    void test09(){
        HashOperations<String, Object, Object> hashOperations = redisTemplate.opsForHash();
        //hset
        hashOperations.put("number","NO1","金钱");
        hashOperations.put("number","NO2","亲情");
        hashOperations.put("number","NO3","爱情");

        //hmset
        HashMap<Object, Object> hashMap = new HashMap<>();
        hashMap.put("number","123");
        hashMap.put("age","25");
        hashOperations.putAll("hmset",hashMap);

        //hget
        Object o = hashOperations.get("number", "NO1");
        System.out.println("获取number集合中 no1-key的值:"+o);

        //hkeys
        Set<Object> number = hashOperations.keys("number");
        System.out.println("获取number集合中的所有keys:"+number);

        //hvals
        List<Object> number1 = hashOperations.values("number");
        System.out.println("获取number集合中的所有values:"+number1);

        //hdel
        hashOperations.delete("hmset","age");
        //获取键值对
        System.out.println("获取hmset的键值对"+hashOperations.entries("hmset"));
        hashOperations.put("hmset","age",20);
        System.out.println("获取hmset的age-value值"+hashOperations.get("hmset","age"));

        //hincrby 使变量中的键以double值的大小进行自增长。
        hashOperations.increment("hmset1","number",1);
        System.out.println(hashOperations.get("hmset1","number"));
    }

    /**
     * LIST --API
     */
    @Test
    void test(){
        ListOperations<String, Object> opsForList= redisTemplate.opsForList();
        //lpush rpush
        opsForList.rightPushAll("rpush","a","b","c","d");

        //lrange
        System.out.println("取rpush集合中的所有值:"+opsForList.range("rpush", 0, -1));

        //lpop rpop
        /*Long size = opsForList.size("rpush");
        for (int i = 0; i < size; i++) {
            System.out.println("从rpush集合中弹出:"+opsForList.leftPop("rpush"));
        }*/

        Object object = null;
        while (opsForList.leftPop("rpush") != null){
            System.out.println("从rpush集合中弹出:"+opsForList.leftPop("rpush"));
        }

    }
    /**
     * Set --Api
     */
    @Test
    void test105(){
        SetOperations<String, Object> opsForSet = redisTemplate.opsForSet();
        //sadd
        opsForSet.add("set1", "a","b","c","d","c","a");
        //smembers
        System.out.println(opsForSet.members("set1"));
        //scard
        System.out.println(opsForSet.size("set1"));
        //sismember
        System.out.println(opsForSet.isMember("set1","a"));
        System.out.println(opsForSet.isMember("set1","x"));
        //随机选取
        //srandrem
        System.out.println(opsForSet.randomMembers("set1", 3));
        System.out.println(opsForSet.randomMembers("set1", 3));
        System.out.println(opsForSet.randomMembers("set1", 3));
        System.out.println(opsForSet.members("set1"));
        System.out.println(opsForSet.pop("set1", 1));
        System.out.println(opsForSet.pop("set1", 1));
        System.out.println(opsForSet.members("set1"));
    }

    /**
     * Zset --API
     */
    @Test
    void test11(){
        ZSetOperations<String, Object> opsForZset = redisTemplate.opsForZSet();
        //zadd
        opsForZset.add("zset","数学",80);
        opsForZset.add("zset","物理",70);
        opsForZset.add("zset","英语",140);
        System.out.println("zset中的全部key:"+opsForZset.range("zset",0,-1));

        Set<ZSetOperations.TypedTuple<Object>> zset = opsForZset.rangeWithScores("zset", 0, -1);
        for (ZSetOperations.TypedTuple<Object> o :zset) {
            System.out.println(o.getValue());
            System.out.println(o.getScore());
        }

    }

    /**
     *  Zset --API 方式二:
     *  Arrays.asList()将数组转换为集合后,底层其实还是数组,它返回的是Arrays的一个内部类,体现了适配器模式。
     *  传递的数组必须是对象数组,而不是基本类型。
     */
    @Test
    void test12(){
        ZSetOperations<String, Object> opsForZSet = redisTemplate.opsForZSet();
        Set<ZSetOperations.TypedTuple<Object>> zset2 = new HashSet<>();
        DefaultTypedTuple<Object> t1 = new DefaultTypedTuple<>("历史", 80.0);
        DefaultTypedTuple<Object> t2 = new DefaultTypedTuple<>("政治", 68.0);
        DefaultTypedTuple<Object> t3 = new DefaultTypedTuple<>("地理", 90.0);
        opsForZSet.add("zset2",new HashSet<>(Arrays.asList(t1,t2,t3)));

    }

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依赖:

<dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>

配置类:

/**
     * Redisson 分布式锁
     */

    @Configuration
    public class RedissonConfiguration {
        @Bean
        public RedissonClient redissonClient(){
            Config config=new Config();
            config.useSingleServer().setAddress("redis://xxx");
            config.useSingleServer().setPassword("xxx");
            return Redisson.create(config);
        }
    }

?实际使用:

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

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

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

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

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-01-17 11:34:11  更:2022-01-17 11:34:24 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 14:50:34-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码