Redis快速入门

一、简介

redis是一个非关系型数据库NoSQL(No Structured Query Language)数据库,数据以键值对存在(key 和 value)

(一)非关系型数据库简识

1.结构化与非结构化

像如上,该表便被各种条件框定住而写死了,该列的值一定是什么特性,是什么类型,这样就实现了结构化

redis的键值对型(包括以json数据作为值)数据存储,不固定值的类型和特性

2.关联的与非关联的

sql中,如上表,一个order通过user_id item_id 两个值关联了两个表,使得两个表中的单独对任一表的修改是会关联传递的

如redis中,像刚刚的order订单表,在redis中被以json嵌套的形式存储记录,张三的订单和李四的订单内容是单独例开的

3.在事务的差别

在sql数据库中,满足ACID(Atomicity原子性 Consistency一致性 Isolation隔离性 Durability持久性)理论

在nosql数据库中,只能满足基本的一致,即BASE理论

(二)redis简介

特征:

键值型数据存储

单线程,每条命令具备原子性,不受下一条命令入侵

低延迟,速度快(基于内存,IO多路复用)

支持数据持久化

支持主从集群、分片集群,即从节点可以备份主节点数据,主从节点可以做读写分离;分片,即数据拆分,存储到不同节点

支持多语言客户端

二、数据结构

key-value类型,key一般为string,但是value可以各种各样,包括string,hash,List,Set,SortedSet五种基本类型,BigMap,HyperLog,GEO三种特殊类型

三、命令

redis是通过命令行进行操作数据库的,对不同的类型数据的命令也不尽相同,在官网(https://redis.io/commands)可查看

四、Redis的Java客户端

(一)分类

1.Jedis

是以命令作为方法名称,所以简单使用,学习成本低。但是Jedis实例是线程不安全的,多线程下需要基于连接池来使用

2.Lettuce

是基于Netty实现的,支持同步、异步和响应式编程方式,而且线程安全的,支持redis的哨兵模式、集群模式和管道模式,推荐使用

Spring整合了Jedis和Lettuce为SpringDataRedis

(二)Jedis入门

1.引入依赖

进入Jedis官网查看自己jdk和redis版本适配的jedis版本,我jdk21

XML 复制代码
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>5.2.0</version>
</dependency>

2.建立连接

Jedis类是jedis客户端依赖中自带的类

3.测试String

4.释放资源

java 复制代码
package com.itheima.test;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import redis.clients.jedis.Jedis;

public class JedisTest {
    private Jedis jedis;

    @BeforeEach
    void setUp(){
        //1.建立连接
        jedis = new Jedis("127.0.0.1",6379);
        //2.设置密码
        jedis.auth("123456");
        //3.选择库
        jedis.select(0);
    }

    @Test
    void testString(){
        //存入数据
        String result = jedis.set("name", "虎哥");
        System.out.println("result = "+ result);
        //获取数据
        String name = jedis.get("name");
        System.out.println(
                "name = "+ name
        );
    }

    @AfterEach
    void tearDown(){
        //释放空间
        if(jedis != null){
            jedis.close();
        }
    }
}

(三)Jedis连接池

Jedis本身是线程不安全的,且频繁的创建和销毁连接会有性能损耗,推荐使用Jedis连接池代替Jedis直连的方式

创建连接池工厂:

java 复制代码
package com.itheima.jedis.util;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.time.Duration;

public class JedisConnectionFactory {

    private static final JedisPool jedisPool;

    static {
        //配置连接池
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(8);//最大连接数
        poolConfig.setMaxIdle(8);//最大空闲连接,即便没有人连接,池子里也可以预备这么多的连接,而不用重新建立
        poolConfig.setMinIdle(0);//最小空闲连接数,超过一段时间后如果连接一直没被人连接,则释放,直到最低值
        poolConfig.setMaxWait(Duration.ofMillis(1000));//等待时长
        //poolConfig.setMaxWaitMillis(1000); 该方法被遗弃,用Duration.of....标识时间

        //创建连接池对象
        jedisPool = new JedisPool(poolConfig,"127.0.0.1",6379,1000,"123456");
    }

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

然后在jedis连接类就可以修改建立连接的方法为获取连接池

java 复制代码
@BeforeEach
    void setUp(){
        //1.建立连接
//        jedis = new Jedis("127.0.0.1",6379);
        jedis = JedisConnectionFactory.getJedis();
        //2.设置密码
        jedis.auth("123456");
        //3.选择库
        jedis.select(0);
    }

(四)SpringDataRedis入门

根据spring.io官网的信息,目前最新正式版的SpringDataRedis为3.4.0

特点(简述)

对Jedis和Lettuce的整合,提供了RedisTemplate统一API来操作Redis,支持基于JDK、Json、字符串、Spring对象的数据序列化及反序列化,支持基于Redis的JDKCollection实现

(五)RedisTemplate工具类

在该工具类内封装了各种对Redis的操作,并将不同的数据类型的操作API封装到了不同的类型中:

1.引入依赖

使用idea自带的springboot的initializr,插件处勾选lombok和SpringDataRedis(Access+Driver)即可

然后引入commons-pool依赖,因为jedis和lettuce都基于这个池

XML 复制代码
     <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- 连接池依赖 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
    </dependencies>

2.配置文件

Crystal 复制代码
spring:
  application:
    name: RedisTemplateDemo
  data:
    redis:
      host: 127.0.0.1
      port: 6379
      password: 123456
      lettuce:
        pool:
          max-active: 8 #最大连接
          max-idle: 8 #最大空闲
          min-idle: 0 #最小空闲
          max-wait: 100 #连接等待时间,单位毫秒

3.注入RedisTemplate

4.编写测试

java 复制代码
@SpringBootTest
class RedisTemplateDemoApplicationTests {

    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    void contextLoads() {
        //写入一条String数据
        redisTemplate.opsForValue().set("name","Jack");
        // 获取String数据
        Object name = redisTemplate.opsForValue().get("name");
        System.out.println("name = "+ name);
    }

}

(六)RedisTemplate的序列化RedisSerializer

RedisTemplate可以接受任意Object作为值写入Redis,只不过写入前会把Object序列化为字节形式,默认是采用JDK序列化,得到的结果是OutputStream输出流形式,缺点是:

可读性差 内存占用较大

所以我们改变默认的序列化方法

有两种:

StringRedisSerializer 用于string

GenericJackson2JacksonRedisSerializer 用于其他值

1.自定义序列化方式

java 复制代码
package com.heima.redistemplatedemo.redis.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;


@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory connectionFactory){
        // 创建RedisTemplate对象
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        //设置连接工厂
        template.setConnectionFactory(connectionFactory);
        //创建Json序列化工具
        GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        //设置Key的序列化
        template.setKeySerializer(RedisSerializer.string());
        template.setHashKeySerializer(RedisSerializer.string());
        //设置Value的序列化
        template.setValueSerializer(jsonRedisSerializer);
        template.setHashValueSerializer(jsonRedisSerializer);
        //返回
        return template;
    }
}

2.通过自定义序列化方式存储中文字符串

java 复制代码
 @Test
    void contextLoads() {
        //写入一条String数据
        redisTemplate.opsForValue().set("name","虎哥");
        // 获取String数据
        Object name = redisTemplate.opsForValue().get("name");
        System.out.println("name = "+ name);
    }

3.通过自定义序列化方式存储对象

java 复制代码
    @Test
    void testSaveUser(){
        //写入数据
        redisTemplate.opsForValue().set("user:100",new User("虎哥",21));
        //获取数据
        User o = (User) redisTemplate.opsForValue().get("user:100");
        System.out.println("o = "+ o);
    }

4.序列化与反序列化------StringRedisTemplate类

用json序列化器存储数据,为了方便反序列化,会存储其类的class路径,这在数据量庞大时占用了大量内存

为了节省内存空间,我们并不会用json序列化器来处理Value,而是统一使用String序列化器,要求只存储String类型的key和value。当真的需要存储Java对象时,手动完成对象的序列化和反序列化

不过,好消息,Spring默认提供了一个StringRedisTemplate类,它的key和value序列化方式默认是String,省去了我们配置自定义RedisTemplate的时间

java 复制代码
package com.heima.redistemplatedemo;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.heima.redistemplatedemo.redis.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;

@SpringBootTest
class RedisStringTests {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Test
    void contextLoads() {
        //写入一条String数据
        stringRedisTemplate.opsForValue().set("name","虎哥");
        // 获取String数据
        Object name = stringRedisTemplate.opsForValue().get("name");
        System.out.println("name = "+ name);
    }


    //SpringMvc中默认使用的Json处理工具
    private  static final ObjectMapper mapper = new ObjectMapper();

    @Test
    void testSaveUser() throws JsonProcessingException {
        //创建对象
        User user = new User("虎哥",21);
        //手动序列化
        String json = mapper.writeValueAsString(user);
        //写入数据
        stringRedisTemplate.opsForValue().set("user:200",json);
        //获取数据
        String jsonUser = stringRedisTemplate.opsForValue().get("user:200");
        //手动反序列化
        mapper.readValue(jsonUser, User.class);//手动将该string按照User格式反序列化
        System.out.println("JsonUser = "+ jsonUser);
    }

}

以后可以通过手动打包手动序列化和反序列化的进程,进一步简化代码

相关推荐
python机器学习建模8 分钟前
科研论文必须要了解的25个学术网站
数据库
J.P.August1 小时前
Oracle DataGuard启动与关闭顺序
数据库·oracle
尚雷55801 小时前
Oracle 与 达梦 数据库 对比
数据库·oracle·达梦数据库
小猿姐3 小时前
Ape-DTS:开源 DTS 工具,助力自建 MySQL、PostgreSQL 迁移上云
数据库·mysql·postgresql·开源
百香果果ccc3 小时前
MySQL中的单行函数和聚合函数
数据库·mysql
Elastic 中国社区官方博客3 小时前
Elasticsearch Serverless 中的数据流自动分片
大数据·数据库·elasticsearch·搜索引擎·serverless·时序数据库
Minyy113 小时前
牛客网刷题SQL--高级查询
数据库·sql
秋意钟3 小时前
MySQL基本架构
数据库·mysql·架构
朱小勇本勇4 小时前
Qt实现控件拖曳
开发语言·数据库·qt