SpringBoot 整合 jedis

混江龙づ霸主 提交于 2020-01-22 04:56:42

常用的redis客户端介绍以及对比

Jedis api 在线网址:http://tool.oschina.net/uploads/apidocs/redis/clients/jedis/Jedis.html

redisson 官网地址:https://redisson.org/

redisson git项目地址:https://github.com/redisson/redisson

lettuce 官网地址:https://lettuce.io/ lettuce

git项目地址:https://github.com/lettuce-io/lettuce-core

首先,在spring boot2之后,对redis连接的支持,默认就采用了lettuce。这就一定程度说明了lettuce 和Jedis 的优劣。

概念

Jedis:是老牌的Redis的Java实现客户端,提供了比较全面的Redis命令的支持,

Redisson:实现了分布式和可扩展的Java数据结构。

Lettuce:高级Redis客户端,用于线程安全同步,异步和响应使用,支持集群,Sentinel,管道和编码器。

优点

Jedis:比较全面的提供了Redis的操作特性

Redisson:促使使用者对Redis的关注分离,提供很多分布式相关操作服务,例如,分布式锁,分布式集合,可通过 Redis支持延迟队列

Lettuce:基于Netty框架的事件驱动的通信层,其方法调用是异步的。Lettuce的API是线程安全的,所以可以操 作单个Lettuce连接来完成各种操作

可伸缩

Jedis:使用阻塞的I/O,且其方法调用都是同步的,程序流需要等到sockets处理完I/O才能执行,不支持异步。 Jedis客户端实例不是线程安全的,所以需要通过连接池来使用Jedis。

Redisson:基于Netty框架的事件驱动的通信层,其方法调用是异步的。Redisson的API是线程安全的,所以可以 操作单个Redisson连接来完成各种操作

Lettuce:基于Netty框架的事件驱动的通信层,其方法调用是异步的。Lettuce的API是线程安全的,所以可以操 作单个Lettuce连接来完成各种操作

lettuce能够支持redis4,需要java8及以上。 lettuce是基于netty实现的与redis进行同步和异步的通信。

lettuce和jedis比较

jedis使直接连接redis server,如果在多线程环境下是非线程安全的,这个时候只有使用连接池,为每个jedis实 例增加物理连接 ;

lettuce的连接是基于Netty的,连接实例(StatefulRedisConnection)可以在多个线程间并发访问, StatefulRedisConnection是线程安全的,所以一个连接实例可以满足多线程环境下的并发访问,当然这也是可伸 缩的设计,一个连接实例不够的情况也可以按需增加连接实例。

Redisson实现了分布式和可扩展的Java数据结构,和Jedis相比,功能较为简单,不支持字符串操作,不支持排 序、事务、管道、分区等Redis特性。Redisson的宗旨是促进使用者对Redis的关注分离,从而让使用者能够将精力 更集中地放在处理业务逻辑上。

总结

优先使用Lettuce,如果需要分布式锁,分布式集合等分布式的高级特性,添加Redisson结合使用,因为Redisson 本身对字符串的操作支持很差。

在一些高并发的场景中,比如秒杀,抢票,抢购这些场景,都存在对核心资源,商品库存的争夺,控制不好,库存数量 可能被减少到负数,出现超卖的情况,或者 产生唯一的一个递增ID,由于web应用部署在多个机器上,简单的同步加 锁是无法实现的,给数据库加锁的话,对于高并发,1000/s的并发,数据库可能由行锁变成表锁,性能下降会厉害。 那相对而言,redis的分布式锁,相对而言,是个很好的选择,redis官方推荐使用的Redisson就提供了分布式锁和 相关服务。

在官方网站列一些Java客户端访问,有:Jedis/Redisson/Jredis/JDBC-Redis等,其中官方推荐使用Jedis和 Redisson。常用Jedis。

简介

我们在使用springboot搭建微服务的时候,在很多时候还是需要redis的高速缓存来缓存一些数据,存储一些高频率 访问的数据,如果直接使用redis的话又比较麻烦,在这里,我们使用jedis来实现redis缓存来达到高效缓存的目的

新建一个spring项目

在这里插入图片描述

引入Jedis依赖

<dependency> 
  <groupId>redis.clients</groupId> 
  <artifactId>jedis</artifactId> 
</dependency>

因为 SpringBoot 内默认引用了jedis版本。

所以我们直接引入jedis 依赖 无需在配置 jedis的版本号了

完成的pom文件

<?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.2.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.fjx</groupId>
    <artifactId>boot-jedis</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>boot-jedis</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

application.yml配置文件

server:
  port: 8080

spring:
  redis:
    host: 192.168.22.165
    port: 6379
    password: fengjiaxing
    jedis:
      pool:
        max-idle: 6 #最大空闲数
        max-active: 20 #最大连接数
        min-idle:  2 #最小空闲数
    timeout: 2000 #连接超时

新建JedisConfig配置类

package com.fjx.config;/*
 @author Jason
 @DESCRIPTION 
 @create 2020-01-08
*/
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

@Configuration //相当于一个XML
public class JedisConfig {
    private Logger logger = LoggerFactory.getLogger(JedisConfig.class);

    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private int port;

    @Value("${spring.redis.password}")
    private String password;

    @Value("${spring.redis.timeout}")
    private int timeout;

    @Value("${spring.redis.jedis.pool.max-active}")
    private int maxActive;

    @Value("${spring.redis.jedis.pool.max-idle}")
    private int maxIdle;

    @Value("${spring.redis.jedis.pool.min-idle}")
    private int minIdle;

    @Bean
    public JedisPool jedisPool(){
        JedisPoolConfig jedisPoolConfig=new JedisPoolConfig();
        jedisPoolConfig.setMaxIdle(maxIdle);
        jedisPoolConfig.setMinIdle(minIdle);
        jedisPoolConfig.setMaxTotal(maxActive);
        JedisPool jedisPool =new JedisPool(jedisPoolConfig,host,port,timeout,password);
        logger.info("JedisPool连接成功:"+host+"\t"+port);
        return jedisPool;
    }
}

新写测试类

package com.fjx;

import com.fjx.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

@SpringBootTest
class  BootJedisApplicationTests {
    @Autowired
    private JedisPool jedisPool;
    
    @Test
    void contextLoads() {
        System.out.println(jedisPool);
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UNYAvm1Y-1579612078557)(2116C3DCCB164A47A208BCFEEE111CC9)]

项目目录

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F1l3SqPR-1579612078558)(8EC107BE3AAC43B4A268BA419B3856FB)]

新建user实体对象 User类

package com.fjx.pojo;/*
 @author Jason
 @DESCRIPTION 
 @create 2020-01-08
*/

import lombok.Data;

import java.io.Serializable;

@Data
public class User implements Serializable {
    private String id;
    private String username;
    private Integer age;
}

新建UserService接口

package com.fjx.service;/*
 @author Jason
 @DESCRIPTION 
 @create 2020-01-08
*/

import com.fjx.pojo.User;

public interface UserService {
    /**
     * @author Jason
     * @DESCRIPTION: ******TODO  测试string类型
     * Redis String类型学习
     * 需求: 用户输入一个key,获取value值
     * 先判断Redis中是否存在该数据
     * 如果存在.redis 中进行查询,结果返回
     * 如果不存在,mysql数据库中查询,将结果复制个redis,并返回
     * @params: [key]
     * @return: java.lang.String
     * @Date: 2020-01-09 15:33
     * @Modified By:
     */

    String getString(String key);

    /**
     * @author Jason
     * @DESCRIPTION: ******TODO  测试hash类型
     * Redis hash类型学习
     * 需求: 根据id查询用户信息
     * 先判断Redis中是否存在该数据
     * 如果存在.redis 中进行查询,并返回
     * 如果不存在,mysql数据库中查询,将结果复制个redis,并返回
     * @params: [id]
     * @return: com.fjx.pojo.User
     * @Date: 2020-01-11 10:29
     * @Modified By:
     */
    User selectById(String id);
}

新建UserServiceImpl实现类,实现UserService接口

package com.fjx.service.impl;/*
 @author Jason
 @DESCRIPTION 
 @create 2020-01-09
*/


import com.fjx.config.JedisUtils;
import com.fjx.pojo.User;
import com.fjx.service.UserService;
import lombok.extern.java.Log;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;

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

@Service
@Log
public class UserServiceImpl implements UserService {

    @Autowired
    private JedisUtils jedisUtils;

    /**
     * @author Jason
     * @DESCRIPTION: redis有什么命令,jedis就有什么方法
     * @params: [key]
     * @return: java.lang.String
     * @Date: 2020-01-09 16:29
     * @Modified By:
     * ***********TODO String类型演示
     */

    @Override
    public String getString(String key) {

        Jedis jedis = jedisUtils.getJedis();
        String val = null;
        if (!jedis.exists(key)) {
            val = "范闲";
            log.info(key + "数据来自mysql数据库,值为:" + val);
            jedis.set(key, val);
            log.info(key + "将数据库中的数据存入redis" + val);
        } else {
            val = jedis.get(key);
            log.info(key + "数据来自redis,值为" + val);
        }
        jedisUtils.close(jedis);
        return val;
    }

    /**
     * @author Jason
     * @DESCRIPTION: 根据id查询用户信息
     * **TODO 测试hash类型
     * @params: [id]
     * @return: com.fjx.pojo.User
     * @Date: 2020-01-11 10:32
     * @Modified By:
     */

    @Override
    public User selectById(String id) {
        // 思路
        // 1.获取连接对象
        Jedis jedis = jedisUtils.getJedis();
        String key = "user:id";
        User user = new User();
        // 如果redis中不存在该key值
        if (!jedis.exists(key)) {
            // 封装一个用户对象
            user.setId(id);
            user.setUsername("哭泣巴拉");
            user.setAge(11);
            //从数据库中进行查询
            log.info("从mysql数据库中查询用户信息" + user);
            // 将查询出来的数据存入到redis
            HashMap<String, String> map = new HashMap<>();
            map.put("id", user.getId());
            map.put("name", user.getUsername());
            jedis.hset(key, map);
            log.info(key + "成功将用户信息存入redis" + user);
        } else {
            // 从redis中查询用户信息
            Map<String, String> map = jedis.hgetAll(key);
            user.setId(map.get("id"));
            user.setUsername(map.get("name"));
            log.info(key + "从redis中查询用户信息" + map);
        }
        // 关闭连接对象
        jedisUtils.close(jedis);
        return user;
    }
}

编写测试类

package com.fjx;

import com.fjx.pojo.User;
import com.fjx.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

@SpringBootTest
class BootJedisApplicationTests {
    @Autowired
    private JedisPool jedisPool;

    @Test
    void contextLoads() {
        System.out.println(jedisPool);
    }

    @Autowired
    private UserService userService;

    /**
     * @author Jason
     * @DESCRIPTION: 用户输入一个key,获取value值
     * TODO 测试String类型
     * @params: []
     * @return: void
     * @Date: 2020-01-11 10:51
     * @Modified By:
     */

    @Test
    void stringTest() {
        String result = userService.getString("username");
        System.out.println(result);
    }

    /**
     * @author Jason
     * @DESCRIPTION:根据用户id查询用户信息
     * TODO 测试Hash类型
     * @params: []
     * @return: void
     * @Date: 2020-01-11 10:50
     * @Modified By:
     */

    @Test
    void hashTest() {
        User user = userService.selectById("1001");
        System.out.println(user);
    }

}


运行结果

在这里插入图片描述

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!