Redis整合SpringBoot微服务基础操作

前言

首先我们先知道类似于JDBC的连接中间件在redis之间使用的是啥

首先是Jedis,这是最初代的连接redis客户端 

操作也是非常的简单

Jedis

首先我们先介绍这个

我们只需要引入对应的pom文件依赖

   <!--SpringBoot通用依赖模块-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--jedis-->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>4.3.1</version>
        </dependency>
        <!--lettuce-->
        <dependency>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
            <version>6.2.1.RELEASE</version>
        </dependency>
        <!--SpringBoot与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>
        <!--swagger2-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>

这个连接中间件主要是线程池不安全

所以才有了后续的迭代

我们先使用一下试试看

注意这里的端口和ip写自己的

如果不知道可以使用对应的命令进行查看

ifconfig  //linux

ipconfig //windows
public class JedisDemo {
    public static void main(String[] args) {
        //获得连接connect
        Jedis jedis = new Jedis("192.168.188.136", 6379);
        jedis.auth("abc123");
        //获得客户端之后可以像JDBC一样可以获取
        System.out.println(jedis.ping());


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

        //设置一个
        jedis.set("k3","v333");
        System.out.println(jedis.get("k3"));


        //list
        jedis.lpush("list","aaa","bbb","ccc");
        System.out.println(jedis.lrange("list",0,-1));


    }
}

然后我们可以进对应的客户端查看就会发现对应的数据已经写入了

这里的乱码问题我们暂时不考虑,主要是编码和序列化的问题,是因为我之前测试集群输入中文的时候产生的,大家不必在意

Lettuce

有人会问有了Jedis为啥使用这个(中文翻译叫生菜)生菜呢?

其实是因为在使用Jedis的时候,会多次创建多个连接池

相对来说如果支持8w个请求,那么也肯定内内存撑爆了

而且其是线程不安全的

这里的Lettuce底层使用netty,可以确保只用一个连接池保证多路复用

说了这么多我们就来看看对应的Lettuce是怎么使用的吧

我们只需要对应的pom依赖导入

    <!--lettuce-->
        <dependency>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
            <version>6.2.1.RELEASE</version>
        </dependency>

这里主要体现链式编程,我们也是一样的配置

我们先配置对应的URL

在座位参数传给对应的客户端

然后创建对应操作command

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

        //获取客户端
        RedisClient redisClient = RedisClient.create(redisURI);
        StatefulRedisConnection<String, String> connect = redisClient.connect();
        
        //创建操作的command
        RedisCommands<String, String> sync = connect.sync();

        //业务操作
        List<String> keys = sync.keys("*");
        System.out.println(keys);


        //关闭资源
        connect.close();
    }
}

虽然体现的日志信息比较多

但是也可以看到完整的信息

RedisTemplate(重中之重)

下面我们来介绍使用的主流 

RedisTemplate,这也是被Spring集成的框架

我们可以在对应的jar包上看到起集成了Lettuce

其实是因为在Lettuce刚开发出来的时候Spring掩盖住了它的光芒

所以使用RedisTemplate更多

他还有一个常用的子类,叫做StringRedisTemplate

首先依然是引入对应的依赖

        <!--SpringBoot与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>
        <!--swagger2-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>

然后我们就可以进行对应的开发了

然后就是对应的配置yml文件

注意修改ip为自己的ip哦

server.port=7777

spring.application.name=redis7_study

# ========================logging=====================
logging.level.root=info
logging.level.com.atguigu.redis7=info
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n 

logging.file.name=D:/mylogs2023/redis7_study.log
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n

# ========================swagger=====================
spring.swagger2.enabled=true
#在springboot2.6.X结合swagger2.9.X会提示documentationPluginsBootstrapper空指针异常,
#原因是在springboot2.6.X中将SpringMVC默认路径匹配策略从AntPathMatcher更改为PathPatternParser,
# 导致出错,解决办法是matching-strategy切换回之前ant_path_matcher
spring.mvc.pathmatch.matching-strategy=ant_path_matcher

# ========================redis单机=====================
spring.redis.database=0
# 修改为自己真实IP
spring.redis.host=192.168.111.185
spring.redis.port=6379
spring.redis.password=111111
spring.redis.lettuce.pool.max-active=8
spring.redis.lettuce.pool.max-wait=-1ms
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.min-idle=0

然后注意修改对应的主启动类

@SpringBootApplication
public class Redis7Study7777
{
    public static void main(String[] args)
    {
        SpringApplication.run(Redis7Study7777.class,args);
    }
}

我们这里采用一个微服务的架构,存储一个订单信息

架构大概是这样的

这里我们业务就在service层中写

@Service
@Slf4j
public class OrderService {
    public static final String ORDER_KEY = "order:";

    @Resource
    private RedisTemplate redisTemplate;
//@Resource
//private StringRedisTemplate redisTemplate;
    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("添加订单成功,keyId:{},value:{}", keyId, value);
    }


    public String getOrder(int keyId) {
        return (String) redisTemplate.opsForValue().get(ORDER_KEY + keyId);
    }


}

后面我们配置一下swagger直接测试接口

 下面我们进行简单的get和add方法的书写以及swagger测试框架的配置

swagger配置

@Configuration
@EnableSwagger2
public class SwaggerConfig
{
    @Value("${spring.swagger2.enabled}")
    private Boolean enabled;

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .enable(enabled)
                .select()
                .apis(RequestHandlerSelectors.basePackage("org.example")) //你自己的package
                .paths(PathSelectors.any())
                .build();
    }

}

对应的包记得改成自己的

然后我们写controller接口


@RestController
@Slf4j
@Api(tags ="订单接口")
public class OrderController {
    @Resource
    private OrderService orderService;

    @ApiOperation("添加订单")
    @RequestMapping("/order/add")
    public void addOrder()
    {
        orderService.addOrder();
    }

    @ApiOperation("查询订单")
    @RequestMapping("/order/{keyId}")
    public void getOrder(@PathVariable int keyId)
    {
        orderService.getOrder(keyId);
    }
}

然后直接使用swagger进行对应的接口测试操作

这里为了演示一个错误,我们使用最原始的RedisTemplate

这时候我们就会发现写入的中文是乱码信息

解决方式这里提供两种方案

首先是使用StringRedisTemplate解决问题

因为默认RedisTemplate默认是采用对应的JDK来进行序列化的

我们使用StringRedisTemplate可以解决问题

但是我们查看对应的值还是不行

我们只需要在链接客户端的时候加上

redis-cli -a abc123 --raw

就可以解决中文乱码的问题了

如果就想使用RedisTemplate可以直接进行配置,在开始的时候就使用

StringRedisTemplate进行对应的初始化

只需要加上一个Config类

@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.setConnectionFactory(lettuceConnectionFactory);
        //设置key序列化方式string
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //设置value的序列化方式json,使用GenericJackson2JsonRedisSerializer替换默认序列化
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());

        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());

        redisTemplate.afterPropertiesSet();

        return redisTemplate;
    }
}

即可解决问题

小总结

使用redis-cli -a "password" -p  port --raw

就可以解决对应的中文乱码问题(根据键查看值的时候)

然后对应的序列化问题使用StringRedisTemplate就可以

注意swagger的包和对应的properties文件记得修改成自己的

集群操作配置

首先我们开启对应的集群

配置对应的配置信息

将单机的配置文件修改成对集群的

使用cluster nodes 查看对应的集群信息

我们试试对应的写入能否成功

# ========================redis集群=====================
spring.redis.password=abc123


# 获取失败 最大重定向次数
spring.redis.cluster.max-redirects=3
spring.redis.lettuce.pool.max-active=8
spring.redis.lettuce.pool.max-wait=-1ms
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.min-idle=0
spring.redis.cluster.nodes=192.168.188.136:6381,192.168.188.136:6382,192.168.188.137:6383,192.168.188.137:6384,192.168.188.138:6385,192.168.188.138:6386

我们尝试一下是否能成功写入

我们发现插入是成功的

我们再验证一下主从的上位情况是否能成功

我们先把主机干掉

我们尝试直接干掉138,查看136是否会上位

我们发现6382已经成为master了

然后我们再次尝试写入

我们发现一直失败了

然后到超时时间就直接失败了

我们可以配置对应的动态刷新拓扑结构或者是定时刷新就可以解决问题

因为这里其实是redis客户端的拓扑结构变化了

其实对应的微服务对其是无感应的

我们只需让其有感知即可

也就是对对应的配置文件进行修改

# ========================redis集群=====================
spring.redis.password=abc123

#支持集群拓扑动态感应刷新,自适应拓扑刷新是否使用所有可用的更新,默认false关闭
spring.redis.lettuce.cluster.refresh.adaptive=true
#定时刷新
spring.redis.lettuce.cluster.refresh.period=2000
# 获取失败 最大重定向次数
spring.redis.cluster.max-redirects=3
spring.redis.lettuce.pool.max-active=8
spring.redis.lettuce.pool.max-wait=-1ms
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.min-idle=0
spring.redis.cluster.nodes=192.168.188.136:6381,192.168.188.136:6382,192.168.188.137:6383,192.168.188.137:6384,192.168.188.138:6385,192.168.188.138:6386

其实还有两种方式,但是我们不推荐

1.底层使用Jedis

2.修改连接池的源码解决问题

解决完之后就是以下的结果

  • 27
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值