“Jedis 的编程实践”的版本间差异

来自Wikioe
跳到导航 跳到搜索
第413行: 第413行:
[main|ZSetDemo.operateZset] |>jedis.zrange(): [u11, u12, u13]
[main|ZSetDemo.operateZset] |>jedis.zrange(): [u11, u12, u13]
</syntaxhighlight>
</syntaxhighlight>
== JedisPool连接池的实践 ==

2021年11月6日 (六) 06:54的版本


关于

Jedis 是一个高性能的 Java 客户端,是 Redis 官方推荐的 Java 开发工具。要在 Java 开发中访问 Redis 缓存服务器,必须对 Jedis 熟悉才能编写出“漂亮”的代码。

Jedis 的项目地址:https://github.com/alphazero/jredis


使用Jedis,可以在 Maven 的 pom 文件中,增加以下依赖:

<dependency>
   <groupId>redis.clients</groupId>
   <artifactId>jedis</artifactId>
   <version>${redis.version}</version>
</dependency>


Jedis 基本的使用十分简单:

  • 在每次使用时,构建 Jedis 对象即可。
  • 一个 Jedis 对象代表一条和 Redis 服务进行连接的 Socket 通道。
  • 使用完 Jedis 对象之后,需要调用 Jedis.close() 方法把连接关闭,否则会占用系统资源。


创建 Jedis 对象时,可以指定 Redis 服务的 host,port 和 password。大致的伪代码如下:

Jedis jedis = new Jedis("localhost", 6379);    // 指定Redis服务的主机和端口
jedis.auth("xxxx");    // 如果Redis服务连接需要密码,就设置密码

...   // 访问Redis服务

jedis.close();    // 使用完,就关闭连接

基础实践

Jedis 的 String操作函数、List操作函数、Hash操作函数、Set操作函数、Zset操作函数,和 Redis 客户端的相关操作命令,基本上可以一比一的相互对应。

Jedis 操作 String(字符串)

示例:

package com.crazymakercircle.redis.jedis;
//...省略import
public class StringDemo {
	/**
	* Jedis字符串数据类型的相关命令
	*/
	@Test
	public void operateString() {
		Jedis jedis = new Jedis("localhost", 6379);
		//如果返回 pong 代表链接成功
		Logger.info("jedis.ping():" + jedis.ping());
		//设置key0的值为 123456
		jedis.set("key0", "123456");
		
		//返回数据类型:string
		Logger.info("jedis.type(key0): " + jedis.type("key0"));
		//取得值
		Logger.info("jedis.get(key0): " + jedis.get("key0"));
		// key是否存在
		Logger.info("jedis.exists(key0):" + jedis.exists("key0"));
		//返回key的长度
		Logger.info("jedis.strlen(key0): " + jedis.strlen("key0"));
		//返回截取字符串, 范围“0,-1”表示截取全部
		Logger.info("jedis.getrange(key0): " + jedis.getrange("key0", 0, -1));
		//返回截取字符串, 范围“1,4”表示区间[1,4]
		Logger.info("jedis.getrange(key0): " + jedis.getrange("key0", 1, 4));
		//追加字符串
		Logger.info("jedis.append(key0): " + jedis.append("key0", "appendStr"));
		Logger.info("jedis.get(key0): " + jedis.get("key0"));
		
		//重命名
		jedis.rename("key0", "key0_new");
		//判断key 是否存在
		Logger.info("jedis.exists(key0): " + jedis.exists("key0"));
		
		//批量插入
		jedis.mset("key1", "val1", "key2", "val2", "key3", "100");		
		//批量取出
		Logger.info("jedis.mget(key1,key2,key3): " + jedis.mget("key1", "key2", "key3"));
		
		//删除
		Logger.info("jedis.del(key1): " + jedis.del("key1"));
		Logger.info("jedis.exists(key1): " + jedis.exists("key1"));
		
		//取出旧值并设置新值
		Logger.info("jedis.getSet(key2): " + jedis.getSet("key2", "value3"));
		//自增1
		Logger.info("jedis.incr(key3): " + jedis.incr("key3"));
		//自增15
		Logger.info("jedis.incrBy(key3): " + jedis.incrBy("key3", 15));
		//自减1
		Logger.info("jedis.decr(key3): " + jedis.decr("key3"));
		//自减15
		Logger.info("jedis.decrBy(key3): " + jedis.decrBy("key3", 15));
		//浮点数加
		Logger.info("jedis.incrByFloat(key3): " + jedis.incrByFloat("key3", 1.1));
		
		//返回0 只有在key不存在的时候才设置
		Logger.info("jedis.setnx(key3): " + jedis.setnx("key3", "existVal"));
		Logger.info("jedis.get(key3): " + jedis.get("key3"));// 3.1
		
		//只有key都不存在的时候才设置,这里返回 null
		Logger.info("jedis.msetnx(key2,key3): " + jedis.msetnx("key2", "exists1", "key3", "exists2"));
		Logger.info("jedis.mget(key2,key3): " + jedis.mget("key2", "key3"));
		
		//设置key,2 秒后失效
		jedis.setex("key4", 2, "2 seconds is no Val");
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		// 2 seconds is no Val
		Logger.info("jedis.get(key4): " + jedis.get("key4"));
		
		jedis.set("key6", "123456789");
		//第三位之后,用新值覆盖旧值(下标从0开始)
		jedis.setrange("key6", 3, "abcdefg");
		//返回:123abcdefg
		Logger.info("jedis.get(key6): " + jedis.get("key6"));
		
		//返回所有匹配的key
		Logger.info("jedis.get(key*): " + jedis.keys("key*")); 
		
		// 关闭连接
		jedis.close();
	}
}

Jedis 操作 List(列表)

示例:

package com.crazymakercircle.redis.jedis;
//...
public class ListDemo {
	/**
	* Redis列表是简单的字符串列表,按照插入顺序排序。
	*/
	@Test
	public void operateList() {
		Jedis jedis = new Jedis("localhost");
		Logger.info("jedis.ping(): " +jedis.ping());
		
		jedis.del("list1");
		//从list列表尾部添加3个元素
		jedis.rpush("list1", "zhangsan", "lisi", "wangwu");
		
		//取得类型:list
		Logger.info("jedis.type(): " +jedis.type("list1"));
		
		//遍历区间[0,-1],取得全部的元素
		Logger.info("jedis.lrange(0,-1): " +jedis.lrange("list1", 0, -1));
		//遍历区间[1,2],取得区间的元素
		Logger.info("jedis.lrange(1,2): " +jedis.lrange("list1", 1, 2));
		
		//获取list列表的长度
		Logger.info("jedis.llen(list1): " +jedis.llen("list1"));
		//获取下标为 1 的元素
		Logger.info("jedis.lindex(list1,1): " +jedis.lindex("list1", 1));
		//左侧弹出元素
		Logger.info("jedis.lpop(): " +jedis.lpop("list1"));
		//右侧弹出元素
		Logger.info("jedis.rpop(): " +jedis.rpop("list1"));
		//设置下标为0的元素val
		jedis.lset("list1", 0, "lisi2");
		//最后,遍历区间[0,-1],取得全部的元素
		Logger.info("jedis.lrange(0,-1): " +jedis.lrange("list1", 0, -1));
		
		// 关闭连接
		jedis.close();
	}
}
运行结果:
[main|ListDemo.operateList] |>jedis.ping(): PONG
[main|ListDemo.operateList] |>jedis.type(): list
[main|ListDemo.operateList] |>jedis.lrange(0,-1): [zhangsan, lisi, wangwu]
[main|ListDemo.operateList] |>jedis.lrange(1,2): [lisi, wangwu]
[main|ListDemo.operateList] |>jedis.llen(list1): 3
[main|ListDemo.operateList] |>jedis.lindex(list1,1): lisi
[main|ListDemo.operateList] |>jedis.lpop(): zhangsan
[main|ListDemo.operateList] |>jedis.rpop(): wangwu
[main|ListDemo.operateList] |>jedis.lrange(0,-1): [lisi2]

Jedis 操作 Hash(哈希表)

示例:

package com.crazymakercircle.redis.jedis;
//…
public class HashDemo {
	/**
	* Redis hash 哈希表是一个string类型的field字段和value值的映射表,
	* hash特别适合用于存储对象。
	* Redis 中每个hash可以存储 2^32 - 1 键-值对(40多亿)
	*/
	@Test
	public void operateHash() {
		Jedis jedis = new Jedis("localhost");
		jedis.del("config");
		
		//设置hash的 field-value对:ip=127.0.0.1
		jedis.hset("config", "ip", "127.0.0.1");
		//取得hash的 field关联的value值
		Logger.info("jedis.hget(): " + jedis.hget("config", "ip"));
		
		//取得类型:hash
		Logger.info("jedis.type(): " + jedis.type("config"));
		
		//批量添加 field-value 对,参数为java map
		Map<String, String> configFields = new HashMap<String, String>();
		configFields.put("port", "8080");
		configFields.put("maxalive", "3600");
		configFields.put("weight", "1.0");
		//执行批量添加
		jedis.hmset("config", configFields);
		
		//批量获取:取得全部 field-value 对,返回 java map映射表
		Logger.info("jedis.hgetAll(): " + jedis.hgetAll("config"));
		//批量获取:取得部分 field对应的value,返回 java map
		Logger.info("jedis.hmget(): " + jedis.hmget("config", "ip", "port"));
		
		//浮点数加: 类似于String的incrByFloat
		jedis.hincrByFloat("config", "weight", 1.2);
		Logger.info("jedis.hget(weight): " + jedis.hget("config", "weight"));
		//获取所有的 field 字段
		Logger.info("jedis.hkeys(config): " + jedis.hkeys("config"));
		//获取所有的 value 字段
		Logger.info("jedis.hvals(config): " + jedis.hvals("config"));
		
		//获取长度
		Logger.info("jedis.hlen(): " + jedis.hlen("config"));
		//判断field是否存在
		Logger.info("jedis.hexists(weight): " + jedis.hexists("config", "weight"));
		//删除一个field
		jedis.hdel("config", "weight");
		Logger.info("jedis.hexists(weight): " + jedis.hexists("config", "weight"));
		
		// 关闭连接
		jedis.close();
	}
}
运行结果:
[main|HashDemo.operateHash] |>jedis.hget(): 127.0.0.1
[main|HashDemo.operateHash] |>jedis.type(): hash
[main|HashDemo.operateHash] |>jedis.hgetAll(): {port=8080, weight=1.0, maxalive=3600, ip=127.0.0.1}
[main|HashDemo.operateHash] |>jedis.hmget(): [127.0.0.1, 8080]
[main|HashDemo.operateHash] |>jedis.hget(): 2.2
[main|HashDemo.operateHash] |>jedis.hkeys(): [weight, maxalive, port, ip]
[main|HashDemo.operateHash] |>jedis.hvals(): [127.0.0.1, 8080, 2.2, 3600]
[main|HashDemo.operateHash] |>jedis.hlen(): 4
[main|HashDemo.operateHash] |>jedis.hexists(weight): true
[main|HashDemo.operateHash] |>jedis.hexists(weight): false

Jedis 操作 Set(集合)

示例:

package com.crazymakercircle.redis.jedis;
//....省略import
public class SetDemo {
	/**
	* Redis 的 Set集合是 String 类型的无序集合。
	* 集合成员是唯一的,集合中不能出现重复的元素。
	* Set集合是通过哈希表实现的,添加,删除,查找的复杂度都是 O(1)。
	*/
	@Test
	public void operateSet() {
		Jedis jedis = new Jedis("localhost");
		jedis.del("set1");
		Logger.info("jedis.ping(): " + jedis.ping());
		Logger.info("jedis.type(): " + jedis.type("set1"));
		
		//sadd函数: 向集合添加元素
		jedis.sadd("set1", "user01", "user02", "user03");
		//smembers函数: 遍历所有元素
		Logger.info("jedis.smembers(): " + jedis.smembers("set1"));
		//scard函数: 获取集合元素个数
		Logger.info("jedis.scard(): " + jedis.scard("set1"));
		//sismember判断是否是集合元素
		Logger.info("jedis.sismember(user04): " + jedis.sismember("set1", "user04"));
		//srem函数:移除元素
		Logger.info("jedis.srem(): " + jedis.srem("set1", "user02", "user01"));
		//smembers函数: 遍历所有元素
		Logger.info("jedis.smembers(): " + jedis.smembers("set1"));
		
		// 关闭连接
		jedis.close();
	}
}
运行结果:
[main|SetDemo.operateSet] |>jedis.ping(): PONG
[main|SetDemo.operateSet] |>jedis.type(): none
[main|SetDemo.operateSet] |>jedis.smembers(): [user02, user03, user01]
[main|SetDemo.operateSet] |>jedis.scard(): 3
[main|SetDemo.operateSet] |>jedis.sismember(user04): false
[main|SetDemo.operateSet] |>jedis.srem(): 2
[main|SetDemo.operateSet] |>jedis.smembers(): [user03]

Jedis 操作 Zset(有序集合)

示例:

有一个 salary 薪资的 Zset 有序集合,Zset 的 Key 键为用户id,Zset 的 score 分数值保存的是用户的薪资:
package com.crazymakercircle.redis.jedis;
//...
public class ZSetDemo {
	/**
	* Zset有序集合和Set集合都是string类型元素的集合,且不允许重复的元素。
	* 不同的是Zset的每个元素都会关联一个double类型的分数,用于从小到大进行排序。
	* 集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。
	* 集合中最大的成员数为 2^32 - 1 (4294967295, 每个集合可存储40多亿个元素)。
	*/
	@Test
	public void operateZset() {
		Jedis jedis = new Jedis("localhost");
		Logger.info("jedis.ping(): " + jedis.ping());
		
		jedis.del("salary");
		
		Map<String, Double> members = new HashMap<String, Double>();
		members.put("u01", 1000.0);
		members.put("u02", 2000.0);
		members.put("u03", 3000.0);
		members.put("u04", 13000.0);
		members.put("u05", 23000.0);
		//批量添加元素,类型为java map映射表
		jedis.zadd("salary", members);
		
		//type类型:Zset
		Logger.info("jedis.type(): " + jedis.type("salary"));
		
		//获取集合元素的个数
		Logger.info("jedis.zcard(): " + jedis.zcard("salary"));
		//按照下标[起,止]遍历元素
		Logger.info("jedis.zrange(): " + jedis.zrange("salary", 0, -1));
		//按照下标[起,止]倒序遍历元素
		Logger.info("jedis.zrevrange(): " + jedis.zrevrange("salary", 0, -1));
		
		//按照分数(薪资)[起,止]遍历元素
		Logger.info("jedis.zrangeByScore(): " + jedis.zrangeByScore("salary", 1000, 10000));
		//按照薪资[起,止]遍历元素,带分数返回
		Set<Tuple> res0 = jedis.zrangeByScoreWithScores("salary", 1000, 10000);
		for (Tuple temp : res0) {
			Logger.info("Tuple.get(): " + temp.getElement() + " -> " + temp.getScore());
		}
		//按照分数[起,止]倒序遍历元素
		Logger.info("jedis.zrevrangeByScore(): " + jedis.zrevrangeByScore("salary", 1000, 4000));
		
		//获取元素[起,止]分数区间的元素数量
		Logger.info("jedis.zcount(): " + jedis.zcount("salary", 1000, 4000));
		
		//获取元素score值:薪资
		Logger.info("jedis.zscore(): " + jedis.zscore("salary", "u01"));
		//获取元素的下标
		Logger.info("jedis.zrank(u01): " + jedis.zrank("salary", "u01"));
		//倒序获取元素的下标
		Logger.info("jedis.zrevrank(u01): " + jedis.zrevrank("salary", "u01"));
		
		//删除元素
		Logger.info("jedis.zrem(): " + jedis.zrem("salary", "u01", "u02"));
		//删除元素,通过下标范围
		Logger.info("jedis.zremrangeByRank(): " +
		jedis.zremrangeByRank("salary", 0, 1));
		//删除元素,通过分数范围
		Logger.info("jedis.zremrangeByScore(): " + jedis.zremrangeByScore("salary", 20000, 30000));
		//按照下标[起,止]遍历元素
		Logger.info("jedis.zrange(): " + jedis.zrange("salary", 0, -1));
		
		Map<String, Double> members2 = new HashMap<String, Double>();
		members2.put("u11", 1136.0);
		members2.put("u12", 2212.0);
		members2.put("u13", 3324.0);
		//批量添加元素
		jedis.zadd("salary", members2);
		//增加指定分数
		Logger.info("jedis.zincrby(10000): " + jedis.zincrby("salary", 10000, "u13"));
		//按照下标[起,止]遍历元素
		Logger.info("jedis.zrange(): " + jedis.zrange("salary", 0, -1));
		
		// 关闭连接
		jedis.close();
	}
}
运行结果:
[main|ZSetDemo.operateZset] |>jedis.ping(): PONG
[main|ZSetDemo.operateZset] |>jedis.type(): zset
[main|ZSetDemo.operateZset] |>jedis.zcard(): 5
[main|ZSetDemo.operateZset] |>jedis.zrange(): [u01, u02, u03, u04, u05]
[main|ZSetDemo.operateZset] |>jedis.zrangeByScore(): [u01, u02, u03]
[main|ZSetDemo.operateZset] |>Tuple.get(): u01 -> 1000.0
[main|ZSetDemo.operateZset] |>Tuple.get(): u02 -> 2000.0
[main|ZSetDemo.operateZset] |>Tuple.get(): u03 -> 3000.0
[main|ZSetDemo.operateZset] |>jedis.zrevrange(): [u05, u04, u03, u02, u01]
[main|ZSetDemo.operateZset] |>jedis.zrevrangeByScore(): []
[main|ZSetDemo.operateZset] |>jedis.zscore(): 1000.0
[main|ZSetDemo.operateZset] |>jedis.zcount(): 3
[main|ZSetDemo.operateZset] |>jedis.zrank(u01): 0
[main|ZSetDemo.operateZset] |>jedis.zrevrank(u01): 4
[main|ZSetDemo.operateZset] |>jedis.zrem(): 2
[main|ZSetDemo.operateZset] |>jedis.zremrangeByRank(): 2
[main|ZSetDemo.operateZset] |>jedis.zremrangeByScore(): 1
[main|ZSetDemo.operateZset] |>jedis.zrange(): []
[main|ZSetDemo.operateZset] |>jedis.get(): 13324.0
[main|ZSetDemo.operateZset] |>jedis.zrange(): [u11, u12, u13]

JedisPool连接池的实践