SpringBoot集成Redis

1.Redis介绍

作为数据库,Redis是一个非常快的非关系数据库(Non-Relational Database),它可以存储键(key)与五种不同类型的值之间的映射,可以将存储在内的键值对数据持久化到硬盘,可以使用复制特性来扩展读性能,还可以使用客户端分片来扩展写性能。

1.1数据类型

Redis数据类型不仅与关系数据库管理系统(RDBMS)不同,也不同于任何简单的NoSQL键值数据存储。Redis数据类型类似于编程语言的基础数据类型,因此开发人员感觉很自然,每个数据类型都支持适用于其类型的操作,受支持的数据类型包括:

  • String(字符串)
  • Hash(哈希)
  • List(列表)
  • Set(集合)
  • Zset(Sorted Set:有序集合)

1.2关键优势

Redis的优势包括速度、对富数据类型支持、操作的原子性、以及通用性等一些优势,以下是一一列举的Redis优势:

  • 速度快‌:Redis使用内存存储数据,避免了磁盘I/O操作,读写速度非常快。
  • 丰富的数据类型‌:支持多种数据类型,如字符串、哈希、列表、集合和有序集合等。
  • 原子性和事务处理‌:Redis的命令是原子的,支持事务处理,保证一组命令的原子性执行。
  • 持久化机制‌:支持‌RDB和‌AOF两种持久化机制,确保数据的可靠性和持久存储。
  • 发布/订阅功能‌:支持发布/订阅功能,适用于消息队列和实时推送等应用。
  • Lua脚本‌:支持Lua脚本,可以在服务器端执行一段脚本。
  • 分布式支持‌:支持分布式模式,可以多个Redis实例组成一个集群,实现数据的垂直和水平切分。
  • 简单易用‌:具有简洁的命令接口,易于使用和管理。
Redis的高性能机制
  • 高效的‌数据结构‌:为不同的数据类型提供了专门优化的数据结构,如‌SDS、双向链表、压缩列表等。
  • 单线程模型‌:内部使用单线程模型处理命令,避免了多线程竞争和锁的开销。
  • I/O多路复用‌:使用I/O多路复用技术,高效地管理多个网络连接。
  • 高效的‌网络库‌:使用专门优化的网络库,提供低延迟和高吞吐量的网络通信能力。

2.Redis基本使用

1.安装

下载地址:https://github.com/microsoftarchive/redis/releases

2.配置Redis服务(Windows特有)

进入Redis目录,在这你下载的redis包输入命令提示符(cmd)窗口。

执行以下命令来安装Redis服务(需要redis-server.exe和redis.windows.conf文件):

redis-server.exe --service-install redis.windows.conf --loglevel verbose

–service-install:表示安装服务。
redis.windows.conf:是配置文件的路径。
–loglevel verbose:设置日志级别为详细。
安装成功后,你可以通过Windows的服务管理器来修改Redis服务的登录身份

3. 启动Redis服务

通过命令提示符窗口,执行以下命令来启动Redis服务:

`redis-server --service-start`

–service-start:表示启动服务。

4. 连接到Redis

使用redis-cli命令连接到Redis服务器。在命令行中输入:

redis-cli.exe -h 127.0.0.1 -p 6379 -a foobared
5. 注意事项和常用命令

如果想方便地使用Redis命令,可以将Redis的路径添加到系统的环境变量中。
Redis的常用命令包括SET、GET、LPUSH、RPUSH、HSET、HGET等,用于操作Redis中的字符串、列表、哈希等数据结构。
Redis还支持事务操作,可以将多个命令打包成一个事务进行执行。
Redis支持两种持久化方式:RDB(Redis Database)和AOF(Append Only File)。可以通过配置文件来选择使用哪种持久化方式,或者同时使用两种方式。

如果需要停止Redis服务,可以通过命令提示符窗口执行以下命令:

redis-server --service-stop

3.Jedis操作Redis

Jedis的基本使用非常简单,只需要创建Jedis对象的时候指定host,port,password即可。

Jedis有很多构造方法,都大同小异,只是对应和Redis连接的socket的参数不一样而已。

3.1常用方法API

在Jedis库中,Jedis类就代表了与Redis服务器连接,因此对服务器的操作都是通过它来进行,Redis的各种操作命令在Jedis类中也直接体现为同名的方法。

Jedis对象常用方法的API,包括对键操作、字符串操作、整数和浮点数操作、列表操作、集合操作、哈希操作、有序集合操作、排序操作等几大类,由于篇幅限制。

3.2Jedis常用API

一、引入Jedis包

二、创建Jedis对象

Jedis jedis = new Jedis(String ip, Dtring port);

三、键操作

清空数据jedis .flushDB()
判断某个键是否存在boolean  jedis .exists(String key)
新增键值对(key,value)jedis.set(String key, String value)
获取所有keySet<String>jedis.keys("*")
删除键为key的数据项jedis.del(String key)
设置键为key的过期时间为i秒jedis.expire(String key, int i)
获取键为key数据项的剩余生存时间(秒)int jedis .ttl(String key)
移除键为key属性项的生存时间限制jedis.persist(String key)
查看键为key所对应value的数据类型jedis.type(String key)

3.3基本操作

1.添加jedis依赖:
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
2.编写junjt单元测试
@Before
    public void setup() {
        jedis = new Jedis("127.0.0.1", 6379);
        jedis.auth("密码");
    }

操作字符串:

 @Test
    public void testString() {
        jedis.set("name", "ktjiaoyu"); //设置键值对
        System.out.println(jedis.get("name"));

        jedis.append("name", "czkt"); //在键值对的值后追加
        System.out.println(jedis.get("name"));

        jedis.del("name"); //删除键值对
        System.out.println(jedis.get("name"));

        jedis.mset("name", "ktjiaoyu", "age", "18", "add", "cz"); //设置多个键值对
        jedis.incr("age"); //对键值对的值进行加1操作
        System.out.println(jedis.mget("name", "age", "add")); //获取多个键值对的值
    }

3.4连接池

在我们使用过程中,不会在每次使用时都创建Jedis对象,一般会使用连接池,并提供一个工具类来对外使用。

使用连接池的好处:

  1. 效率更高;
  2. 线程安全;

连接池:

public final class RedisPool {
    //Redis服务器IP地址
    private static String ADDR = "127.0.0.1";
    //Redis的端口号
    private static int PORT = 6379;
    //访问密码
    private static String AUTH = "密码";
    //可用连接实例的最大数目,默认值为8;
    //如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。
    private static int MAX_ACTIVE = 1024;
    //控制一个pool最多有多少个状态为idle(空闲的)的jedis实例,默认值也是8。
    private static int MAX_IDLE = 200;
    //等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException;
    private static int MAX_WAIT = 10000;
    private static int TIMEOUT = 10000;
    //在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;
    private static boolean TEST_ON_BORROW = true;
    private static JedisPool jedisPool = null;

    /**
     * 初始化Redis连接池
     */
    static {
        try {
            JedisPoolConfig config = new JedisPoolConfig();
            config.setMaxTotal(MAX_ACTIVE);
            config.setMaxIdle(MAX_IDLE);
            config.setMaxWaitMillis(MAX_WAIT);
            config.setTestOnBorrow(TEST_ON_BORROW);
            jedisPool = new JedisPool(config, ADDR, PORT, TIMEOUT, AUTH);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取Jedis实例
     *
     * @return
     */
    public synchronized static Jedis getJedis() {
        try {
            if (jedisPool != null) {
                Jedis resource = jedisPool.getResource();
                return resource;
            } else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    /**
     * 释放jedis资源
     *
     * @param jedis
     */
    public static void returnResource(final Jedis jedis) {
        if (jedis != null) {
            jedisPool.returnResource(jedis);
        }
    }
}

工具类:

public class RedisUtil {
    /**
     * 设置key的有效期时间,单位是秒
     */
    public static Long expire(String key, int exTime) {
        Jedis jedis = null;
        Long result = null;
        try {
            // 从连接池中获取 jedis 对象
            jedis = RedisPool.getJedis();
           //设置成功则返回Jedis对象
            result = jedis.expire(key, exTime);
        } catch (Exception e) {
            e.printStackTrace();
            return result;
        } finally {
            RedisPool.returnResource(jedis);
        }
        return result;
    }


    //exTime单位是秒
    //设置key-value并且设置超时时间
    public static String setEx(String key, String value, int exTime) {
        Jedis jedis = null;
        String result = null;
        try {
            jedis = RedisPool.getJedis();
            result = jedis.setex(key, exTime, value);
        } catch (Exception e) {
            e.printStackTrace();
            return result;
        } finally {
            RedisPool.returnResource(jedis);
        }
        return result;
    }

    public static String get(String key) {
        Jedis jedis = null;
        String result = null;
        try {
            jedis = RedisPool.getJedis();
            result = jedis.get(key);
        } catch (Exception e) {
            e.printStackTrace();
            return result;
        } finally {
            RedisPool.returnResource(jedis);
        }
        return result;
    }



    public static Long del(String key) {
        Jedis jedis = null;
        Long result = null;
        try {
            jedis = RedisPool.getJedis();
            result = jedis.del(key);
        } catch (Exception e) {
            e.printStackTrace();
            return result;
        } finally {
            RedisPool.returnResource(jedis);
        }
        return result;
    }
}

4.Spring操作Redis

4.1spring-boot-sstarter-data-redis

Spring Boot 提供了对 Redis 集成的组件包:spring-boot-starter-data-redis,它依赖于spring-data-redis 和 lettuce。Spring Boot 1.0 默认使用的是 Jedis 客户端,2.0 替换成了 Letuce但如果你从SpringBoot1.5X切换过来,几乎感受不大差异,这是因为spring-boot-starter-data-redis 为我们隔离了其中的差异性。

  • Lettuce:是一个可伸缩线程安全的Redis 客户端,多个线程可以共享同一个RedisConnection,它利用优秀NettyNI0 框架来高效地管理多个连接。
  • Spring Data:是 Spring 框架中的一个主要项目,目的是为了简化构建基于 Spring 框架应用的数据访问,包括非关系数据库、Map-Reduce 框架、云数据服务等,另外也包含对关系数据库的访问支持。
  • Spring Data Redis:是 Spring Data 项目中的一个主要模块,实现了对 Redis 客户端 AP的高度封装,使对Redis的操作更加便捷。

因此 Spring Data Redis 和 Lettuce 具备的功能,spring-boot-starter-data-redis 几乎都会有。

4.2基本操作
1.添加依赖
        <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>

引入commons-pool2是因为Lettuce需要使用commons-pool2创建Redis连接池

2.application.yml配置相关信息
  #  Redis配置
  data:
    redis:
      host: 127.0.0.1
      port: 6379
      password: 密码
      database: 0
      lettuce:
        pool:
#          连接池最大连接数(使用负值表示没有限制): 8
          max-active: 8
          # 连接池最大阻塞等待时间(使用负值表示没有限制)默认为-1
          max-wait: -1
          # 连接池中的最大空闲连接 默认为8
          max-idle: 8
          # 连接池中的最小空闲连接 默认为0
          min-idle: 0

StringRedisTemplateRedisTemplate的主要区别在于序列化策略、数据类型支持、以及使用场景。

序列化策略‌:
  • StringRedisTemplate默认采用String的序列化策略,保存的key和value都是采用此策略序列化保存的。这意味着StringRedisTemplate显示的是原文,即存入什么就显示什么,适用于存储字符串类型的数据。
  •  RedisTemplate默认采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。RedisTemplate显示的是字节数组,即存入数据时,先序列化为字节数组,再存入Redis数据库。这种序列化策略使得RedisTemplate处理数据范围更广,适用于存储复杂对象,如果不想额外处理数据,最好使用RedisTemplate
数据类型支持‌:
  • StringRedisTemplate专门用于操作字符串类型的数据,其泛型参数固定为<String,String>,表示键值都是字符串类型的数据。
  • RedisTemplate是泛型类,通过指定泛型参数可以让RedisTemplate支持各种数据类型的操作。它支持Redis的五种数据类型:字符串、列表、集合、有序集合、散列,并且提供了对这五种数据类型的操作方法。
使用场景‌:
  • StringRedisTemplate要求存入类型为String,否则会报类型转化异常,适用于需要直接操作字符串数据的情况。
  • RedisTemplate在存入复杂对象时更为灵活,如果不想额外处理数据,可以直接使用RedisTemplate进行操作。它还支持批量插入和删除,可以一次性执行多个命令,适用于需要处理复杂数据类型或批量操作的场景。

RedisTemplate中定义了5种数据结构操作:

    RedisTemplate.opsForValue();   //操作字符串数据
    RedisTemplate.opsForHash();    //操作hash数据
    RedisTemplate.opsForList();    //操作list数据
    RedisTemplate.opsForSet();     //操作set数据
    RedisTemplate.opsForZSet();    //操作有序set数据
1.操作字符串:
   @Test
    public void testStrings() {
        stringRedisTemplate.opsForValue().set("name", "czkt"); //设置键值对
        Assert.assertEquals("czkt", stringRedisTemplate.opsForValue().get("name")); //获取键值对的值
    }

我们使用StringRedisTemplate存储了一个字符串"czkt",存储之后获取进行验证,多次进行set相同的key,键对应的值会被覆盖。

2.操作实体
 @Test
    public void testobj() {
        User user = new User("czkt", "123456", 1, null);
        ValueOperations<String, User> operations = redisTemplate.opsForValue();
        operations.set("ktjiaoyu.crm.user.czkt", user);
        User u = operations.get("ktjiaoyu.crm.user.czkt");
        System.out.println("user.usrName:" + u.getUsrName());
    }

输出结果:user.usrName:czkt

验证发现完美支持对象的存入和读取

3.超时失效:

Redis在存入每一个数据的时候都可以设置一个超时时间,过了这个时间就会自动删除数据,这种特性非常适合我们对阶段数据的缓存。

 @Test
    public void testExpire() throws InterruptedException {
        User user = new User("czkt", "123456", 1, null);
        ValueOperations<String, User> operations = redisTemplate.opsForValue();
        operations.set("ktjiaoyu.crm.user.czkt", user, 100, TimeUnit.SECONDS);
        Thread.sleep(1000);
        boolean exists = redisTemplate.hasKey("expire");
        if (exists) {
            System.out.println("exists is true");
        } else {
            System.out.println("exists is false");
        }
    }

从结果看出来,Redis中已经不存在User对象了,此数据已经过期,同时我们在这个测试的方法中使用haskey("expire")方法,可以判断key是否存在。

4.操作哈希

一般我们存储一个键,会很自然的就会使用get/set去存储,实际上这并不是很好的做法。

Redis存储一个key会有一个最小内存,不管你存的这个键多小,都不会低于这个内存,因此合理使用Hash可以帮我们节省很多内存。

Hash Set就在哈希表key中域的值设为value。如果key不存在,一个新的哈希表被创建并进行Hset操作;如果域已经存在于哈希表中,旧值将被覆盖。

 @Test
    public void testHash() {
        HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
        hash.put("hash", "name", "ktjiaoyu");
        String value = (String) hash.get("hash", "name");
        System.out.println("hash name'value:" + value);
    }

根据上面测试用例发现,Hashset 的时候需要传入三个参数,第一个为 key,第二个为 Field,第三个为存储的值。一般情况下 Key代表一组数据,Field 为 key 相关的属性,而 value 就是属性对应的值。

5.操作列表

Redis List的应用场景非常多,也是Redis最重要的数据结构之一。使用List可以轻松的实现一个队列,List典型的应用场景就是消息队列,可以利用List的Push 操作,将任务存在的中,然后工作线程再用 POP操作将任务取出进行执行。

    @Test
    public void testList() {
        ListOperations<String, Object> list = redisTemplate.opsForList();
        list.rightPush("list", "accp");
        list.rightPush("list", "bdqn");
        list.rightPush("list", "czkt");
        String value = (String) list.leftPop("list");
        System.out.println("list value:" + value.toString());
    }
6、集合

Redis Set对外提供的功能与List类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,Set是一个很好的选择,并目 Set提供了判断某个成员是否在一个Set 集合内的重要接口,这个也是 ist 所不能提供的。Redis 还为集合提供了求交集、并集、差集等操作。

7.有序集合

Redis Sorted Set的使用场景与 Set 类似,区别是 Set 不是自动有序的,而 Sorted set 可以通过用户额外提供一个优先级(Score)的参数来为成员排序,并且是插入有序,即自动排序。

使用 Zset的时候需要额外的输入一个参数Score,Zset 会自动根据 Score 的值对集合进行排序,我们可以利用这个特性来做具有权重的队列,比如普通消息的Score为1,重要消息的Score 为2,然后工作线程可以选择按Score 的倒序来获取工作任务。

Spring Boot集成Redis可以通过以下步骤实现: 1. 引入spring-boot-starter-data-redis依赖。在项目的pom.xml文件中,添加以下依赖项: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 这将自动引入与Redis集成所需的依赖项。 2. 在Spring Boot的核心配置文件application.properties中配置Redis连接信息。在该文件中添加以下配置项: ``` spring.redis.host=127.0.0.1 spring.redis.port=6379 spring.redis.password=123456 ``` 根据你的实际情况,将host、port和password替换为相应的值。这些配置将用于建立与Redis服务器的连接。 通过以上步骤,你就成功地在Spring Boot应用程序中集成Redis。现在,你可以使用Spring Data Redis的API来访问和操作Redis数据库。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [SpringBoot集成redis](https://blog.csdn.net/qq_43512320/article/details/122684865)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [springboot集成Redis](https://blog.csdn.net/m0_54853420/article/details/126515971)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值