0%

Redis基础篇

  • 基础篇
    • 初识Redis
    • Redis常见命令
    • Redis的Java客户端

一、基础篇

1.1 初识Redis

1.1.1 认识NoSQL

  • NoSQL(Not only Structured Query Language),非结构型数据库,对数据库格式没有严格约束,往往形式松散,自由,数据库格式可以是 key-value,可以是文档,或者图格式。

  • NoSQL 和 SQL 的区别:

    1. 结构化和非结构化
      • 传统 SQL 结构型数据库是结构化数据,每一张表都有严格的约束信息:字段名、字段数据类型、字段约束等等信息,插入的数据必须遵守这些约束。
      • NoSql 非结构型数据库对数据库格式没有严格约束,往往形式松散,自由,数据库格式可以是 key-value,可以是文档,或者图格式。
    2. 关联和非关联
      • 传统数据库的表与表之间往往存在关联,例如外键。
      • NoSQL 数据库中的数据是无关联的。
    3. 查询方式
      • 传统关系型数据库基于 SQL 语句做查询,语法有统一标准。
      • 不同的非关系数据库查询语法差异极大,五花八门各种各样。
    4. 事务
      • 传统关系型数据库能满足事务 ACID 的原则。
      • 非关系型数据库往往不支持事务,或者不能严格保证 ACID 的特性,只能实现基本的一致性。

1.1.2 认识Redis

  • Redis(Remote dictionary server),远程词典服务器,是一个基于内存的键值型 NoSQL 数据库。

    Redis 的特征有以下几个:

    • 键值(key - value)型存储,value 支持多种不同数据结构,功能丰富。
    • 单线程,每个命令具备原子性。
    • 低延迟,速度快(基于内存、IO多路复用、良好的编码)。
    • 支持数据持久化(定期将内存搬运到磁盘)。
    • 支持主从集群、分片集群(数据拆分)。
    • 支持多语言客户端:Java、C、Python。

1.1.3 安装并启动Redis

  • Redis 作者只开发了 Redis 的 Linux 版本,所以我们要在虚拟机上安装 Redis,这里虚拟机选择 CentOS7 操作系统(CentOS 适合做服务器,因为它更加安全稳定)。

    1. Redis 是基于 C 编写的,所以需要先安装 Redis 所需的 gcc 依赖。

      1
      yum install -y gcc 
    2. 将 Redis 的安装包通过 WinSCP 上传到 /usr/local/src

    3. 在虚拟机的 /usr/local/src 目录下解压安装包:

      1
      tar -zxvf redis-6.2.6.tar.gz
    4. 进入 Redis 的目录:

      1
      cd redis-6.2.6/
    5. 运行编译命令进行安装:

      1
      [runoob@localhost redis-6.2.6]$ sudo make && make install
    6. 安装成功后,在 /usr/local/bin 目录下检查是否有 Redis,有则表示安装成功:

      1
      2
      3
      4
      5
      6
      7
      8
      [runoob@localhost bin]$ ls -l
      总用量 18904
      -rwxr-xr-x. 1 root root 4829512 3月 2 20:45 redis-benchmark
      lrwxrwxrwx. 1 root root 12 3月 2 20:45 redis-check-aof -> redis-server
      lrwxrwxrwx. 1 root root 12 3月 2 20:45 redis-check-rdb -> redis-server
      -rwxr-xr-x. 1 root root 5003792 3月 2 20:45 redis-cli
      lrwxrwxrwx. 1 root root 12 3月 2 20:45 redis-sentinel -> redis-server
      -rwxr-xr-x. 1 root root 9518920 3月 2 20:45 redis-server
    7. 为 Redis 配置环境变量:

      • 修改 ~/.bash_profile 文件,添加 Redis 的环境变量:

        1
        2
        export REDIS_HOME=/usr/local/bin
        export PATH=$PATH:$REDIS_HOME

        然后重启虚拟机。

    8. 接着就可以在任何目录下通过输入 redis-server 来启动 Redis 服务。

      • 但是这种启动属于前台启动,会阻塞整个会话窗口,窗口关闭或者按下 [CTRL+C] 才能让 Redis 停止,不推荐使用。
    9. 如果要让 Redis 以后台方式启动,则必须修改 Redis 的配置文件,就在我们之前解压的 Redis 目录下:/usr/local/src/redis-6.2.6,配置文件名称为 redis.conf

      • 先备份一份:sudo cp redis.conf redis.conf.bak
    10. 修改 redis.conf 配置文件:

    11. 根据所写的 Redis 配置文件启动 Redis:

      1
      [runoob@localhost redis-6.2.6]$ redis-server redis.conf
      • 可以看到,Redis 已经在后台启动了:

        1
        2
        3
        [runoob@localhost redis-6.2.6]$ ps -ef | grep redis
        runoob 2922 1 0 21:55 ? 00:00:00 redis-server 0.0.0.0:6379
        runoob 2945 2745 0 21:56 pts/0 00:00:00 grep --color=auto redis
  • 在启动 Redis 服务后,就可以通过客户端和 Redis 进行交互了,这里我们省略了 redis-cli 命令行客户端和图形化界面客户端的内容,后面直接用 Java 客户端与 Redis 进行交互。

1.2 ★★★Redis常见命令

1.2.1 Redis数据结构介绍

  • Redis 是一个 key-value 数据库,key 一般是 String 类型,不过 value 的类型多种多样,常见的 value 类型包括:

    • String
    • Hash
    • List
    • Set
    • SortedSet

    上面的类型都是 Redis 的基本类型。

    接下来,我们会分别介绍 Redis 的通用命令以及 Redis 基本类型相应的命令。

1.2.2 Redis命令-通用命令

  • KEYS pattern:查看符合 pattern 的所有 key。

    • KEYS * 表示查看所有 key。
    • KEYS a* 表示查看所有以 a 字母开头的 key。
    • KEYS a? 表示查看所有以 a 字母开头,总共两位字符的 key。

    不建议在生产环境设备上使用,因为是模糊查询,且 Redis 是单线程,当 key 的数量多了以后,执行该命令会阻塞,将无法进行其他命令,同时对 Redis 服务器也是巨大的负担。

  • DEL key [key ...]:删除指定的 key。

  • EXISTS key [key ...]:判断指定 key 是否存在。

  • EXPIRE key seconds:给一个 key 设置有效期,有效期到期时该 key 会被自动删除。

    • TTL key:查看一个 key 的剩余有效期
      • 不给 key 设置 EXPIRE 的话 TTL 返回值为 -1,表示该 key 永久有效。
      • 如果 key 失效了,TTL 返回值为 -2。

1.2.3 Redis命令-String类型

  • String 类型,也就是字符串类型,是 Redis 中最简单的存储类型,其 value 是字符串,不过根据字符串的格式不同,又可以分为 3 类:

    • string:普通字符串
    • int:整数类型,可以做自增、自减操作
    • float:浮点类型,可以做自增、自减操作
    KEYVALUE
    msghello world
    num10
    score9.5

    不管是哪种格式,底层都是字节数组形式存储,只不过编码方式不同。字符串类型的最大空间不能超过 512 MB。

  • String 类型的常见命令:

思考
  • Redis 中没有类似 MySQL 中的 Table 的概念,所有的数据存储在一起,那我们该如何区分不同类型的 key 呢?
    • 例如,需要存储用户、商品信息到 redis,有一个用户 id 是 1,有一个商品 id 恰好也是 1。那 SET id 1 存储的究竟是用户的 id,还是商品的 id 呢?
      • 所以我们要用到 Redis 的 key 的层级格式
★key的层级格式
  • Redis 的 key 允许有多个单词形成层级结构,多个单词之间用 : 隔开,格式如下:

    • 项目名:业务名:类型:id
      • 这个格式并非固定,也可以根据自己的需求来删除或添加词条。
  • 回到 “思考” 中的问题,假如我们的项目名称为 redis,有 user 和 product 两种不同类型的数据,则我们可以这样定义 key:

    • redis:user:1

    • redis:product:1

    • 一旦我们在 Redis 中采用这样的方式存储数据,那么在可视化界面中,redis 会以层级结构来对数据进行存储,形成类似于这样的结构,更加方便 Redis 获取数据:

1.2.4 Redis命令-Hash类型

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

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

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

  • Hash 类型的常见命令:

1.2.5 Redis命令-List类型

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

    特征也与 LinkedList 类似:

    • 有序
    • 元素可以重复
    • 插入和删除快
    • 查询速度一般

    常用来存储一个有序数据,例如:朋友圈点赞列表,评论列表等。

  • List 类型的常见命令:

1.2.6 Redis命令-Set类型

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

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

1.2.7 Redis命令-SortedSet类型

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

    • 可排序
    • 元素不重复
    • 查询速度快

    因为 SortedSet 的可排序特性,经常被用来实现排行榜这样的功能。

  • SortedSet 类型的常见命令:

1.3 Redis的Java客户端

  • 目前 Redis 主流的 Java 客户端包括:

    • Jedis:以 Redis 命令作为方法名称,学习成本低,简单实用。但是 Jedis 实例是线程不安全的,多线程环境下需要基
      于连接池来使用。
    • Lettuce:Lettuce 是基于 Netty 实现的,支持同步、异步和响应式编程方式,并且是线程安全的。支持 Redis 的哨兵
      模式、集群模式和管道模式。
    • Redission:Redisson 是一个基于 Redis 实现的分布式、可伸缩的 Java 数据结构集合。包含了诸如 Map、Queue、Lock、Semaphore、AtomicLong 等强大功能,用于分布式环境中。

    Spring Data Redis 底层兼容了 JedisLettuce,所以我们重点学习它,不过有些公司也仍在使用 Jedis,所以也要学习一下 Jedis

1.3.1 Jedis

  • 使用 Jedis 的步骤:

    1. 使用 maven 创建新模块 jedis-demo,设置相应内容:

    2. pom.xml 文件中导入 jedis 的依赖:

      1
      2
      3
      4
      5
      6
      <!--jedis依赖-->
      <dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
      <version>3.7.0</version>
      </dependency>
    3. 建立连接。

    4. 使用 jedis 操作 Redis 数据库。

    5. 释放资源。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      package com.f.redis;

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

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

      /**
      * @author fzy
      * @date 2024/3/4 21:03
      */
      public class JedisTest {
      private Jedis jedis;

      @BeforeEach // 表示在当前类中的每个@Test方法之前执行该注解方法
      public void setUp() {
      // 1.建立连接
      jedis = new Jedis("192.168.44.130", 6379);
      // 2.设置密码
      jedis.auth("123456");
      // 3.选择库
      jedis.select(0);
      }

      @Test
      public void test() {
      Map<String, String> map = new HashMap<>();
      map.put("id", "1");
      map.put("name", "jack");
      map.put("age", "18");
      jedis.hmset("redis:user:1", map);
      Map<String, String> data = jedis.hgetAll("redis:user:1");
      System.out.println(data);
      }

      @AfterEach // 表示在当前类中的每个@Test方法之后执行该注解方法
      public void tearDown() {
      if (jedis != null) {
      jedis.close();
      }
      }
      }
Jedis连接池
  • Jedis 本身是线程不安全的,并且频繁地创建和销毁连接会有性能损耗,因此推荐使用 Jedis 连接池代替 Jedis 的直连方式。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    package com.f.redis.util;

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

    /**
    * @author fzy
    * @date 2024/3/4 21:53
    */
    public class JedisConnectFactory {
    private static final JedisPool jedisPool;

    static {
    // 配置连接池
    JedisPoolConfig poolConfig = new JedisPoolConfig();
    poolConfig.setMaxTotal(8);
    poolConfig.setMaxIdle(8);
    poolConfig.setMinIdle(0);
    poolConfig.setMaxWaitMillis(1000);
    jedisPool = new JedisPool(poolConfig, "192.168.44.130", 6379, 1000, "123456");
    }

    public static Jedis getJedis() {
    return jedisPool.getResource();
    }
    }
    1
    2
    3
    4
    5
    @BeforeEach
    void setUp() {
    jedis = JedisConnectFactory.getJedis();
    jedis.select(0);
    }

1.3.2 ★★★Spring Data Redis

  • SpringData 是 Spring 中数据操作的模块,包含对各种数据库的集成,其中对 Redis 的集成模块就叫做 SpringDataRedis,官网地址:Spring Data Redis
    • 提供了对不同 Redis 客户端的整合(Lettuce 和 Jedis)
    • 提供了 RedisTemplate 统一 API 来操作 Redis
    • 支持 Redis 的发布订阅模型
    • 支持 Redis 哨兵和 Redis 集群
    • 支持基于 Lettuce 的响应式编程
    • 支持基于JDK、JSON、字符串、Spring对象的数据序列化及反序列化
    • 支持基于 Redis 的 JDKCollection 实现
RedisTemplate
  • SpringDataRedis 中提供了 RedisTemplate 工具类,其中封装了各种对 Redis 的操作,并且将不同数据类型的操作 API 封装到了不同的类型中
1.3.2.1 在 springboot 中使用 Spring Data Redis
  • 在 springboot 中使用 Spring Data Redis:

    1. 新建 spring-data-redis-demo 模块,使用 Spring Initializr 初始化 springboot 项目,设置相关内容:

    2. 在技术集中勾选 Spring Data Redis,另外勾选 Lombok,用于实体类:

    3. 配置 pom.xml 文件,除了前面导入的 spring-boot-starter-data-redis 依赖之外,还要引入 commons-pool2 连接池依赖:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      <!--Spring Data Redis依赖-->
      <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis</artifactId>
      </dependency>
      <!--连接池依赖-->
      <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-pool2</artifactId>
      </dependency>
    4. 编辑 application.yml 文件,配置 Redis 的相关信息:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      spring:
      data:
      redis:
      host: 192.168.44.130
      port: 6379
      password: 123456
      database: 0
      # springboot默认使用lettuce,如果要使用jedis,需要引入jedis的依赖
      lettuce:
      pool:
      max-active: 8
      max-idle: 8
      min-idle: 0
      max-wait: 1000
    5. 注入 RedisTemplate

      1
      2
      @Autowired
      private RedisTemplate redisTemplate;
    6. RedisTemplate 的方法进行测试:

      1
      2
      3
      4
      5
      6
      7
      8
      @Test
      public void testString() {
      // 写入一条String数据
      redisTemplate.opsForValue().set("name", "jack");
      // 读取String数据
      String name = redisTemplate.opsForValue().get("name").toString();
      System.out.println(name);
      }
1.3.2.2 自定义RedisTemplate的RedisSerializer
  • 在前面的例子中,由于 redisTemplate.opsForValue()set 方法的参数是泛型:void set(K key, V value);,没有指定 KV 的话就是 Object 类型,所以存储在 Redis 服务器中的数值是这样的:

    1
    2
    3
    4
    127.0.0.1:6379> KEYS *
    1) "\xac\xed\x00\x05t\x00\x04name"
    127.0.0.1:6379> GET "\xac\xed\x00\x05t\x00\x04name"
    "\xac\xed\x00\x05t\x00\x04jack"
    • 亦即:我们存入 Redis 服务器的键和值都是 Java 对象,会被 RedisTemplate 底层的默认序列化方法:JDK 序列化工具 JdkSerializationRedisSerializer 序列化。

      JdkSerializationRedisSerializer 采用的是 ObjectOutputStream(把 Java 对象转成字节)来进行序列化,所以最终存储在 Redis 服务器中的数值就显示成这样了。

    • 这种默认的序列化方式有以下几个缺点:

      • 可读性差
      • 内存占用大
  • 为了解决这个问题,我们需要初始化 RedisTemplateRedisSerializer

    • RedisTemplate 有以下几个主要的 RedisSerializer
      • private @Nullable RedisSerializer keySerializer = null;
      • private @Nullable RedisSerializer valueSerializer = null;
      • private @Nullable RedisSerializer hashKeySerializer = null;
      • private @Nullable RedisSerializer hashValueSerializer = null;
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    package com.f.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;

    /**
    * @author fzy
    * @date 2024/3/5 13:56
    */
    @Configuration
    public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
    // 1.创建RedisTemplate对象
    // key一般是String类型,value一般是Object类型
    RedisTemplate<String, Object> template = new RedisTemplate<>();
    // 2.设置连接工厂
    template.setConnectionFactory(factory);
    // 3.创建JSON序列化工具
    GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
    // 4.设置Key的序列化
    template.setKeySerializer(RedisSerializer.string());
    template.setHashKeySerializer(RedisSerializer.string());
    // 5.设置Value的序列化
    template.setValueSerializer(jsonRedisSerializer);
    template.setHashValueSerializer(jsonRedisSerializer);
    // 6.返回RedisTemplate对象
    return template;
    }
    }
    • 然后重新注入 RedisTemplate 对象:

      1
      2
      @Autowired
      private RedisTemplate<String, Object> redisTemplate;

      进行测试:

      1
      2
      3
      4
      5
      6
      7
      8
      @Test
      public void testString() {
      // 写入一条String数据
      redisTemplate.opsForValue().set("name", "jack");
      // 读取String数据
      String name = redisTemplate.opsForValue().get("name").toString();
      System.out.println(name);
      }
      • 可以看到存储在 Redis 服务器中的数值是这样的:

        1
        2
        3
        4
        127.0.0.1:6379> KEYS *
        1) "name"
        127.0.0.1:6379> GET name
        "\"jack\""

        是我们想看到的效果。

  • 因为我们对 Value 的序列化是 JSON 序列化,所以可以测试 Value 值为 pojo 对象时,Redis 服务器中数值的样子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @Test
    public void testJson() {
    User user1 = new User();
    user1.setId(1);
    user1.setName("tom");
    user1.setAge(18);
    redisTemplate.opsForValue().set("redis:user:1", user1);
    User result = (User) redisTemplate.opsForValue().get("redis:user:1");
    System.out.println(result); // User(id=1, name=tom, age=18)
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    package com.f.redis.pojo;

    import lombok.Data;

    /**
    * @author fzy
    * @date 2024/3/5 14:39
    */
    @Data
    public class User {
    private int id;
    private String name;
    private int age;
    }
    • 可以看到存储在 Redis 服务器中的数值是这样的:

      1
      2
      3
      4
      127.0.0.1:6379> KEYS *
      1) "redis:user:1"
      127.0.0.1:6379> GET redis:user:1
      "{\"@class\":\"com.f.redis.pojo.User\",\"id\":1,\"name\":\"tom\",\"age\":18}"
      • 注意:在 RedisConfig 类中对 valueSerializer 进行设置后,RedisTemplate 在将 Java 对象存储到 Redis 服务器中时,会将 Java 对象序列化为 JSON 数据;同理,RedisTemplate 在将 JSON 数据从 Redis 服务器中取出到 Java 内存中时,会将 JSON 数据反序列化为 Java 对象
1.3.2.3 StringRedisTemplate
  • 尽管 JSON 的序列化方式可以满足我们的需求,但依然存在一些问题,例如:

    1
    2
    127.0.0.1:6379> GET redis:user:1
    "{\"@class\":\"com.f.redis.pojo.User\",\"id\":1,\"name\":\"tom\",\"age\":18}"

    为了在反序列化的时候知道对象的类型,JSON 序列化器在序列化时会将类的 class 类型写入 json 结果中,并存入Redis,这会带来额外的内存开销。

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

Spring 默认提供了一个 StringRedisTemplate 类,它的 keyvalue 的序列化方式默认就是 String 方式,省去了我们自定义 RedisTemplate 的过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.f.redis;

import com.f.redis.pojo.User;
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.StringRedisTemplate;

/**
* @author fzy
* @date 2024/3/5 18:14
*/
@SpringBootTest
public class StringRedisTemplateTest {
@Autowired
private StringRedisTemplate stringRedisTemplate;
//JSON工具类ObjectMapper,或者可以用fastjson:JSON.toJSONString(), JSON.parseObject()
private static final ObjectMapper MAPPER = new ObjectMapper();

@Test
void testStringRedisTemplate() throws JsonProcessingException {
User user1 = new User();
user1.setId(1);
user1.setName("tom");
user1.setAge(18);
// 手动序列化
String user1Json = MAPPER.writeValueAsString(user1);
stringRedisTemplate.opsForValue().set("redis:user:1", user1Json);
// 手动反序列化
User result = MAPPER.readValue(stringRedisTemplate.opsForValue().get("redis:user:1"), User.class);
System.out.println(result);
}
}
  • 然后再看 Redis 服务器的数据:

    1
    2
    3
    4
    127.0.0.1:6379> KEYS *
    1) "redis:user:1"
    127.0.0.1:6379> GET redis:user:1
    "{\"id\":1,\"name\":\"tom\",\"age\":18}"

    已经没有 @class 的数据了。

1.3.2.4 RedisTemplate操作Hash类型
  • RedisTemplate 操作 Hash 类型的数据的方法名,和 Redis 本身的命令不尽相同,有所差别:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    @Test
    void testHash() {
    // HSET <-> put
    stringRedisTemplate.opsForHash().put("redis:user:1", "id", "1");
    Map<String, String> map = new HashMap<>();
    map.put("name", "zhangsan");
    map.put("age", "18");
    // HMSET <-> putAll
    stringRedisTemplate.opsForHash().putAll("redis:user:1", map);
    // HGET <-> get
    String name = stringRedisTemplate.opsForHash().get("redis:user:1", "name").toString();
    System.out.println(name);
    // HMGET <-> multiGet
    List list = new ArrayList<>();
    list.add("id");
    list.add("age");
    List<Object> values = stringRedisTemplate.opsForHash().multiGet("redis:user:1", list);
    values.forEach(value -> {
    System.out.println(value);
    });
    }
---------------The End---------------