Java jedis 连接池小结-踩坑实战

435 阅读3分钟

在上篇内容中,我们学习了在 Java 使用 jedis 进行 redis 的缓存操作,这篇内容,我们将从 连接池 方面给大家分享。

1.三方库依赖

下面是 maven 环境依赖的配置文件:

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>redisDemo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>5.0.2</version>
        </dependency>

        <!-- 解决类加载问题 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.36</version>
        </dependency>

        <!-- 解决程序未找到问题 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.36</version>
        </dependency>
    </dependencies>

</project>

注意,此处我们多添加了 slf4j 的相关库,不要问为什么,问就是必须有,不然会报环境依赖问题,这里是和 redis 单实例连接的不同,一定要注意,注意,注意!

2.相关配置

通常我们都会在项目应用中通过一个配置文件存储配置项,当然如果你的项目很大,可以使用配置应用,不同的语言有不同的生态,根据需要选择,这里不展开。

下面是 redis 的简单配置:

# redis settings
redis.host=172.30.3.57
redis.port=6379
redis.timeout=10000

redis.maxIdle=100
redis.maxTotal=200

# ms
redis.maxWaitMillis=1000

我们是放在 maven 构建项目的 resources目录 中,请注意。

3.配置工具类

主要功能就是根据配置文件返回配置实例,以便于后面读取配置:

package org.example;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class PropertyUtil {
    public static Properties loadProperties(String propertyFile) {
        Properties properties = new Properties();

        try {
            InputStream is = PropertyUtil.class.getClassLoader().getResourceAsStream(propertyFile);

            if (is == null) {
                is = PropertyUtil.class.getClassLoader().getResourceAsStream("properties/" + propertyFile);
            }
            properties.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return properties;
    }

    public static String getValue(String propertyFile, String key) {
        Properties properties = loadProperties(propertyFile);

        return properties.getProperty(key);
    }

    public static void main(String[] args) {
        // properties files
        String propertyFile = "redis.properties";
        Properties properties = loadProperties(propertyFile);
        System.out.println(properties);

        System.out.printf("redis.host: %s", PropertyUtil.getValue(propertyFile, "redis.host"));
    }
}

4.redis 连接池

下面这段源码,主要就是读取上面的 redis 配置,然后创建单例连接池,然后提供外部连接调用:

package org.example;

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

import java.util.Properties;

/**
 * redis 连接池的使用
 */
public class RedisPoolDemo {
    private static Properties properties = getProperties();

    private static final JedisPoolConfig jpc = getConfig();

    private static final JedisPool pool = new JedisPool(jpc,
            properties.getProperty("redis.host"),
            Integer.parseInt(properties.getProperty("redis.port")),
            Integer.parseInt(properties.getProperty("redis.timeout"))
            );

    private static Properties getProperties() {
        Properties properties = PropertyUtil.loadProperties("redis.properties");
        return properties;
    }

    private static JedisPoolConfig getConfig() {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxIdle(Integer.parseInt(properties.getProperty("redis.maxIdle")));
        config.setMaxTotal(Integer.parseInt(properties.getProperty("redis.maxTotal")));

        return config;
    }

    private Jedis getInstance() {
        return pool.getResource();
    }


    public void set(String key, String val) {
        Jedis jedis = getInstance();
        jedis.select(5);
        System.out.printf(jedis.getClient().toString() + "\n");
        try {
            Thread.sleep(1000* 10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        jedis.set(key, val);
    }

    public String get(String key) {
        Jedis jedis = getInstance();
        return jedis.get(key);
    }

    public void del(String key) {
        Jedis jedis = getInstance();
        jedis.del(key);
    }

    public static void main(String[] args) {
        RedisPoolDemo pool = new RedisPoolDemo();
        pool.set("1", "1");
    }
}

5.连接池的使用

连接池的调用也很简单,就是简单地创建多线程测试 redis 的连接,看是否 work:

package org.example;

public class JedisPoolUsage {
    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new MyThread(Integer.toString(i)).start();
        }
    }
}


class MyThread extends Thread {
    public String key;

    public MyThread(String key) {
        this.key = key;
    }

    @Override
    public void run() {
        RedisPoolDemo pool = new RedisPoolDemo();
        pool.set(this.key, this.key);
        System.out.printf(Thread.currentThread().getName() + " end!\n");
    }
}

6.测试结果

我们通过 redis 客户端的 info 命令 看看调用连接池前后 redis 的客户端连接情况及库内数据情况。

调用连接池前

image.png

可以看到调用前的 connected_clients = 80。

调用中

image.png

我们在代码中休眠线程10s,以便进一步看到效果,确实连接的客户端,大约增长了100个,符合我们的预期。

调用连接池结束

image.png

调用结束后,连接的客户端数量恢复到80左右,符合预期。

keys *

image.png

从插入的数据来看,也是符合预期的,说明我们的 redis线程池 确实可用,当然这都是很草的,实际运用中还是需要注意更多,让我们的程序更加健壮,因为示例,所以,展示用法为主。

7.更多

在实际操作时,遇到个坑就是 slf4j 依赖的问题,感兴趣的可以自己搜搜看看,一定要注意三方库的依赖问题。

这里分享两个看 三方库依赖的方法:

1. plugin: maven helper

在 IDEA 插件中 install Maven Helper,restart IDEA 后再查看 pom.xml 就可以看到多了以来分析:

image.png

我们可以点进去看看相关依赖树或冲突,便于我们结局冲突问题:

image.png

2.Maven自带工具 我们也可以通过工具栏中的 Maven 的自带分析工具:

image.png

接着查看依赖情况:

image.png

最后,预祝大家使用 jedis连接池 一次成功。

p.s. 连接池参数[1]:

image.png

参考: