eyb:Redis学习(2)


目录:

(1)Jedis连接Redis

(2)Jedis连接池连接Redis

(3)封装JedisUtil对外提供连接对象获取的方法

(4)Jedis操作String数据类型

(5)Jedis操作hash数据类型

(6)Jedis操作list类型的数据

(7)Jedis操作set类型数据

(8)Jedis操作sortesSet数据类型

(9)层级目录、失效时间

(10)获取所有key+事务

(11)Jedis操作byte数组

(12)Redis持久化方案-bgsave

(13)Redis持久化方案-rdb


(1)Jedis连接Redis

通过Java代码操作Redis,通过客户端使用命令比较少

创建springbooot项目,选择依赖:

redis依赖默认继承的是Lettuce客户端,我们先学习Jedis客户端

区别:

Jedis是直连连接的,直接连接到Redis服务器,在多个线程上是共享一个Jedis实例的,所以这个时候线程是不安全的,所以你想在多线程场景下使用Jedis需要使用连接池,每个线程都会使用自己的Jedis实例, 当你的连接数增多的时候呢,会消耗比较多的物理资源  Jedis并发不安全

Lettuce:完全克服线程不安全的特点是基于Netty的连接方式,他支持同步异步响应式的操作,多线程之间呢共享连接实例,不必担心多线程的并发问题,并发比较安全一点

我们需要移出默认的Lettuce依赖,重新引入Redis依赖

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.xxxx</groupId>
    <artifactId>redis-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <name>redis-demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <!--redis依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>

            <!--
                1.x 的版本蓦然采用的连接池技术是Jedis
                2.0以上的版本默认采用的连接池是Lettuce
                如果采用Jedis,需要排除Lettuce依赖
            -->
            <exclusions>
                <exclusion>
                    <groupId>io.lettuce</groupId>
                    <artifactId>lettuce-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--Jedis依赖-->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
        <!--web组件依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--test依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>



</project>

application.yml:配置文件

spring:
  redis:
    # Redis服务器地址
    host: 192.168.67.128
    # Redis服务端口
    port: 6379
    # 设置redis服务器密码
    password: root
    # 选择那个库,默认是0
    database: 0
    # 连接超时时间
    timeout: 10000ms
    jedis:
      pool:
        # 最大连接数,默认18
        max-active: 1024
        # 最大连接阻塞时间,单位为毫秒,默认-1ms
        max-wait: 10000ms
        # 最大空闲连接,默认8
        max-idle: 200
        # 最小空闲连接
        min-idle: 5

  测试类:

package com.xxxx.redisdemo;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import redis.clients.jedis.Jedis;

@SpringBootTest
class RedisDemoApplicationTests {

    @Test
    public void initConnt(){
        //创建Jedis对象,连接redis服务器
        Jedis jedis=new Jedis("192.168.67.128",6379);
        //设置认证密码
        jedis.auth("root");
        //指定数据库
        jedis.select(1);
        //使用pink命令连接是否成功
        String result = jedis.ping();
        System.out.println(result);
        //添加一条数据
        jedis.set("name","zhangsan");
        //获取数据
        String name = jedis.get("name");
        System.out.println(name);

        //操作完之后关闭jedis
        if (jedis!=null){
            jedis.close();
        }
    }

}

redis可视化工具:

(2)Jedis连接池连接Redis

Jedis连接Redis服务器没有问题了,但是我们现在是直接创建的Jedis对象,Jedis是线程不安全的,多线程的情况下我们会用连接池,来处理Jedis,下面我们用连接池来获取我们的一个连接对象 并且操作redis服务器

测试类:

package com.xxxx.redisdemo;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

@SpringBootTest
class RedisDemoApplicationTests {

   

    //使用Jedis连接池操作Jedis
    @Test
    public void initConnt2(){
        //初始化创建Jedis连接池
        JedisPool jedisPool=new JedisPool(new JedisPoolConfig(),"192.168.67.128",6379,10000,"root");
        //从连接池获取Jedis对象
        Jedis jedis = jedisPool.getResource();

        //使用pink命令连接是否成功
        String result = jedis.ping();
        System.out.println(result);

        //指定数据库,默认为0
        jedis.select(2);
        //添加一条数据
        jedis.set("name","wangwu");
        //获取数据
        String name = jedis.get("name");
        System.out.println(name);

        //释放资源
        if (jedis!=null){
            jedis.close();
        }

    }

}

 

 Jedis客户端可视化工具:

(3)封装JedisUtil对外提供连接对象获取的方法

上面的操作,我们都要新建一个连接池,再获取Jedis对象,再进行相关操作,操作完之后再释放资源,这种逻辑在实际开发中是不允许的,在实际开发中是这样的,当项目启动后,线程池只会创建一次,不可能会被频繁的创建,创建完一次之后呢 ,Jedis从线程池里面拿对象,拿完对象进行操作,操作完之后进行释放资源,下次之后呢直接从线程池去拿就行了,不需要新建一个线程池了,线程值只要新建一次

我们现在新建一个配置类,让线程对象呢只会新建一次

ReidsConfig:

package com.xxxx.redisdemo.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;


@Configuration
public class RedisConfig {

    //使用Value注解读取注入配置文件内容
    //服务器地址
    @Value("${spring.redis.host}")
    private String host;
    //服务器端口
    @Value("${spring.redis.port}")
    private int port;
    //访问密码
    @Value("${spring.redis.password}")
    private String password;
    //连接超时时间
    @Value("${spring.redis.timeout}")
    private String timeout;

    //最大连接数
    @Value("${spring.redis.jedis.pool.max-active}")
    private int maxTotal;
    //最大连接等待阻塞时间
    @Value("${spring.redis.jedis.pool.max-wait}")
    private String maxWaitMillis;
    //最大空闲连接
    @Value("${spring.redis.jedis.pool.max-idle}")
    private int maxIdle;
    //最小空闲连接
    @Value("${spring.redis.jedis.pool.min-idle}")
    private int minIdle;



    @Bean
    public JedisPool getJedisPool(){
        //配置
        JedisPoolConfig jedisPoolConfig= new JedisPoolConfig();
        //最大连接数
        jedisPoolConfig.setMaxTotal(maxTotal);
        //最大阻塞时间
        jedisPoolConfig.setMaxWaitMillis(Long.valueOf(maxWaitMillis.substring(0,maxWaitMillis.length()-2)));
        //最大空闲连接
        jedisPoolConfig.setMaxIdle(maxIdle);
        //最小空闲连接
        jedisPoolConfig.setMinIdle(minIdle);

        //Jedis对象
        JedisPool jedisPool=new JedisPool(jedisPoolConfig,host,port,Integer.valueOf(timeout.substring(0,timeout.length()-2)),password);

        return jedisPool;
    }
}

测试类:

使用了Junit的注解@Before @After,需要在配置类上面加一个注解@RunWith(SpringRunner.class)注解,否则获取的连接池对象为null

package com.xxxx.redisdemo;

import org.junit.After;
import org.junit.Before;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

@SpringBootTest
@RunWith(SpringRunner.class)
class RedisDemoApplicationTests {


    //注入线程池对象
    @Autowired
    private JedisPool jedisPool;

    Jedis jedis=null;

    //初始化jedis实例对象
    @Before //每次运行Test之前获取jedisPool对象
    public void initConnt3(){
        jedis = jedisPool.getResource();

    }

    //释放资源
    @After
    public void closeConnt(){
        if (null!=jedis){
            jedis.close();
        }
    }


}

这样通过@Autoeired拿到jedisPool,然后在内次运行@test方法之前呢,都会经过@Before从连接池拿到redis对象,结束test方法之后呢,经过@After释放jedis对象

(4)Jedis操作String数据类型

测试类:

package com.xxxx.redisdemo;

import org.junit.After;
import org.junit.Before;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.util.List;

@SpringBootTest
@RunWith(SpringRunner.class)
class RedisDemoApplicationTests {



    //注入线程池对象
    @Autowired
    private JedisPool jedisPool;

    Jedis jedis=null;

    //初始化jedis实例对象
    @BeforeEach //每次运行Test之前获取jedisPool对象
    public void initConnt3(){
        jedis = jedisPool.getResource();

    }


    //操作string类型数据
    @Test
    public void testString(){
        //添加数据
        jedis.set("name","zhangsan1");
        //获取一条数据
        String name = jedis.get("name");
        System.out.println(name);
        //添加多条数据
        jedis.mset("address","sh","sex","1");
        //获取多条数据
        List<String> list = jedis.mget("name", "address", "sex");
        list.forEach(System.out::println);

        //删除数据
        Long result = jedis.del("name");
        System.out.println(result);
    }

    //释放资源
    @AfterEach
    public void closeConnt(){
        if (null!=jedis){
            jedis.close();
        }
    }


}

 运行@Test

出现了异常:解决办法

有关使用junit依赖出现@Before或者@Before注解不生效

有可能是Junit使用版本过高,有两种解决方法:
1.如果Junit使用版本较高,可以使用@BeforeEach和@AfterEach代替@Before和@After
2.降低Junit版本 

可视化界面客户端:

看到成功的添加到第一个数据库中:因为name删除了没有添加进来

 

 (5)Jedis操作hash数据类型

测试类:

package com.xxxx.redisdemo;

import org.junit.After;
import org.junit.Before;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@SpringBootTest
@RunWith(SpringRunner.class)
class RedisDemoApplicationTests {


    //注入线程池对象
    @Autowired
    private JedisPool jedisPool;

    Jedis jedis=null;

    //初始化jedis实例对象
    @BeforeEach //每次运行Test之前获取jedisPool对象
    public void initConnt3(){
        jedis = jedisPool.getResource();

    }


    

    //操作hash
    @Test
    public void testHash(){
        //添加一条数据 第一个参数是redis的key 第二个参数hash的key 第三个参数的hash的value
        jedis.hset("user","name","zhangsan");
        //获取一条数据
        String name = jedis.hget("user", "name");
        System.out.println(name);
        //添加多条数据
        Map<String, String> map = new HashMap<>();
        map.put("age","20");
        map.put("sex","1");
        jedis.hmset("user",map);

        //获取多条数据
        List<String> list = jedis.hmget("user", "age", "sex");
        list.forEach(System.out::println);

        //获取hash类型的所有数据
        Map<String, String> user = jedis.hgetAll("user");
        user.entrySet().forEach(e->{
            System.out.println(e.getKey()+"-----"+e.getValue());
        });

        //删除数据
        jedis.hdel("user","name","age");

    }

    //释放资源
    @AfterEach
    public void closeConnt(){
        if (null!=jedis){
            jedis.close();
        }
    }


}

 可视化客户端:添加了user的hash类型

 (6)Jedis操作list类型的数据

package com.xxxx.redisdemo;

import org.junit.After;
import org.junit.Before;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

@SpringBootTest
@RunWith(SpringRunner.class)
class RedisDemoApplicationTests {



    //注入线程池对象
    @Autowired
    private JedisPool jedisPool;

    Jedis jedis=null;

    //初始化jedis实例对象
    @BeforeEach //每次运行Test之前获取jedisPool对象
    public void initConnt3(){
        jedis = jedisPool.getResource();

    }


    //操作list类型的数据
    @Test
    public void testlist(){
        //左添加
        jedis.lpush("students","zhangsan","lisi");
        //右添加
        jedis.rpush("students","wangwu","zhangliu");
        //获取数据 第一个参数redis的key 第二个参数起始下标 第三个参数结束下标
        List<String> list = jedis.lrange("students", 0, 3);
        list.forEach(System.out::println);
        //获取总条数
        Long totall = jedis.llen("students");
        System.out.println(totall);
        //删除数据 第二个参数删除的个数 第三个参数需要删除的值
        jedis.lrem("students",1,"lisi");

        /*
        //左弹出 相当于从左边开始删除一条数据
        String left = jedis.lpop("students");
        System.out.println(left);

        //右弹出 相当于从右边开始删除一条数据
        String right = jedis.rpop("students");
        System.out.println(right);
        */

    }


    //释放资源
    @AfterEach
    public void closeConnt(){
        if (null!=jedis){
            jedis.close();
        }
    }


}

 可视化客户端:

左弹出、右弹出

 

package com.xxxx.redisdemo;

import org.junit.After;
import org.junit.Before;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

@SpringBootTest
@RunWith(SpringRunner.class)
class RedisDemoApplicationTests {



    //注入线程池对象
    @Autowired
    private JedisPool jedisPool;

    Jedis jedis=null;

    //初始化jedis实例对象
    @BeforeEach //每次运行Test之前获取jedisPool对象
    public void initConnt3(){
        jedis = jedisPool.getResource();

    }


    //操作list类型的数据
    @Test
    public void testlist(){
        /*//左添加
        jedis.lpush("students","zhangsan","lisi");
        //右添加
        jedis.rpush("students","wangwu","zhangliu");
        //获取数据 第一个参数redis的key 第二个参数起始下标 第三个参数结束下标
        List<String> list = jedis.lrange("students", 0, 3);
        list.forEach(System.out::println);
        //获取总条数
        Long totall = jedis.llen("students");
        System.out.println(totall);
        //删除数据 第二个参数删除的个数 第三个参数需要删除的值
        jedis.lrem("students",1,"lisi");*/

        //左弹出 相当于从左边开始删除一条数据
        String left = jedis.lpop("students");
        System.out.println(left);

        //右弹出 相当于从右边开始删除一条数据
        String right = jedis.rpop("students");
        System.out.println(right);


    }


    //释放资源
    @AfterEach
    public void closeConnt(){
        if (null!=jedis){
            jedis.close();
        }
    }


}

 

(7)Jedis操作set类型数据

 

package com.xxxx.redisdemo;

import org.junit.After;
import org.junit.Before;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

@SpringBootTest
@RunWith(SpringRunner.class)
class RedisDemoApplicationTests {


    //注入线程池对象
    @Autowired
    private JedisPool jedisPool;

    Jedis jedis=null;

    //初始化jedis实例对象
    @BeforeEach //每次运行Test之前获取jedisPool对象
    public void initConnt3(){
        jedis = jedisPool.getResource();

    }



    //操作set类型的数据
    @Test
    public void testSet(){
        //添加数据
        jedis.sadd("letters","aaa","bbb","ccc","ddd","eee");
        //获取数据
        Set<String> set = jedis.smembers("letters");
        set.forEach(System.out::println);

        //获取总条数
        Long totall = jedis.scard("letters");
        System.out.println(totall);

        //删除数据
        jedis.srem("letters","aaa","bbb");

    }

    //释放资源
    @AfterEach
    public void closeConnt(){
        if (null!=jedis){
            jedis.close();
        }
    }


}

可视化客户端 

 可视化客户端

 (8)Jedis操作sortesSet数据类型

package com.xxxx.redisdemo;

import org.junit.After;
import org.junit.Before;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

@SpringBootTest
@RunWith(SpringRunner.class)
class RedisDemoApplicationTests {

    //注入线程池对象
    @Autowired
    private JedisPool jedisPool;

    Jedis jedis=null;

    //初始化jedis实例对象
    @BeforeEach //每次运行Test之前获取jedisPool对象
    public void initConnt3(){
        jedis = jedisPool.getResource();

    }


  

    //操作sorted set
    @Test
    public void testSortedSet(){
        //存储数据
        Map<String,Double> map=new HashMap<>();
        map.put("zhangsan",7D);
        map.put("lisi",3D);
        map.put("wangwu",5D);
        map.put("zhaoliu",6D);
        map.put("tianqi",1D);
        jedis.zadd("score",map);

        //获取数据 第一个参数redis中的key 第二个参数:起始下标 第三个参数:结束下标
        Set<String> set = jedis.zrange("score", 0, 4);
        set.forEach(System.out::println);

        //获取总条数
        Long total = jedis.zcard("score");
        System.out.println(total);

        //删除数据
        jedis.zrem("score","zhagnsan","wangwu");
    }

    //释放资源
    @AfterEach
    public void closeConnt(){
        if (null!=jedis){
            jedis.close();
        }
    }


}

 

 (9)层级目录、失效时间

package com.xxxx.redisdemo;

import org.junit.After;
import org.junit.Before;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.params.SetParams;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

@SpringBootTest
@RunWith(SpringRunner.class)
class RedisDemoApplicationTests {



    //注入线程池对象
    @Autowired
    private JedisPool jedisPool;

    Jedis jedis=null;

    //初始化jedis实例对象
    @BeforeEach //每次运行Test之前获取jedisPool对象
    public void initConnt3(){
        jedis = jedisPool.getResource();

    }




    //层级目录形式存储数据:
    @Test
    public void testDir(){
        jedis.set("cart:user01:item01","apple");
        System.out.println(jedis.get("cart:user01:item01"));
    }


    //释放资源
    @AfterEach
    public void closeConnt(){
        if (null!=jedis){
            jedis.close();
        }
    }


}

 

 

package com.xxxx.redisdemo;

import org.junit.After;
import org.junit.Before;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.params.SetParams;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

@SpringBootTest
@RunWith(SpringRunner.class)
class RedisDemoApplicationTests {



    //注入线程池对象
    @Autowired
    private JedisPool jedisPool;

    Jedis jedis=null;

    //初始化jedis实例对象
    @BeforeEach //每次运行Test之前获取jedisPool对象
    public void initConnt3(){
        jedis = jedisPool.getResource();

    }





    //key的失效时间
    @Test
    public void testExpire(){

        /*//设置存在的值失效时间30秒
        jedis.set("code","test");
        //设置失效时间单位 秒
        jedis.expire("code",30);
        //设置失效时间单位 毫秒
        jedis.pexpire("code",30000);
        //查看失效时间单位秒 -1:用不失效 -2:已经失效
        Long ttl = jedis.ttl("code");
        System.out.println(ttl);*/

        //添加key设置失效时间
        //设置失效时间单位 秒
        jedis.setex("code",30,"test");
        //设置失效时间单位 毫秒
        //jedis.psetex("code",30000,"test");
        //查看失效时间单位 毫秒
        Long pttl = jedis.pttl("cose");
        System.out.println(pttl);

        //nx xx用法
        SetParams setParams=new SetParams();
        //不存在时才能设置成功
        setParams.nx();
        //存在时才能设置成功
        setParams.xx();
        //设置失效时间单位 秒
        setParams.ex(30);
        //设置失效时间单位 毫秒
        //setParams.px(30000);
        jedis.set("cose","test",setParams);
    }
    //释放资源
    @AfterEach
    public void closeConnt(){
        if (null!=jedis){
            jedis.close();
        }
    }


}

(10)获取所有key+事务

package com.xxxx.redisdemo;

import org.junit.After;
import org.junit.Before;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Transaction;
import redis.clients.jedis.params.SetParams;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

@SpringBootTest
@RunWith(SpringRunner.class)
class RedisDemoApplicationTests {



    //注入线程池对象
    @Autowired
    private JedisPool jedisPool;

    Jedis jedis=null;

    //初始化jedis实例对象
    @BeforeEach //每次运行Test之前获取jedisPool对象
    public void initConnt3(){
        jedis = jedisPool.getResource();

    }


  

    //获取所有key
    @Test
    public void testAllKey(){
        //当前数据库key的数量
        Long size = jedis.dbSize();
        System.out.println(size);
        //查询当前数据库的所有key
        Set<String> set = jedis.keys("*");
        set.forEach(System.out::println);
    }

    //事务
    @Test
    public void testMutil(){
        //开启事务
        Transaction tx=jedis.multi();
        tx.set("tel","10086");
        //提交事务
        tx.exec();

        //回滚事务
        //tx.discard();
    }

    //释放资源
    @AfterEach
    public void closeConnt(){
        if (null!=jedis){
            jedis.close();
        }
    }


}

第一个test:

数据库中有7个key

 

 第二个test:

 

如果注释提交,开启回滚,不会存入数据库 

事务比如说操作3张表,第一 第二 已经操作成功了,不会回滚了,第三张表出了问题,它自己回滚,第四章不会运行了

Redis并没有表的概念,它都是key value形式的数据库,没有表的概念,所以正常也没有多表联查的功能,只是说你开启事务混滚功能,它只会把当前出错的数据进行回滚,但是之前操作成功的并不会回滚,事务能力比较弱的

 (11)Jedis操作byte数组

非关系型数据库,可以存放一个对象,可以先把这个对相关转换成一个byte数组,把它存到redis里面去

序列化工具类:

SerializeUtil:

package com.xxxx.redisdemo.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class SerializeUtil {

    //将java对象转换为byte数组 序列化过程
    public static byte[] serialize(Object object){
        ObjectOutputStream oos=null;
        ByteArrayOutputStream baos=null;
        try{
            //序列化
            baos=new ByteArrayOutputStream();
            oos=new ObjectOutputStream(baos);
            oos.writeObject(object);
            byte[] bytes=baos.toByteArray();
            return bytes;
        }catch(Exception e){
            e.printStackTrace();
        }
        return null;
    }

    //将byte数组转换为java对象 反序列化
    public static Object unserialize(byte[] bytes){
        if (bytes==null) return null;
        ByteArrayInputStream bais=null;
        try{
            //反序列化
            bais=new ByteArrayInputStream(bytes);
            ObjectInputStream ois=new ObjectInputStream(bais);
            return ois.readObject();
        }catch(Exception e){
            e.printStackTrace();
        }
        return null;
    }
}

pojo类:User

package com.xxxx.redisdemo.pojo;

import java.io.Serializable;

public class User implements Serializable {
    private static final long serialVersionUID=914893743109191022L;

    private Integer id;
    private String username;
    private String password;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

 测试类:

package com.xxxx.redisdemo;

import com.xxxx.redisdemo.pojo.User;
import com.xxxx.redisdemo.util.SerializeUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Transaction;
import redis.clients.jedis.params.SetParams;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

@SpringBootTest
@RunWith(SpringRunner.class)
class RedisDemoApplicationTests {



    //注入线程池对象
    @Autowired
    private JedisPool jedisPool;

    Jedis jedis=null;

    //初始化jedis实例对象
    @BeforeEach //每次运行Test之前获取jedisPool对象
    public void initConnt3(){
        jedis = jedisPool.getResource();

    }


    

    //操作byte数组
    @Test
    public void testByte(){
        User user=new User();
        user.setId(2);
        user.setUsername("zhangsan");
        user.setPassword("123456");

        //序列化key
        byte[] userKey = SerializeUtil.serialize("user:" + user.getId());
        //序列化对象
        byte[] userValue = SerializeUtil.serialize(user);

        //存入Redis
        jedis.set(userKey,userValue);
        //取出数据
        byte[] bytes = jedis.get(userKey);
        //反序列化
        User user1 =(User) SerializeUtil.unserialize(bytes);
        System.out.println(user1);
    }

    //释放资源
    @AfterEach
    public void closeConnt(){
        if (null!=jedis){
            jedis.close();
        }
    }


}

 

 

通过序列化成byte数组存入Redis,通过可视化客户端查看存入的数据,是二进制的看不懂

后面将SpringDataRedis用Lettuce的一个客户端去连接我们的Redis的时候我们会讲一个正常的序列化工具,Redis序列化的配置,去解决二进制的问题

 

(12)Redis持久化方案-bgsave

Redis是一个在内存中的存储系统,内存有一个优点,就是内存操作数据,比磁盘上操作数据的速度快,效率更高,但是他有一个无法避免的缺点,就是内存无法存储我们的数据,比如你正在操作数据的同时,突然断电了或者宕机了 ,内存存入的数据都会丢失,它并没有办法存储我们的数据,Redis提供了一个磁盘持久化的功能,通过磁盘持久化的功能,可以把内存中的数据持久化到磁盘中去

持久化方案:

1.使用bgsave命令

比如使用2窗口:设置添加一条数据

客户端存入数据:

 

 

 1窗口演示宕机或者关机,以杀死进程为例:然后再重新启动

 再次查看客户端:数据不在了

说明内存无法存储数据

输入后台保存的命令bgsave:把数据存入到磁盘里面去,即使这时候1窗口演示宕机,数据也会存在

 

 bgsave命令:优点:比较简单,只需要输入bgsave命令,就可以把数据持久化到磁盘上面去

缺点:需要频繁的使用这个命令,还是优点麻烦的

(13)Redis持久化方案-rdb

rdb持久化方案:

通过redis.conf里观看: 

持久化文件夹dump.rdb 

dir ./当前目录

save 900 1:表示只要900秒只要有一个key发生变化,就会把数据持久化到磁盘 

 

可以添加一条 

 

 rdb方案优点:比较省心,只需要在配置文件做了配置就不需要动了,它会自动根据配置问价,自动化持久化数据到磁盘

缺点:rdb有可能还是会丢失数据的,比如58秒 10000个key 58秒的时候突然宕机了,10000个key根本没有保存进去没有保存到dump.rdb这个文件中去

(14)Redis持久化方案-aof

开启appendonly:改为yes, rdb方案就会失效 

把输入的命令,会追加到appendOnly.aof这个文件中去,它是后台开启了一个线程,每当我们输入一条命令,这个线程就会把这条数据追加到appendonly.aof中去 ,当在启动的时候呢,它会先读取appendonly.aof中去,把aof中的命令读取出来,相当于把这个命令在敲一遍 

aof优点:实时的记录我们的命令,把数据持久到我们的磁盘的

缺点:如果一段时间敲了十几万行命令,这个文件就变得非常大,启动的时候呢,在读取命令是非常缓慢的

在日常的项目中,需要看具体的情况,选择合适的方案。如果允许部分数据丢失,选择使用rdb方案。

如果不允许数据丢失,需要实时更新,选择aof方案

也可能把这两种方案结合

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

喵俺第一专栏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值