Springboot整合redis

一、概述

常用网站汇总

官方网站: Redis
Redis中文文档 redis中文文档

Redis 在线测试 Try Redis
Redis 命令参考 Commands | Redis

 1.1 jedis(一般不用,了解即可)

        <!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>4.3.1</version>
        </dependency>
package com.yanyu.redisjedistest.demo;

import redis.clients.jedis.Jedis;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class JedisDemo
{
    public static void main(String[] args)
    {
        //1 connection获得,通过指定ip和端口号
        Jedis jedis = new Jedis("0", 3390);
        //2 指定访问服务器的密码
        jedis.auth("0");

        // 指定访问的数据库(此处以第0号数据库为例)
        jedis.select(16);
        //3 获得了jedis客户端,可以像jdbc一样,访问我们的redis
        System.out.println(jedis.ping());

        //keys
        Set<String> keys = jedis.keys("*");
        System.out.println(keys);

        //string
        jedis.set("k3","hello-jedis");
        System.out.println(jedis.get("k3"));
        System.out.println(jedis.ttl("k3"));
        jedis.expire("k3",20L);

        //list
        jedis.lpush("list","11","12","13");
        List<String> list = jedis.lrange("list", 0, -1);
        for (String element : list) {
            System.out.println(element);
        }
        // hash
        jedis.hset("hset1","k1","v1");
        Map<String,String> hash = new HashMap<>();
        hash.put("k1","1");
        hash.put("k2","2");
        hash.put("k3","3");
        jedis.hmset("hset2",hash);
        System.out.println(jedis.hmget("hset2","k1","k3","k2"));
        System.out.println(jedis.hget("hset1", "k1"));
        System.out.println(jedis.hexists("hset2","k2"));
        System.out.println(jedis.hkeys("hset2"));

        // set
        jedis.sadd("set1","1","2","3");
        jedis.sadd("set2","4");
        System.out.println(jedis.smembers("set1"));
        System.out.println(jedis.scard("set1"));
        System.out.println(jedis.spop("set1"));
        jedis.smove("set1","set2","2");
        System.out.println(jedis.smembers("set1"));
        System.out.println(jedis.smembers("set2"));
        System.out.println(jedis.sinter("set1", "set2"));  // 交集
        System.out.println(jedis.sunion("set1","set2"));   // 并集

        // zset
        jedis.zadd("zset1",100,"v1");
        jedis.zadd("zset1",80,"v2");
        jedis.zadd("zset1",60,"v3");

        List<String> zset1 = jedis.zrange("zset1", 0, -1);
        for (String s : zset1) {
            System.out.println(s);
        }
        List<String> zset11 = jedis.zrevrange("zset1", 0, -1);
        for (String s : zset11) {
            System.out.println(s);
        }
    }
}

1.2 lettuce(了解)

<!-- https://mvnrepository.com/artifact/io.lettuce/lettuce-core -->
<dependency>
    <groupId>io.lettuce</groupId>
    <artifactId>lettuce-core</artifactId>
    <version>6.2.3.RELEASE</version>
</dependency>
package com.yanyu.redisjedistest.demo;

import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisURI;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.sync.RedisCommands;

import java.util.List;

public class LettuceDemo
{
    public static void main(String[] args)
    {
        // 1 使用构建器链式编程来builder我们RedisURI
        RedisURI uri = RedisURI.builder()
                .redis("0")
                .withPort(0)
                .withAuthentication("default","")
                .build();

        //2 创建连接客户端
        RedisClient redisClient = RedisClient.create(uri);
        StatefulRedisConnection conn = redisClient.connect();

        //3 通过conn创建操作的command
        RedisCommands commands = conn.sync();
        commands.select(16);
        //========biz====================
        //keys
        List keys = commands.keys("*");
        System.out.println("***********"+keys);

        //string
        commands.set("k5","hello-lettuce");
        System.out.println("***********"+commands.get("k5"));

        // list
        commands.lpush("list01","1","2","3");
        List<String> list01 = commands.lrange("list01", 0, -1);
        for (String s : list01) {
            System.out.println("================"+s);
        }
        System.out.println("===================="+ commands.rpop("list01", 2));

        // hash
        commands.hset("hash","k1","v1");
        commands.hset("hash","k2","v2");
        commands.hset("hash","k3","v3");
        System.out.println("======================="+commands.hgetall("hash"));
        Boolean hexists = commands.hexists("hash", "v2");
        System.out.println("------"+hexists);

        // set
        commands.sadd("s1","1","2");
        System.out.println("=================================" + commands.smembers("s1"));
        System.out.println(commands.sismember("s1", "1"));
        System.out.println(commands.scard("s1"));

        // zset
        commands.zadd("a1",100,"v1");
        commands.zadd("a1",80,"v2");
        System.out.println(commands.zrange("a1", 0, -1));
        System.out.println("======================"+commands.zcount("a1", "90", "100"));

        //4 各种关闭释放资源
        conn.close();
        redisClient.shutdown();
    }
}

1.3RedisTemplate

依赖

        <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>

默认情况下会为我们提供下面两个bean对象,我更推荐使用StringRedisTemplate原因如下

RedisTemplate<Object, Object>
StringRedisTemplate

配置

# Spring Boot应用程序的Spring Data Redis配置

spring:
  data:
    redis:
      # 指定要连接的Redis数据库编号。Redis默认有16个数据库(编号为0至15),此处设置为16。
      database: 16

      # Redis服务器的主机地址,这里是
      host: 

      # Redis服务器监听的端口号,此处设置为
      port: 

      # 访问Redis服务器所需的密码。此处设置为`
      password: 

      # 配置Lettuce连接池参数(Lettuce是Spring Data Redis使用的默认客户端库之一)

      lettuce:
        pool:
          # 连接池中允许的最大活动连接数。当达到此限制时,新请求将被阻塞直到有连接释放。此处设置为`8`
          max-active: 8

          # 当连接池耗尽时,客户端尝试获取连接的最长时间。负值表示无限等待。此处设置为`-1ms`,意味着无限制等待
          max-wait: -1ms

          # 连接池中的最大空闲连接数。超过此数量的空闲连接将被断开。此处设置为`8`
          max-idle: 8

          # 连接池中的最小空闲连接数。低于此数量时,连接池将尝试补充空闲连接。此处设置为`0`,意味着无需保持最小空闲连接数
          min-idle: 0

service

package com.yanyu.redisjedistest.service;

import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;

@Service
@Slf4j
public class OrderService
{

    public static final String ORDER_KEY = "ord:";

    @Resource
    private RedisTemplate redisTemplate;
    //@Resource private StringRedisTemplate StringRedisTemplate;

    public void addOrder()
    {
        int keyId = ThreadLocalRandom.current().nextInt(1000)+1;
        String serialNo = UUID.randomUUID().toString();

        String key = ORDER_KEY+keyId;
        String value = "京东订单"+serialNo;

        redisTemplate.opsForValue().set(key,value);


        log.info("***key:{}",key);
        log.info("***value:{}",value);
    }

    public String getOrderById(Integer keyId)
    {
        return (String) redisTemplate.opsForValue().get(ORDER_KEY + keyId);
        //return StringRedisTemplate.opsForValue().get(ORDER_KEY + keyId);
    }

}

controller

package com.yanyu.redisjedistest.controller;

import com.yanyu.redisjedistest.service.OrderService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Slf4j

public class OrderController
{
    @Resource
    private OrderService orderService;


    @RequestMapping(value = "/order/add",method = RequestMethod.POST)
    public void addOrder()
    {
        orderService.addOrder();
    }

    @RequestMapping(value = "/order/{keyId}",method = RequestMethod.GET)
    public String getOrderById(@PathVariable Integer keyId)
    {
        return orderService.getOrderById(keyId);
    }
}

config

package com.yanyu.redisjedistest.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {

    /**
     * redis序列化的工具配置类,下面这个请一定开启配置
     * 127.0.0.1:6379> keys *
     * 1) "ord:102"  序列化过
     * 2) "\xac\xed\x00\x05t\x00\aord:102"   野生,没有序列化过
     * this.redisTemplate.opsForValue(); //提供了操作string类型的所有方法
     * this.redisTemplate.opsForList(); // 提供了操作list类型的所有方法
     * this.redisTemplate.opsForSet(); //提供了操作set的所有方法
     * this.redisTemplate.opsForHash(); //提供了操作hash表的所有方法
     * this.redisTemplate.opsForZSet(); //提供了操作zset的所有方法
     * @param lettuceConnectionFactory
     * @return
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();

        // 设置 RedisTemplate 连接工厂
        redisTemplate.setConnectionFactory(lettuceConnectionFactory);

        // 设置键(Key)的序列化方式为字符串(String)
        redisTemplate.setKeySerializer(new StringRedisSerializer());

        // 设置值(Value)的序列化方式为 JSON,使用 Jackson 库实现
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());

        // 设置哈希键(Hash Key)和哈希值(Hash Value)的序列化方式同上
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());

        // 调用 afterPropertiesSet() 方法完成模板初始化
        redisTemplate.afterPropertiesSet();

        return redisTemplate;
    }
}

1.4集群

spring:
  redis:
    password: 123456
    lettuce:
      pool:
        max-idle: 32
        max-active: 32
        min-idle: 8
        max-wait: -1
    cluster:
      nodes:
        - 192.168.139.140:6379
        - 192.168.139.140:6380
        - 192.168.139.140:6381
        - 192.168.139.140:6382
        - 192.168.139.140:6383
        - 192.168.139.140:6384
      max-redirects: 3

问题复现:

选择一台主节点宕机,这里选择 6379,首先找到一个会落到6379节点的key

问题的原因:服务没有感受到集群的变化。

Lettuce 不会刷新拓扑图。

解决方案:
方案一:使用 jedis(不推荐)
方案二:重写连接工厂实例(不推荐)
方案三:刷新节点集群拓扑动态感应(官网)

spring:
  redis:
    password: 123456
    lettuce:
      cluster:
        # 刷新集群拓扑        
        refresh:
          adaptive: true
          period: 2000

参考链接 spring boot整合redis集群,连接虚拟机redis集群,Unable to connect to 127-java面试题网

  • 15
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

烟雨平生9527

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值