Java 使用 Jedis 操作 Redis 各种数据类型详解
在现代应用中,Redis 已成为高性能缓存与数据存储的重要工具。本文将通过 Java 中广泛使用的 Jedis 客户端,系统性地介绍如何操作 Redis 支持的多种数据结构,包括:
- String(字符串)
- List(列表)
- Set(集合)
- Hash(哈希)
- ZSet(有序集合)
- Bitmap(位图)
- HyperLogLog(基数估计)
- Stream(流)
- Geospatial(地理位置)
- Pub/Sub(发布订阅)
本文不仅涵盖每种数据类型的基本操作,还附带完整示例代码和注释,方便开发者快速掌握 Jedis 的使用方法。
一、环境准备
Maven 引入 Jedis 依赖
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.0.0</version>
</dependency>
二、连接 Redis
import redis.clients.jedis.Jedis;
public class RedisExample {
public static void main(String[] args) {
// 连接到本地 Redis 服务
Jedis jedis = new Jedis("localhost");
System.out.println("Connection to server successfully");
// 检查 Redis 服务是否可用
System.out.println("Server is running: " + jedis.ping());
}
}
三、数据类型操作
1. String(字符串)
字符串是 Redis 中最基本的数据类型,支持设置、获取、追加、递增等操作。
// 设置字符串
jedis.set("name", "Alice");
// 获取字符串
String name = jedis.get("name");
System.out.println("Stored string in redis: " + name);
// 递增操作
jedis.set("counter", "1");
jedis.incr("counter");
String counter = jedis.get("counter");
System.out.println("Counter value in redis: " + counter);
// 追加操作
jedis.append("name", " Wonderland");
String fullName = jedis.get("name");
System.out.println("Full name in redis: " + fullName);
// 获取字符串长度
long length = jedis.strlen("name");
System.out.println("Length of 'name': " + length);
2. List(列表)
列表是一种链表结构,支持从头部或尾部插入和移除元素。
// 将值插入列表
jedis.lpush("fruits", "apple");
jedis.lpush("fruits", "banana");
jedis.rpush("fruits", "cherry");
// 获取列表中的所有值
List<String> fruits = jedis.lrange("fruits", 0, -1);
System.out.println("Stored list in redis: " + fruits);
// 移出并获取列表的第一个元素
String firstFruit = jedis.lpop("fruits");
System.out.println("First fruit: " + firstFruit);
// 移出并获取列表的最后一个元素
String lastFruit = jedis.rpop("fruits");
System.out.println("Last fruit: " + lastFruit);
// 获取列表长度
long listLength = jedis.llen("fruits");
System.out.println("List length: " + listLength);
3. Set(集合)
集合是一种无序、不可重复的元素集合,适合去重场景。
// 向集合添加元素
jedis.sadd("animals", "dog");
jedis.sadd("animals", "cat");
jedis.sadd("animals", "lion");
// 获取集合中的所有元素
Set<String> animals = jedis.smembers("animals");
System.out.println("Stored set in redis: " + animals);
// 判断元素是否存在
boolean isMember = jedis.sismember("animals", "cat");
System.out.println("Is 'cat' in set: " + isMember);
// 获取集合大小
long setSize = jedis.scard("animals");
System.out.println("Set size: " + setSize);
// 移除集合中的一个元素
jedis.srem("animals", "lion");
Set<String> updatedAnimals = jedis.smembers("animals");
System.out.println("Updated set in redis: " + updatedAnimals);
4. Hash(哈希)
哈希是键值对的集合,适合存储对象。
// 设置哈希字段
jedis.hset("user:1000", "name", "John Doe");
jedis.hset("user:1000", "email", "john@example.com");
// 获取字段值
String userName = jedis.hget("user:1000", "name");
System.out.println("Stored hash field value in redis: " + userName);
// 获取全部字段
Map<String, String> user = jedis.hgetAll("user:1000");
System.out.println("User info: " + user);
// 删除字段
jedis.hdel("user:1000", "email");
Map<String, String> updatedUser = jedis.hgetAll("user:1000");
System.out.println("Updated user info: " + updatedUser);
// 获取哈希长度
long hashSize = jedis.hlen("user:1000");
System.out.println("Hash size: " + hashSize);
5. ZSet(有序集合)
有序集合为每个元素关联一个 score,支持排序查询。
// 添加元素及分数
jedis.zadd("leaderboard", 100, "player1");
jedis.zadd("leaderboard", 200, "player2");
jedis.zadd("leaderboard", 150, "player3");
// 获取排序结果
Set<String> leaderboard = jedis.zrange("leaderboard", 0, -1);
System.out.println("Stored zset in redis: " + leaderboard);
// 获取分数
Set<Tuple> leaderboardWithScores = jedis.zrangeWithScores("leaderboard", 0, -1);
for (Tuple tuple : leaderboardWithScores) {
System.out.println("Element: " + tuple.getElement() + ", Score: " + tuple.getScore());
}
// 获取数量
long zsetSize = jedis.zcard("leaderboard");
System.out.println("ZSet size: " + zsetSize);
// 获取指定成员分数
double score = jedis.zscore("leaderboard", "player2");
System.out.println("Score of player2: " + score);
// 删除成员
jedis.zrem("leaderboard", "player1");
Set<String> updatedLeaderboard = jedis.zrange("leaderboard", 0, -1);
System.out.println("Updated zset in redis: " + updatedLeaderboard);
6. Bitmap(位图)
Bitmap 是一种高效存储布尔值的方式,常用于用户打点、签到等场景。
// 设置位图
jedis.setbit("bitmap", 7, true);
jedis.setbit("bitmap", 10, true);
// 获取位图
boolean bitValue1 = jedis.getbit("bitmap", 7);
boolean bitValue2 = jedis.getbit("bitmap", 10);
boolean bitValue3 = jedis.getbit("bitmap", 8);
System.out.println("Bit value at position 7: " + bitValue1);
System.out.println("Bit value at position 10: " + bitValue2);
System.out.println("Bit value at position 8: " + bitValue3);
// 统计位为 1 的数量
long bitCount = jedis.bitcount("bitmap");
System.out.println("Number of bits set to 1: " + bitCount);
7. HyperLogLog(基数统计)
HyperLogLog 是一种用于估算唯一元素数量的算法,精度略有误差但节省空间。
// 添加元素
jedis.pfadd("hll", "elem1");
jedis.pfadd("hll", "elem2");
jedis.pfadd("hll", "elem3");
// 获取估算值
long hllCount = jedis.pfcount("hll");
System.out.println("Stored HyperLogLog count in redis: " + hllCount);
// 合并多个 HyperLogLog
jedis.pfadd("hll2", "elem4");
jedis.pfmerge("hll_merged", "hll", "hll2");
long mergedHllCount = jedis.pfcount("hll_merged");
System.out.println("Merged HyperLogLog count in redis: " + mergedHllCount);
8. Stream(流)
Redis Stream 用于消息队列场景,支持 ID 顺序、消费者组等功能。
import java.util.HashMap;
import java.util.Map;
import redis.clients.jedis.StreamEntryID;
import redis.clients.jedis.resps.StreamEntry;
// 添加条目
Map<String, String> streamEntry = new HashMap<>();
streamEntry.put("field1", "value1");
streamEntry.put("field2", "value2");
StreamEntryID id = jedis.xadd("stream", StreamEntryID.NEW_ENTRY, streamEntry);
System.out.println("Added stream entry with ID: " + id);
// 读取条目
List<StreamEntry> entries = jedis.xrange("stream", null, null, 10);
for (StreamEntry entry : entries) {
System.out.println("Stream entry: " + entry);
}
// 删除条目
jedis.xdel("stream", id);
List<StreamEntry> updatedEntries = jedis.xrange("stream", null, null, 10);
System.out.println("Updated stream entries: " + updatedEntries);
9. Geospatial(地理空间)
地理空间数据类型支持存储经纬度坐标、计算距离和范围查询。
// 添加位置
jedis.geoadd("geo", 13.361389, 38.115556, "Palermo");
jedis.geoadd("geo", 15.087269, 37.502669, "Catania");
// 计算距离
Double distance = jedis.geodist("geo", "Palermo", "Catania", "km");
System.out.println("Distance between Palermo and Catania: " + distance + " km");
// 获取位置坐标
List<GeoCoordinate> coordinates = jedis.geopos("geo", "Palermo", "Catania");
for (GeoCoordinate coordinate : coordinates) {
System.out.println("Coordinate: " + coordinate);
}
// 查询指定范围内的位置
List<GeoRadiusResponse> radiusResponses = jedis.georadius("geo", 15, 37, 200, GeoUnit.KM);
for (GeoRadiusResponse response : radiusResponses) {
System.out.println("GeoRadiusResponse: " + response.getMemberByString());
}
10. 发布/订阅(Pub/Sub)
Pub/Sub 模式适用于广播通知、实时消息分发等场景。
发布消息:
jedis.publish("channel", "Hello, Redis!");
订阅频道:
import redis.clients.jedis.JedisPubSub;
JedisPubSub jedisPubSub = new JedisPubSub() {
@Override
public void onMessage(String channel, String message) {
System.out.println("Received message: " + message + " from channel: " + channel);
}
};
// 启动订阅线程
new Thread(() -> {
Jedis jedisSubscriber = new Jedis("localhost");
jedisSubscriber.subscribe(jedisPubSub, "channel");
}).start();
结语
通过本指南,你可以全面掌握使用 Java 和 Jedis 操作 Redis 各种数据类型的核心方法。根据你的业务需求,可以进一步封装工具类或集成到 Spring Boot 项目中,实现更复杂的缓存和消息处理逻辑。
如需进一步提升 Redis 使用效率,建议关注连接池(如 JedisPool)、分布式锁、缓存穿透/击穿处理等高级话题。