Jedis快速入门

一、前言:为什么选择 Jedis?

在 Java 生态中,操作 Redis 的主流客户端有:

  • Jedis:轻量、简单、API 直接映射 Redis 命令
  • Lettuce:基于 Netty,支持异步、响应式(Spring Boot 2.x+ 默认)
  • Redisson:功能丰富,提供分布式锁、集合等高级特性

Jedis 凭借其极简 API、低学习成本、高性能 ,依然是许多项目的首选,尤其适合:

✅ 快速原型开发

✅ 对 Redis 命令熟悉、追求控制力的开发者

✅ 轻量级应用或微服务

本文将带你从零搭建 Jedis 环境,并实现常用数据类型操作


二、环境准备

2.1 前提条件

  • JDK 8+
  • Maven 或 Gradle
  • 本地或远程 Redis 服务(版本 ≥ 3.0)
bash 复制代码
# 启动本地 Redis(Docker 示例)
docker run -d --name redis -p 6379:6379 redis:7.2

2.2 Maven 依赖

复制代码
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>5.1.2</version> <!-- 推荐使用最新稳定版 -->
</dependency>

💡 注意:Jedis 4.x+ 要求 Java 8+,5.x 支持 Redis 7+


三、Jedis 基础用法:单连接模式

⚠️ 仅用于测试!生产环境必须用连接池

java 复制代码
import redis.clients.jedis.Jedis;

public class JedisDemo {
    public static void main(String[] args) {
        // 1. 创建 Jedis 实例(默认 localhost:6379)
        try (Jedis jedis = new Jedis("localhost", 6379)) {
            
            // 2. 测试连接
            System.out.println("Redis 连接状态: " + jedis.ping()); // 返回 "PONG"

            // 3. String 操作
            jedis.set("name", "Alice");
            System.out.println("name = " + jedis.get("name"));

            // 4. 设置过期时间(秒)
            jedis.setex("temp_key", 10, "临时数据");

            // 5. Hash 操作
            jedis.hset("user:1001", "age", "25");
            jedis.hset("user:1001", "email", "alice@example.com");
            System.out.println("用户邮箱: " + jedis.hget("user:1001", "email"));

            // 6. List 操作
            jedis.lpush("news", "头条", "科技", "体育");
            System.out.println("最新新闻: " + jedis.lrange("news", 0, 1));

            // 7. Set 操作
            jedis.sadd("tags:1001", "java", "redis", "jedis");
            System.out.println("是否包含 'redis': " + jedis.sismember("tags:1001", "redis"));

            // 8. Sorted Set 操作
            jedis.zadd("rank", 1500, "player1");
            jedis.zadd("rank", 1800, "player2");
            System.out.println("TOP1: " + jedis.zrevrange("rank", 0, 0));
        }
    }
}

输出示例

复制代码
Redis 连接状态: PONG
name = Alice
用户邮箱: alice@example.com
最新新闻: [体育, 科技]
是否包含 'redis': true
TOP1: [player2]

四、生产必备:Jedis 连接池(JedisPool)

单连接无法应对高并发,必须使用连接池

4.1 配置连接池

java 复制代码
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class JedisPoolUtil {
    private static JedisPool jedisPool;

    static {
        JedisPoolConfig config = new JedisPoolConfig();
        // 最大连接数
        config.setMaxTotal(20);
        // 最大空闲连接
        config.setMaxIdle(10);
        // 获取连接时的最大等待时间(毫秒)
        config.setMaxWaitMillis(2000);
        // 在获取连接时检查有效性
        config.setTestOnBorrow(true);

        // 创建连接池(无密码)
        jedisPool = new JedisPool(config, "localhost", 6379, 2000);
        
        // 若有密码,使用:
        // jedisPool = new JedisPool(config, "localhost", 6379, 2000, "your_password");
    }

    public static Jedis getJedis() {
        return jedisPool.getResource();
    }

    public static void closePool() {
        if (jedisPool != null) {
            jedisPool.close();
        }
    }
}

4.2 使用连接池操作 Redis

java 复制代码
public class UserService {
    public void saveUser(String userId, String name, int age) {
        try (Jedis jedis = JedisPoolUtil.getJedis()) {
            jedis.hset("user:" + userId, "name", name);
            jedis.hset("user:" + userId, "age", String.valueOf(age));
            jedis.expire("user:" + userId, 3600); // 1小时过期
        }
    }

    public Map<String, String> getUser(String userId) {
        try (Jedis jedis = JedisPoolUtil.getJedis()) {
            return jedis.hgetAll("user:" + userId);
        }
    }
}

优势

  • 复用连接,避免频繁创建/销毁
  • 控制资源,防止连接耗尽
  • 自动回收异常连接

五、常见数据类型操作封装示例

5.1 String 工具类

java 复制代码
public class RedisStringUtil {
    public static void set(String key, String value) {
        try (Jedis jedis = JedisPoolUtil.getJedis()) {
            jedis.set(key, value);
        }
    }

    public static String get(String key) {
        try (Jedis jedis = JedisPoolUtil.getJedis()) {
            return jedis.get(key);
        }
    }

    public static void setEx(String key, int seconds, String value) {
        try (Jedis jedis = JedisPoolUtil.getJedis()) {
            jedis.setex(key, seconds, value);
        }
    }
}

5.2 分布式锁(简易版)

java 复制代码
public boolean tryLock(String lockKey, String requestId, int expireTime) {
    try (Jedis jedis = JedisPoolUtil.getJedis()) {
        // SET key value NX PX milliseconds
        String result = jedis.set(lockKey, requestId, "NX", "PX", expireTime);
        return "OK".equals(result);
    }
}

public void unlock(String lockKey, String requestId) {
    // 安全解锁需 Lua 脚本(略),此处简化
    try (Jedis jedis = JedisPoolUtil.getJedis()) {
        if (requestId.equals(jedis.get(lockKey))) {
            jedis.del(lockKey);
        }
    }
}

⚠️ 注意:生产级分布式锁建议使用 Redisson


六、Jedis vs Lettuce:如何选择?

特性 Jedis Lettuce
线程安全 ❌ 单实例非线程安全(需连接池) ✅ 线程安全
连接模型 阻塞 I/O 基于 Netty 的异步非阻塞
内存占用 稍高
Spring Boot 默认 1.x 2.x+
学习曲线 极简 稍复杂

选型建议

  • 新项目 + Spring Boot 2+ → Lettuce
  • 老项目 / 追求极致控制 / 轻量级 → Jedis

七、常见问题与最佳实践

❓ Q1:连接超时怎么办?

  • 检查 Redis 是否启动
  • 检查防火墙/安全组是否开放 6379
  • 增加 JedisPoolConfig.setMaxWaitMillis

❓ Q2:中文乱码?

  • Jedis 默认使用 UTF-8,确保你的字符串编码一致
  • 避免直接存储二进制数据(可用 Base64 编码)

✅ 最佳实践

  1. 永远使用 try-with-resources 或手动 close()
  2. 生产环境必须用连接池
  3. key 命名规范 :如 user:{id}:profile
  4. 设置 TTL,避免内存泄漏
  5. 监控连接池使用率getActive() / getMaxTotal()

八、结语

感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!

相关推荐
Scout-leaf5 小时前
WPF新手村教程(五)— 附魔教学(绑定)
c#·wpf
数据知道1 天前
MongoDB灾难恢复计划:RTO/RPO目标下的应急响应完整方案
数据库·mongodb·wpf
闻哥2 天前
深入剖析Redis数据类型与底层数据结构
java·jvm·数据结构·spring boot·redis·面试·wpf
yatum_20142 天前
Hadoop 三种核心运行模式(伪分布式/分布式/混合模式)全总结
hadoop·分布式·wpf
有技巧搬砖2 天前
基于WPF MVVM的流程编排状态机引擎上位机
wpf·状态机·流程步骤
Wiktok2 天前
WPF核心UI组件的功能、使用场景和基础示例
ui·wpf
Wiktok2 天前
WPF文件命名的核心规则
wpf
Wiktok2 天前
WPF.XAML文件属性解析
wpf
Wiktok2 天前
WPF 中的 <Window> 和 <Application>根级标签讲解
wpf