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

八、结语

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

相关推荐
七夜zippoe2 小时前
DolphinDB在工业物联网中的优势
物联网·wpf·工业物联网·优势·dolphindb
heimeiyingwang5 小时前
【架构实战】观察者模式在分布式系统中的应用
观察者模式·架构·wpf
bugcome_com8 小时前
WPF + Microsoft.ToolKit.Mvvm 技术指南与实战项目
microsoft·wpf
武藤一雄1 天前
WPF中逻辑树(Logical Tree)与可视化树(Visual Tree)到底是什么
microsoft·c#·.net·wpf·.netcore
炸炸鱼.1 天前
ELK 企业级日志分析系统完整部署手册
elk·wpf
Mr_pyx2 天前
微服务可观测性实战:分布式链路追踪从入门到精通
wpf
c#上位机3 天前
wpf附加事件
wpf
玖笙&3 天前
✨WPF编程进阶【9.1】:WPF资源完全指南(附源码)
c++·c#·wpf·visual studio
想你依然心痛3 天前
HarmonyOS 6(API 23)分布式实战:基于悬浮导航与沉浸光感的“光影协创“跨设备白板系统
分布式·wpf·harmonyos·悬浮导航·沉浸光感
c#上位机5 天前
wpf路由事件
wpf