Bootstrap

Java 操作 Redis和redis持久化

一、Jedis

我们要使用 Java 来操作 Redis,Jedis 是 Redis 官方推荐的 java连接开发工具! 使用Java 操作 Redis 中间件!

1.导入对应的依赖

https://mvnrepository.com/artifact/redis.clients/jedis

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

2、编码测试:

@SpringBootTest
class TransactionYiburenwuApplicationTests {

    @Test
    void contextLoads() {
        //测试一下redis
        //1.new Jedis对象即可
        Jedis jedis = new Jedis("localhost", 6379);
        //2.jedis所有的命令就是我们之前学习的所有指令!所以之前的指令学习很重要!
        //System.out.println(jedis.ping());
        System.out.println(jedis.set("name","lili"));
        System.out.println(jedis.get("name"));
    }
}

二、Spring-data-redis

spring data redis中封装了两个模板类,帮助我们实现redis的crud

RedisTemplate            key value泛型都是object

StringRedisTemplate   key value泛型都是string

注意:

1.两者数据各自存,各自取,数据不互通。

RedisTemplate不能取StringRedisTemplate存入的数据 StringRedisTemplate不能取RedisTemplate存入的数据

2.序列化策略不同:

RedisTemplate采用JDK的序列化策略(JdkSerializationRedisSerializer)保存的key 和value 都是采用此策略序列化保存的存储时,先将数据序列化为字节数组,再存入Redis数据库。查看Redis会发现,是字节数组的形式类似乱码读取时,会将数据当做字节数组转化为我们需要的数据,以用来存储对象,但是要实现 Serializable接口

StringRedisTemplate采用String的序列化策略(StringRedisSerializer)保存的key和 value都是采用此策略序列化保存的当存入对象时,会报错:can not cast into String 存储和读取,都为可读的数据

3.两者的关系是StringRedisTemplate继承RedisTemplate

4.使用场景:

当你的redis数据库里面本来存的是字符串数据或者你要存取的数据就是字符串类型数据的时候,那么你就使用StringRedisTemplate即可。 但是如果你的数据是复杂的对象类型,而取出的时候又不想做任何的数据转换,直接从Redis里面取出一个对象,那么使用RedisTemplate是更好的选择。

  五大数据类型 *         *         *    

redisTemplate.opsForValue();//操作字符串

redisTemplate.opsForList();//操作List

redisTemplate.opsForSet();//操作Set        

redisTemplate.opsForZSet();//操作ZSet

redisTemplate.opsForHash();//操作Hash

操作: 

1.加入Redis相关依赖

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

2.application.properties中加入redis相关配置

# Redis数据库索引(默认为0)  

spring.redis.database=0  

# Redis服务器地址  

spring.redis.host=192.168.0.24  

# Redis服务器连接端口  

spring.redis.port=6379  

# Redis服务器连接密码(默认为空)  

spring.redis.password=  

# 连接池最大连接数(使用负值表示没有限制)  

spring.redis.pool.max-active=200  

# 连接池最大阻塞等待时间(使用负值表示没有限制)  

spring.redis.pool.max-wait=-1  

# 连接池中的最大空闲连接  

spring.redis.pool.max-idle=10

# 连接池中的最小空闲连接  

spring.redis.pool.min-idle=0  

# 连接超时时间(毫秒)  

spring.redis.timeout=1000 

3.具体代码了解

@RunWith(SpringRunner.class)
@SpringBootTest
class SpringbootRedisApplicationTests {
    //演示1(专用对象)
    @Autowired
    public RedisTemplate redisTemplate;

    //演示2(专用字符串key value均是String)
    @Autowired
    public StringRedisTemplate stringRedisTemplate;

    //演示3(自定义)
    @Autowired
    public RedisTemplate jsonRedisTemplate;

    /**
     * 测试RedisTemplate
     * 注意:
     * 1.测试RedisTemplate与stringRedisTemplate存的数据相互独立
     * 2.redisTemplate默认使用key序列化方式和value的序列化方式都使用的是jdk serializer序列化
     * 	 所以存对象会乱码
     *
     * */
    @Test
    public void redisTemplate() {
        ValueOperations valueOperations = redisTemplate.opsForValue();
        valueOperations.set("name","lili");
        String name = (String)valueOperations.get("name");
        System.out.println(name);

        Student stu1 = new Student(1, "pony", "play");
        redisTemplate.opsForValue().set("stu1",stu1);
        Object ss1 = redisTemplate.opsForValue().get("stu1");
        System.out.println(ss1);

        redisTemplate.opsForList().leftPushAll("mylist","睡觉","打豆豆");
        List<String> list=redisTemplate.opsForList().range("mylist",0,-1);
        for(int i=0;i<list.size();i++){
            String s = list.get(i);
            System.out.println(s);
        }
        System.out.println("打印默认序列策略"+redisTemplate.getDefaultSerializer());

    }
    /**
     * 测试stringRedisTemplate+
     * */
    @Test
    public void stringRedisTemplate() {
        //1.key相关
        Set<String> keys = stringRedisTemplate.keys("*");
        for (String key:keys){
            System.out.println(key);
        }
        //2.各种类型支持
        stringRedisTemplate.opsForValue();//String
        stringRedisTemplate.opsForList();//List
        stringRedisTemplate.opsForHash();//hash
        stringRedisTemplate.opsForSet();//set
        stringRedisTemplate.opsForZSet();//zset
        //3.举例字符串
        stringRedisTemplate.opsForValue().set("name","ken");
        String name = stringRedisTemplate.opsForValue().get("name");
        System.out.println(name);
        //4.操作list列表
        stringRedisTemplate.opsForList().leftPush("mylist1","吃饭");
        stringRedisTemplate.opsForList().leftPush("mylist1","玩儿");
        stringRedisTemplate.opsForList().leftPushAll("mylistall","吃饭","睡觉","打豆豆");
        List<String> list = stringRedisTemplate.opsForList().range("mylistall", 0, 2);
        System.out.println(list);

    }

}

三、jsonRedisTemplate自定义序列化策略

1.配置类:

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<Object, Object> jsonRedisTemplate(
            RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        //1.创建自定义模板类
        RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>();
        //配置json类型的序列化工具
        template.setKeySerializer(new StringRedisSerializer());//这样key会用字符串方式保存
        template.setDefaultSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));

        template.setConnectionFactory(redisConnectionFactory);

        return template;
    }



}

2.具体代码了解: 

 /**
     * 测试自定义
     * 法意:定义配置类JavaConfig,自定义序列化策略
     *
     * */
    @Test
    public void jsonRedisTemplate(){
        //保存对象
        Student stu = new Student(1,"xx","拉面");
        jsonRedisTemplate.opsForValue().set("stu",stu);
        //获取对象
        Object s1 = jsonRedisTemplate.opsForValue().get("stu");
        String jsonS1 = JSONObject.toJSONString(s1);
        Student s11 = JSONObject.parseObject(jsonS1,Student.class);
        System.out.println(s11);

        Student stu2 = new Student(2,"ll","拉面");
        Student stu1 = new Student(2,"ll","拉面");
        Student stu3 = new Student(2,"ll","拉面");
        List<Student> students = Arrays.asList(stu1, stu2, stu3);
        jsonRedisTemplate.opsForValue().set("stus",students);
        //必须Object接受,利用ObjectMapper对象转换,如果强制转换会报错
        Object data = jsonRedisTemplate.opsForValue().get("stus");
        String dataJson = JSONObject.toJSONString(data);
        //将JSON类型转为List
        List<Student> stus = JSONObject.parseArray(dataJson, Student.class);
        System.out.println(stus);

    }

四、redis持久化

Redis 是内存数据库,如果不将内存中的数据库状态保存到磁盘,那么一旦服务器进程退出,服务器中 的数据库状态也会消失。所以 Redis 提供了持久化功能!

持久化过程保存什么

1.将当前数据状态进行保存,快照形式,存储数据结果,存储格式简单,关注点在数据 (RDB) 2.将数据的操作过程进行保存,日志形式,存储操作过程,关注点在数据的操作过程(AOF)

4.1RDB方式

概念: 在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的Snapshot快照,它恢复时是将 快照文件直接读到内存里

4.2AOF方式

概念: AOF(append only file)持久化:以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中命令 达到恢复数据的目的;与RDB相比可以简单描述为改记录数据为记录数据产生的过程AOF的主要作用是 解决了数据持久化的实时性,目前已经是Redis持久化的主流方式

AOF执行过程

客户端的请求写命令会被append追加到AOF缓冲区内;

AOF缓冲区根据AOF持久化策略[always,everysec,no]将操作sync同步到磁盘的AOF文件中;

AOF文件大小超过重写策略或手动重写时,会对AOF文件rewrite重写,压缩AOF文件容量;

Redis服务重启时,会重新load加载AOF文件中的写操作达到数据恢复的目的;

AOF写数据三种策略(appendfsync)

always(每次) 每次写入操作均同步到AOF文件中,数据零误差,性能较低

everysec(每秒) 每秒将缓冲区中的指令同步到AOF文件中,数据准确性较高,性能较高 在系统突然宕机的情况下丢失1秒内的数据

no(系统控制) 由操作系统控制每次同步到AOF文件的周期,整体过程不可控

比较: 

 

 

;