← Back to all posts

Redis基础篇

初识Redis

认识NoSQL

image-20230826191849828

SQL的全称是结构化查询语言(Structured Query Language),是一种用于关系型数据库的查询语言

NOSQL的全称是Not Only SQL,不限于SQL,也可以说是非关系型数据库,说明它于传统的SQL有所不同,而Redis正是一种NOSQL,接下来看一下两者的不同

SQLNOSQL 数据结构结构化(Structured)非结构化 数据关联关联的(Relational)无关联的 查询方式SQL查询非SQL 事务特性ACIDBASE 存储方式磁盘内存 拓展性垂直水平 使用场景1、数据结构固定
2、相关业务对数据安全性、一致性要求较高1、数据结构不固定
2、对一致性、安全性要求不高
3、对性能要求较高

NOSQL的非结构化类型主要有:

  • 键值类型(Redis)
  • 文档类型(MongoDB)
  • 列类型(Hbase)
  • Graph类型(Neo4j)
  • NOSQL没有统一的SQL语句

    认识Redis

    Redis诞生于2009年,全称是Remote Dictionary Server,远程词典服务器,是一个基于内存的键值型NoSQL数据库。

    特征:

  • 键值(key-value)型,value支持多种不同数据结构,功能丰富
  • 单线程,每个命令具备原子性
  • 低延迟,速度快(基于内存、IO多路复用、良好的编码)
  • 支持数据持久化
  • 支持主从集群、分片集群
  • 支持多语言客户端
  • 安装Redis

    这里简单讲述一下Linux中Redis的安装过程

    Redis的官方网站:https://redis.io/

    因为Redis是基于C语言编写的,因此需要安装Redis所需要的gcc依赖

    bash
    yum install -y gcc tcl

    在Redis官方网站下载好安装包,并上传到Linux上,目录看自己喜好,上传完成后进行解压

    bash
    tar -zxvf redis的文件名

    进入redis的安装目录

    bash
    cd 解压完成后的redis目录

    运行编译命令

    make是编译,make install是安装

    `make & make install`是编译并安装

    bash
    make & make install

    默认的安装路径就是在`/usr/local/bin`目录下

    该目录以及默认配置到环境变量,因此可以在任意目录下运行这些命令

  • redis-cli:redis提供的命令行客户端
  • redis-server:redis提供的服务端启动脚本
  • redis-sentinel:是redis的哨兵启动脚本
  • 默认启动

    bash
    redis-server

    启动后,你会发现你无法连接客户端,因为服务端已经建立连接了,如果你想连接客户端,你得重新打开一个页面建立客户端的连接,我们发现这样很麻烦,所以我们需要让它后台启动

    指定配置启动

    在我们之前解压的redis安装包下,有一个redis.conf的配置文件,我们先将这个文件备份一份

    bash
    cp redis.conf redis.conf.bck

    然后对redis.conf进行修改

    bash
    vi redis.conf

    Redis的常用配置

    properties
    # 监听的地址,默认是127.0.0.1,会导致只能在本地访问,修改为0.0.0.0可以在任意IP进行访问
    bind 0.0.0.0
    # 守护进程,修改为yes后即可在后台运行
    daemonize yes
    # 密码,设置后访问Redis必须输入密码
    requirepass 123456

    Redis的其他配置

    properties
    # 监听的端口
    port 6379
    # 工作目录,默认是当前目录,也就是运行redis-server时的命令,日志、持久化等文件会保存在这个目录
    dir .
    # 数据库数量,设置为1,代表只使用1个库,默认有16个库,编号为0~15
    databases 1
    # 设置redis能够使用的最大内存
    maxmemory 512mb
    # 日志文件,默认为空,不记录日志,可以指定日志文件名
    logfile "redis.log"

    指定配置文件启动,如果在redis-server命令所在的文件夹下启动的,则不需要指定,默认为当前目录下的redis.conf配置文件,如需指定,可使用下面的代码

    bash
    redis-server redis.conf

    查看redis进程

    bash
    ps -ef | grep redis

    停止redis进程

    bash
    kill -9 redis对应的进程号

    默认自启动

    Redis客户端

    Redis命令行客户端

    Redis安装完成后就自带了命令行客户端:redis-cli,使用方式如下

    bash
    redis-cli [options] [commonds]

    options是可选项,常见options有:

  • `-h 127.0.0.1`:指定要连接的redis节点的IP地址,默认是127.0.0.1
  • `-p 6379`:指定要连接的redis节点的端口,默认是6379
  • -a 123456:指定redis的访问密码
  • commonds是Redis的操作命令,例如:

    `ping`:与redis服务做连通测试,服务端正常会返回`pong`

    不指定commonds时,会进入`redis-cli`的交互控制台

    Redis图形化客户端

    Redis图形化客户端是一个GitHub上的大神出的,所以需要在GitHub上下载

    地址如下:https://github.com/MicrosoftArchive/redis/releases

    这里就不讲关于Redis图形化客户端的安装了,都很简单,我们讲讲如何使用

    image-20230827093318995

    打开后的页面如上图所示,我们单击`连接到Redis服务器`

    image-20230827093621171

    image-20230827093720046

    连接成功后一路确定即可

    image-20230827093906710

    添加键后的效果如下

    image-20230827093944301

    Redis常见命令

    Redis数据结构介绍

    Redis是一个key-value的数据库,key一般是String类型,value的类型多样

    image-20230827094756629

    学习Redis可以多看看Redis的官方文档:https://redis.io/commands/

    甚至你可以在Redis的命令行中使用help来查看帮助

    bash
    help

    Redis的通用命令

    KEYS

    一般是用来查找满足条件的key

    bash
    KEYS pattern

    示例:

    bash
    KEYS *

    查询所有的key

    image-20230827095911637

    一般都是根据pattern通配符来查找专门的key

    不建议在生产环境使用,因为Redis是单线程的,模糊查询很慢,如果数据量较大,一查可能会出现问题

    DEL

    删除一个指定的key

    废话不多说,直接上示例

    删除单个key

    image-20230827100250004

    删除多个key,中间用空格隔开

    image-20230827100415966

    EXISTS

    判断key是否存在

    EXISTS后面可以传递多个key,返回的是key存在的数量

    image-20230827100944335

    EXPIRE

    为key设置有效期,到期后key会被自动删除,设置的有效期一般为秒

    image-20230827101505382

    TTL

    查看key的有效时间,一般和EXPIRE联用

    bash
    TTL key

    使用TTL查看一个key的默认有效时间

    image-20230827101635387

    -1代表永久有效

    String类型

    String类型,也就是字符串类型,是Redis中最简单的存储类型

    其value是字符串,不过根据字符串的格式不同,又可以分为3类:

  • string:普通字符串
  • int:整数类型
  • float:浮点类型,可以做自增、自减操作
  • 不管哪种格式,底层都是字节数组形式存储,只不过编码方式不同。字符串类型的最大空间不能超过512m

    KeyValue msghello world num10 score66.6

    String类型的常见命令

    SET、GET

    set:添加或者修改已经存在的一个String类型的键值对

    get:根据key获取String类型的键值对

    image-20230827131504197

    MSET、MGET

    mset:批量添加多个String类型的键值对

    mget:根据多个key获取多个String类型的value

    image-20230827131727462

    INCR、INCRBY、INCRBYFLOAT

    incr:让一个整型的key自增1

    incrby:让一个整型的key自增,并指定步长,例如:incrby num 2,让num值自增2

    incrbyfloat:让一个浮点类型的数字自增并指定步长

    image-20230827132414507

    SETNX、SETEX

    setnx:添加一个String类型的键值对,前提是这个key不存在,否则不执行

    setex:添加一个String类型的键值对,并且指定有效期

    image-20230827132614979

    Key的层级格式

    Redis没有类似MySQL中的Table的概念,我们该如何区分不同类型的key呢?

    Redis的key允许有多个单词形成层级结构,多个单词之间用`:`隔开,格式如下:

    txt
    项目名:业务名:类型:id

    这个格式并非固定,也可以根据自己的需求来删除和添加词条

    例如我们的项目叫eastwind,有user和product两种不同类型的数据,我们可以这样定义key

  • user相关的key:eastwind:user:1
  • product相关的key:eastwind:product:1
  • 如果Value是一个Java对象,例如一个User对象,则可以将对象序列化为JSON字符串后存储:

    KEYVALUE eastwind:user:1{"id":1,"name":"Jack","age":21} eastwind:product:1{"id":1,"name":"小米x66","price":4999}

    测试一下层级

    image-20230827135124187

    添加以下代码后,来到redis的桌面端查看

    image-20230827135158442

    此时这里就有了层级关系

    Hash类型

    Hash类型,也叫散列,其value是一个无序字典,类似于Java中的HashMap结构

    String结构是将对象序列化为JSON字符串后存储,当需要修改对象某个字段时很不方便

    image-20230827142321008

    Hash结构可以将对象中的每个字段独立存储,可以针对单个字段做CRUD:

    image-20230827142353944

    Hash类型的常见命令

    HSET、HGET

    hset:添加或修改hash类型key的field的值

    hset hash名 字段名 值

    hget:获取一个hash类型key的field的值

    hget hash名 字段名

    image-20230827142618982

    HMSET、HMGET

    hmset:添加多个键值对

    hmget:获取多个键值对

    image-20230827143330348

    HGETALL、HKEYS、HVALS

    hgetall:获取一个hash类型中的所有字段和值

    hkeys:获取一个hash类型中所有的字段

    hvals:获取一个hash类型中所有的值

    image-20230827143953427

    HINCRBY

    hincrby:让一个hash类型的字段值自增并指定步长

    image-20230827144034484

    HSETNX

    hsetnx:添加一个hash类型的字段值,前提是该字段不存在,否则不执行

    image-20230827144125389

    List类型

    Redis中的List类型与Java中的LinkedList类似,可以看做是一个双向链表结构。既可以支持正向检索和也可以支持反向检索。

    特征也与LinkedList类似:

  • 有序
  • 元素可以重复
  • 插入和删除快
  • 查询速度一般
  • 常用来存储一个有序数据,例如:朋友圈点赞列表,评论列表等。

    关于左侧和右侧插入的情况,举出一个例子

    我们想插入值C,如果在左侧插入,那么就在A的前面,如果在右侧插入,就在B的后面
    A-B
    C-A-B
    A-B-C

    List类型的常见命令

    LPUSH

    向列表左侧插入一个或多个元素

    image-20230827144933737

    根据上面的例子,我们会依次插入name、123、jsda,都是左侧插入,所以插入顺序如下

    jsda-123-name

    image-20230827144944032

    LPOP

    lpop:移除并返回列表左侧的第一个元素,没有则返回nil

    image-20230827145219579

    RPUSH

    向列表右侧插入一个或多个元素

    image-20230827145457900

    右侧插入也是同理,我们这次只插入了一个age

    123-name-age

    image-20230827145528649

    LRANGE

    xxxxxxxxxx @Testvoid commonTest() {    //查看所有key(keys )    Set keys = redisTemplate.keys("");    for (String key : keys) {        System.out.println(key);   }    //查看是否存在指定key    System.out.println("----------------------------");    System.out.println(redisTemplate.hasKey("Random"));    System.out.println("----------------------------");    //删除指定key,并再次查看    redisTemplate.delete("myZset");    keys = redisTemplate.keys("*");    for (String key : keys) {        System.out.println(key);   }    System.out.println("----------------------------");    //输出指定key的类型    System.out.println(redisTemplate.type("tmp"));}java

    BLPOP、BRPOP

    与LPOP和RPOP类似,唯一不同是会在没有元素时等待指定时间,而不是直接返回nil

    Set

    Redis的Set结构与Java中的HashSet类似,可以看做是一个value为null的HashMap。因为也是一个hash表,因此具备与HashSet类似的特征:

  • 无序
  • 元素不可重复
  • 查找快
  • 支持交集、并集、差集等功能
  • Set类型常见命令

    SADD、SREM、SCARD

    sadd:向set中添加一个或多个元素

    不会重复

    image-20230827151033266

    srem:移除set中的指定元素

    image-20230827151130254

    image-20230827151139268

    scard:返回set中元素的个数

    image-20230827151155115

    SISMEMBER、SMEMBERS

    sismember:判断一个元素是否存在于set中

    smembers:获取set中的所有元素

    image-20230827151430246

    SINTER、SUNION、SDIFF

    sinter:求两个集合的交集

    sunion:求两个集合的并集

    sdiff:求两个集合的差集(补集)

    SortedSet

    Redis的SortedSet是一个可排序的set集合,与Java中的TreeSet有些类似,但底层数据结构却差别很大。SortedSet中的每一个元素都带有一个score属性,可以基于score属性对元素排序,底层的实现是一个跳表(SkipList)加 hash表。

    SortedSet具备下列特性:

  • 可排序
  • 元素不重复
  • 查询速度快
  • 因为SortedSet的可排序特性,经常被用来实现排行榜这样的功能。

    SortedSet的常见命令

    ZADD、ZREM

    zadd:添加一个或多个元素到sorted set,如果已经存在则更新其score值

    zrem:删除sorted set中的一个指定元素

    image-20230827152759717

    image-20230827152812548

    image-20230827152844811

    image-20230827152854442

    ZSCORE、ZRANK

    zscore:获取sorted set中指定元素的score值

    zrank:获取sorted set中的指定元素的排名,一般分数越高,排名越靠后

    image-20230827153031622

    ZCARD、ZCOUNT

    zcard:统计元素个数

    zcount:统计score值在给定范围内的所有元素的个数

    image-20230827153415587

    ZINCRBY

    让sorted set中的指定元素自增,步长为指定的值,添加的是score

    image-20230827153606740

    ZRANGE

    按照score排序后,获取指定范围内的元素,这里的范围代指索引,也可以称为排名

    image-20230827153718727

    ZRANGEBYSCORE

    按照score排序后,获取score范围内的元素,根据score来获取值

    image-20230827153927534

    ZDIFF、ZINTER、ZUNION

    求差集、交集、并集,跟set一致

    注意:所有的排名默认都是升序,如果要降序则在命令的Z后面添加REV即可,例如:

  • `升序`获取sorted set 中的指定元素的排名:ZRANK key member
  • `降序`获取sorted set 中的指定元素的排名:ZREVRANK key memeber
  • Redis的Java客户端

    Jedis

    快速入门

    新建一个maven工程

    引入依赖

    xml
    <!--jedis-->
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>3.7.0</version>
    </dependency>
    <!--单元测试-->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter</artifactId>
        <version>5.7.0</version>
        <scope>test</scope>
    </dependency>

    在test下新建Java类

    建立连接

    代码 (37 行)
    java
    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在测试类方法执行前所执行的方法
        @BeforeEach
        void setup(){
            // 1、建立连接
            jedis = new Jedis("127.0.0.1",6379);
            // 2、设置密码
            jedis.auth("123456");
            // 3、选择库
            jedis.select(0);
        }
    
        @AfterEach
        void tearDown() {
            // 关闭连接
            if (jedis != null)
                jedis.close();
        }
    
        @Test
        void test1(){
            // 存储数据
            String result = jedis.set("name", "zhangsan");
            System.out.println("result = " + result);
            // 获取数据
            String s = jedis.get("name");
            System.out.println("newName = " + s);
        }
    }

    结果如下

    报错是正常的,这个不用管

    image-20230827175632015

    接着测试一下其他的写法

    Hash

    java
    @Test
    void test2(){
        jedis.hset("user:1","name","zhangsan");
        jedis.hset("user:1","age","10");
        jedis.hset("user:1","score","99.9");
        Map<String, String> hgetAll = jedis.hgetAll("user:1");
        System.out.println(hgetAll);
    }

    image-20230827191620229

    其他的也是类似的,只要知道命令就会写了

    Jedis连接池

    Jedis本身是线程不安全的,并且频繁的创建和销毁连接会造成有性能损耗,因此我们推荐Jedis连接池代替Jedis的直连方式

    代码 (27 行)
    java
    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.JedisPool;
    import redis.clients.jedis.JedisPoolConfig;
    
    public class JedisConnectionFactory {
        private static final JedisPool jedisPool;
    
        static {
            // 配置连接池
            JedisPoolConfig poolConfig = new JedisPoolConfig();
            // 最大连接数
            poolConfig.setMaxTotal(8);
            // 设置最大空闲时间,预备8个池子,即使没人访问,依然有8个池子
            poolConfig.setMaxIdle(8);
            // 最少可以为0,即使没人用,也可以释放掉
            poolConfig.setMinIdle(0);
            // 设置等待时间为1秒,池子满了无法连接一秒后就报错
            poolConfig.setMaxWaitMillis(1000);
            // 创建连接池对象
            jedisPool = new JedisPool(poolConfig,"127.0.0.1",6379,1000,"123456");
        }
    
        public static Jedis getJedis(){
            return jedisPool.getResource();
        }
    }

    并修改JedisTest中的连接方法

    java
    // @BeforeEach在测试类方法执行前所执行的方法
    @BeforeEach
    void setup(){
        // 1、建立连接
        jedis = JedisConnectionFactory.getJedis();
        // 2、设置密码
        jedis.auth("123456");
        // 3、选择库
        jedis.select(0);
    }

    再次测试

    image-20230827193556729

    SpringDataRedis

    SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块就叫做SpringDataRedis

    官网地址:https://spring.io/projects/spring-data-redis

  • 提供了对不同Redis客户端的整合(Lettuce和Jedis)
  • 提供了RedisTemplate统一API来操作Redis
  • 支持Redis的发布订阅模型
  • 支持Redis哨兵和Redis集群
  • 支持基于Lettuce的响应式编程
  • 支持基于JDK、JSON、字符串、Spring对象的数据序列化及反序列化
  • 支持基于Redis的JDKCollection实现
  • SpringDataRedis中提供了RedisTemplate工具类,其中封装了各种对Redis的操作。并且将不同数据类型的操作API封装到了不同的类型中:

    image-20230827194234532

    快速入门

    创建一个Spring Boot项目

    引入依赖

    代码 (62 行)
    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.15</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>fun.eastwind</groupId>
        <artifactId>RedisDemo2</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>RedisDemo2</name>
        <description>RedisDemo2</description>
        <properties>
            <java.version>1.8</java.version>
        </properties>
        <dependencies>
            <!-- redis依赖 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
    
            <!-- common-pool依赖 -->
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-pool2</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>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <configuration>
                        <excludes>
                            <exclude>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok</artifactId>
                            </exclude>
                        </excludes>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    
    </project>

    配置application.yaml文件

    代码 (16 行)
    yaml
    spring:
      redis:
        host: 127.0.0.1
        port: 6379
        password: 123456
        lettuce:
          pool:
            # 最大连接数
            max-active: 8
            # 空闲时最大可连接数
            max-idle: 8
            # 空闲时最少可连接数
            min-idle: 0
            # 连接的最大等待时间
            max-wait: 100ms

    自动注入RedisTemplate并测试

    代码 (20 行)
    java
    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;
    
    @SpringBootTest
    class RedisDemo2ApplicationTests {
    
        @Autowired
        private RedisTemplate redisTemplate;
    
        @Test
        void contextLoads() {
            redisTemplate.opsForValue().set("name","zhangsan");
            String name = (String) redisTemplate.opsForValue().get("name");
            System.out.println("name = " + name);
        }
    
    }

    RedisTemplate的RedisSerializer(序列化器)

    为什么说序列化器呢,当你执行完刚刚的测试代码后,去Redis客户端中get这个name字段

    image-20230827200137337

    此时会发现是zhangsan,当你在Redis客户端后重新设置name,name会改变,而你在自己写的测试上运行后,再次get,依然是客户端上的值,这是怎么回事呢,我们keys *查看一下所有的key

    image-20230827200254513

    此时发现了一个很奇怪的东西,但不可否认的,这个key就是你刚刚set上去的name

    RedisTemplate可以接收任意Object作为值写入Redis

    只不过写入前会把Object序列化为字节形式,默认是采用JDK序列化,得到的结果是这样的

    `"\xAC\xED\x00\x05t\x00\x04name"`

    缺点:

  • 可读性差
  • 内存占用较大
  • 我们可以自定义RedisTemplate的序列化方式

    引入JackSon依赖

    xml
    <!--Jackson依赖-->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
    </dependency>

    编写配置类

    代码 (30 行)
    java
    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 RedisTemplateSerializer {
    
        @Bean
        public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
            // 创建RedisTemplate对象
            RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
            // 设置连接工厂
            redisTemplate.setConnectionFactory(connectionFactory);
            // 设置JSON序列化工具
            GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
            // 设置key的序列化
            redisTemplate.setKeySerializer(RedisSerializer.string());
            redisTemplate.setHashKeySerializer(RedisSerializer.string());
            // 设置value的序列化
            redisTemplate.setValueSerializer(jsonRedisSerializer);
            redisTemplate.setHashValueSerializer(jsonRedisSerializer);
            // 返回
            return redisTemplate;
    
        }
    }

    测试类

    代码 (20 行)
    java
    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;
    
    @SpringBootTest
    class RedisDemo2ApplicationTests {
    
        @Autowired
        private RedisTemplate<String,Object> redisTemplate;
    
        @Test
        void contextLoads() {
            redisTemplate.opsForValue().set("name","lisi");
            String name = (String) redisTemplate.opsForValue().get("name");
            System.out.println("name = " + name);
        }
    
    }

    image-20230827201822126

    此时就成功了,如果你存入对象的话,会自动转为json对象并存入

    StringRedisTemplate

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

    因为存入和读取时的序列化及反序列化都是我们自己实现的,SpringDataRedis就不会将class信息写入Redis了

    这种用法比较普遍,因此SpringDataRedis就提供了RedisTemplate的子类:StringRedisTemplate,它的key和value的序列化方式默认就是String方式。

    普通属性(非对象)

    代码 (21 行)
    java
    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 RedisDemo2ApplicationTests {
    
        @Autowired
        private StringRedisTemplate stringRedisTemplate;
    
        @Test
        void contextLoads() {
            stringRedisTemplate.opsForValue().set("name","lisi");
            String name = (String) stringRedisTemplate.opsForValue().get("name");
            System.out.println("name = " + name);
        }
    
    }

    对象(手动序列化)

    代码 (31 行)
    java
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.ObjectMapper;
    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 RedisDemo2ApplicationTests {
    
        @Autowired
        private StringRedisTemplate stringRedisTemplate;
    
        private static final ObjectMapper mapper = new ObjectMapper();
        @Test
        void contextLoads() throws JsonProcessingException {
            User zhangsan = new User("zhangsan", 66);
            // 手动序列化对象(将对象写成json)
            String value = mapper.writeValueAsString(zhangsan);
            // 写入数据
            stringRedisTemplate.opsForValue().set("user:1",value);
            // 获取数据
            String jsonUser = stringRedisTemplate.opsForValue().get("user:1");
            // 手动反序列化对象
            User user = mapper.readValue(jsonUser, User.class);
            System.out.println("user = " + user);
        }
    
    }

    优点:大大减少了字节码文件的空间

    image-20230827203329137

    关于其他的类型,其实都是类似的,这里也不再赘述了

    © 2025 EastWind. All rights reserved.