Redis的java客户端Jedis的使用
标签(空格分隔): 未分类
一、Jedis简介和使用
使用Jedis提供的JavaAPI对Redis进行操作,是Redis官方推崇的方式;并且,使用Jedis提供的对Redis的支持也最为灵活、全面;不足之处,就是编码复杂度较高。
- 入门使用:
下载Jedis的依赖包jedis-2.1.0.jar,然后将其添加到classpath下面。然后,即可进行编程。
定义连接:Redis暂时不要设置登录密码
Jedis jedis = new Jedis("192.168.142.12");
进行键值存储:
jedis.set("country", "China");
获取value值:
String country = jedis.get("country");
删除key:
jedis.del("country");
- 使用连接池:
添加依赖包commons-pool.jar,注意不要选择高版本,以免不必要的错误。
配置属性文件:redis.properties
redis.host=192.168.142.12 #Redis服务器地址
redis.port=6379 #服务端口
redis.timeout=3000 #超时时间:单位ms
redis.password=nick123 #授权密码
redis.pool.maxActive=200 #最大连接数:能够同时建立的“最大链接个数”
redis.pool.maxIdle=20 #最大空闲数:空闲链接数大于maxIdle时,将进行回收
redis.pool.minIdle=5 #最小空闲数:低于minIdle时,将创建新的链接
redis.pool.maxWait=3000 #最大等待时间:单位ms
redis.pool.testOnBorrow=true #使用连接时,检测连接是否成功
redis.pool.testOnReturn=true #返回连接时,检测连接是否成功
加载属性文件:redis.properties
ResourceBundle bundle = ResourceBundle.getBundle("redis");
创建配置对象:
JedisPoolConfig config = new JedisPoolConfig();
String host = bundle.getString("redis.host");
...
config.setMaxActive(Integer.valueOf(bundle.getString("redis.pool.maxActive")));
...
config.setTestOnBorrow(Boolean.valueOf(bundle.getString("redis.pool.testOnBorrow")));
...
创建Jedis连接池:
JedisPool pool = new JedisPool(config, host, port, timeout, password);
- 使用方式:
从连接池获取Jedis对象:
Jedis jedis = pool.getResource();
基本操作:
jedis.set("province", "shannxi");
String province = jedis.get("province");
jedis.del("province");
将Jedis对象归还给连接池:
pool.returnResource(jedis);
二、Jedis使用详解
- jedis简单测试
package com.kang.redis;
import redis.clients.jedis.Jedis;
public class JedisDemo {
public static void main(String[] args) {
// 构造jedis对象
Jedis jedis = new Jedis("127.0.0.1", 6379);
// 向redis中添加数据
jedis.set("mytest", "123");
// 从redis中读取数据
String value = jedis.get("mytest");
System.out.println(value);
// 关闭连接
jedis.close();
}
}
- jedis连接池测试
package com.kang.redis;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class JedisPoolDemo {
public static void main(String[] args) {
// 构建连接池配置信息
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
// 设置最大连接数
jedisPoolConfig.setMaxTotal(50);
// 构建连接池
JedisPool jedisPool = new JedisPool(jedisPoolConfig, "127.0.0.1", 6379);
// 从连接池中获取连接
Jedis jedis = jedisPool.getResource();
// 读取数据
System.out.println(jedis.get("mytest"));
// 将连接还回到连接池中
jedisPool.returnResource(jedis);
// 释放连接池
jedisPool.close();
}
}
- jedis设置集群连接池
package com.kang.redis;
import java.util.ArrayList;
import java.util.List;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;
/**
* 集群式的连接池
*
*/
public class ShardedJedisPoolDemo {
public static void main(String[] args) {
// 构建连接池配置信息
JedisPoolConfig poolConfig = new JedisPoolConfig();
// 设置最大连接数
poolConfig.setMaxTotal(50);
// 定义集群信息
List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();
shards.add(new JedisShardInfo("127.0.0.1", 6379));
//可以加入其他集群的jedis端口
// 定义集群连接池
ShardedJedisPool shardedJedisPool = new ShardedJedisPool(poolConfig, shards);
ShardedJedis shardedJedis = null;
try {
// 从连接池中获取到jedis分片对象
shardedJedis = shardedJedisPool.getResource();
// 从redis中获取数据
String value = shardedJedis.get("mytest");
System.out.println(value);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != shardedJedis) {
// 关闭,检测连接是否有效,有效则放回到连接池中,无效则重置状态
shardedJedis.close();
}
}
// 关闭连接池
shardedJedisPool.close();
}
}
- 一个jedis的工具类
package com.kang.redis;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class RedisUtil {
protected Logger log = LoggerFactory.getLogger(getClass());
/**
* 私有构造器.
*/
private RedisUtil() {
}
private static Map<String,JedisPool> maps = new HashMap<String,JedisPool>();
/**
* 获取连接池.
* @return 连接池实例
*/
static JedisPool getPool(String ip,int port) {
String key = ip+":" +port;
JedisPool pool = null;
if(!maps.containsKey(key)) {
JedisPoolConfig config = new JedisPoolConfig();
config.setTestOnBorrow(true);
config.setTestOnReturn(true);
try{
/**
*如果你遇到 java.net.SocketTimeoutException: Read timed out exception的异常信息
*请尝试在构造JedisPool的时候设置自己的超时值. JedisPool默认的超时时间是2秒(单位毫秒)
*/
pool = new JedisPool(config, ip, port);
maps.put(key, pool);
} catch(Exception e) {
e.printStackTrace();
}
}else{
pool = maps.get(key);
}
return pool;
}
/**
*类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例
*没有绑定关系,而且只有被调用到时才会装载,从而实现了延迟加载。
*/
private static class RedisUtilHolder{
/**
* 静态初始化器,由JVM来保证线程安全
*/
private static RedisUtil instance = new RedisUtil();
}
/**
*当getInstance方法第一次被调用的时候,它第一次读取
*RedisUtilHolder.instance,导致RedisUtilHolder类得到初始化;而这个类在装载并被初始化的时候,会初始化它的静
*态域,从而创建RedisUtil的实例,由于是静态的域,因此只会在虚拟机装载类的时候初始化一次,并由虚拟机来保证它的线程安全性。
*这个模式的优势在于,getInstance方法并没有被同步,并且只是执行一个域的访问,因此延迟初始化并没有增加任何访问成本。
*/
public static RedisUtil getInstance() {
return RedisUtilHolder.instance;
}
/**
* 获取Redis实例.
* @return Redis工具类实例
*/
public static Jedis getJedis(String ip,int port) {
Jedis jedis = null;
int count =0;
do{
try{
jedis = getPool(ip,port).getResource();
//log.info("get redis master1!");
} catch (Exception e) {
// 销毁对象
getPool(ip,port).returnBrokenResource(jedis);
}
count++;
}while(jedis==null&&count<1000);
return jedis;
}
/**
* 释放redis实例到连接池.
* @param jedis redis实例
*/
public static void closeJedis(Jedis jedis,String ip,int port) {
if(jedis != null) {
getPool(ip,port).returnResource(jedis);
}
}
}
- 一个jedis的详细测试代码
package com.kang.redis;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.Test;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.SortingParams;
public class TestCase {
/**
* 在不同的线程中使用相同的Jedis实例会发生奇怪的错误。但是创建太多的实现也不好因为这意味着会建立很多sokcet连接,
* 也会导致奇怪的错误发生。单一Jedis实例不是线程安全的。为了避免这些问题,可以使用JedisPool,
* JedisPool是一个线程安全的网络连接池。可以用JedisPool创建一些可靠Jedis实例,可以从池中拿到Jedis的实例。
* 这种方式可以解决那些问题并且会实现高效的性能
*/
@Test
public void Hello() {
Jedis jedis = RedisUtil.getJedis("127.0.0.1",6379);
try {
// 向key-->name中放入了value-->java
jedis.set("name", "java");
String ss = jedis.get("name");
System.out.println(ss);
// 很直观,将spring append到已经有的value之后
jedis.append("name", "spring");
ss = jedis.get("name");
System.out.println(ss); //输出javasspring
// 2、直接覆盖原来的数据
jedis.set("name", "spring");
System.out.println(jedis.get("name")); //输出spring
// 删除key对应的记录
jedis.del("name");
System.out.println(jedis.get("name"));// 执行结果:null
/**
* mset相当于 jedis.set("name","java"); jedis.set("jarorwar","aaa");
*/
jedis.mset("name", "java", "jarorwar", "aaa");
System.out.println(jedis.mget("name", "jarorwar")); //输出[java, aaa]
} catch (Exception e) {
e.printStackTrace();
} finally {
RedisUtil.getPool("127.0.0.1",6379).returnResource(jedis);
}
}
@Test
public void testKey() {
Jedis jedis = RedisUtil.getJedis("127.0.0.1",6379);
System.out.println("=============key==========================");
// 清空数据
System.out.println(jedis.flushDB());
System.out.println(jedis.echo("foo")); //Echo命令用于打印给定的字符串。
// 判断key否存在
System.out.println(jedis.exists("foo")); //false
jedis.set("key", "values");
System.out.println(jedis.exists("key")); //true
}
@Test
public void testString() {
System.out.println("==String==");
Jedis jedis = RedisUtil.getJedis("127.0.0.1",6379);
try {
// String
jedis.set("key", "Hello World!");
String value = jedis.get("key");
System.out.println(value);
} catch (Exception e) {
e.printStackTrace();
} finally {
RedisUtil.getPool("127.0.0.1",6379).returnResource(jedis);
}
System.out.println("=============String==========================");
// 清空数据
System.out.println(jedis.flushDB());
// 存储数据
jedis.set("foo", "bar");
System.out.println(jedis.get("foo"));
// 若key不存在,则存储
jedis.setnx("foo", "foo not exits"); //因为key(foo)已存在,所以这里不会存储这个值
System.out.println(jedis.get("foo")); //输出foo
// 覆盖数据
jedis.set("foo", "foo update");
System.out.println(jedis.get("foo")); //foo update
// 追加数据
jedis.append("foo", " hello, world");
System.out.println(jedis.get("foo")); //foo update hello, world
// 设置key的有效期,并存储数据
jedis.setex("foo", 2, "foo not exits"); //有效期两秒
System.out.println(jedis.get("foo")); //foo not exits
try {
Thread.sleep(3000); //延时3秒,数据失效
} catch (InterruptedException e) {
}
System.out.println(jedis.get("foo")); //null
// 获取并更改数据
jedis.set("foo", "foo update");
System.out.println(jedis.getSet("foo", "foo modify")); //foo modify
System.out.println(jedis.get("foo"));//foo modify
// 截取value的值
System.out.println(jedis.getrange("foo", 1, 5)); //oo mo
System.out.println(jedis.mset("mset1", "mvalue1", "mset2", "mvalue2",
"mset3", "mvalue3", "mset4", "mvalue4"));
System.out.println(jedis.mget("mset1", "mset2", "mset3", "mset4")); //[mvalue1, mvalue2, mvalue3, mvalue4]
System.out.println(jedis.del(new String[] { "foo", "foo1", "foo3" })); //输出1,DEL命令用于删除已存在的键。不存在的 key 会被忽略。
//返回值是被删除 key 的数量。
}
@Test
public void testList() {
System.out.println("==List==");
Jedis jedis = RedisUtil.getJedis("127.0.0.1",6379);
try {
// 开始前,先移除所有的内容
jedis.del("messages");
jedis.rpush("messages", "Hello how are you?");
jedis.rpush("messages", "Fine thanks. I'm having fun with redis.");
jedis.rpush("messages", "I should look into this NOSQL thing ASAP");
// 再取出所有数据。jedis.lrange是按范围取出,
// 第一个是key,第二个是起始位置,第三个是结束位置,jedis.llen获取长度 -1表示取得所有
List<String> values = jedis.lrange("messages", 0, -1);
System.out.println(values);
} catch (Exception e) {
e.printStackTrace();
} finally {
RedisUtil.getPool("127.0.0.1",6379).returnResource(jedis);
}
// 清空数据
System.out.println(jedis.flushDB());
// 添加数据
jedis.lpush("lists", "8");
jedis.lpush("lists", "5");
jedis.lpush("lists", "9");
// 数组长度
System.out.println(jedis.llen("lists")); //3
// 排序
System.out.println(jedis.sort("lists")); //[5, 8, 9](默认升序排序)
/*
* 如果使用Redis SORT排序的不是数字,是字母,将他们按照字典的顺序排名,则需要使用 SORT key ALPHA
* 如果不加ALPHA参数,则会报错,提示:(error) ERR One or more scores can't be converted into double。
* 我们还可以使用关系型数据库的DESC进行倒序排序和LIMIT offset count来限定获取的条数
*/
// 字串
System.out.println(jedis.lrange("lists", 0, 3)); //[9, 5, 8]
/*LRANGE命令将返回存储在key列表的特定元素。偏移量开始和停止是从0开始的索引,
* 0是第一元素(该列表的头部),1是列表的下一个元素。这些偏移量也可以是表示开始在列表的末尾偏移负数。
* 例如,-1是该列表的最后一个元素,-2倒数第二个,等等。
*/
// 修改列表中单个值
jedis.lset("lists", 0, "hello list!");
System.out.println(jedis.lrange("lists", 0, 3));//[hello list!, 5, 8]
// 获取列表指定下标的值
System.out.println(jedis.lindex("lists", 1)); //5
// 删除列表指定下标的值
System.out.println(jedis.lrem("lists", 1, "vector")); //输出0
/*
* Lrem 根据参数 COUNT 的值,移除列表中与参数 VALUE 相等的元素。命令形式:LREM KEY_NAME COUNT VALUE
* COUNT 的值可以是以下几种:
* count > 0 : 从表头开始向表尾搜索,移除与 VALUE 相等的元素,数量为 COUNT 。
* count < 0 : 从表尾开始向表头搜索,移除与 VALUE 相等的元素,数量为 COUNT 的绝对值。
* count = 0 : 移除表中所有与 VALUE 相等的值。
* 返回值是被移除元素的数量。 列表不存在时返回 0 。
*/
// 删除区间以外的数据
System.out.println(jedis.ltrim("lists", 0, 1)); //ok
/*
* Ltrim 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。
* 下标 0 表示列表的第一个元素,以 1 表示列表的第二个元素,以此类推。 你也可以使用负数下标,
* 以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。命令形式: LTRIM KEY_NAME START STOP
* 返回值:命令执行成功时,返回 ok 。
*/
// 列表出栈
System.out.println(jedis.lpop("lists")); //hello list!
/*
* Lpop 命令用于移除并返回列表的第一个元素。返回值:列表的第一个元素。 当列表 key 不存在时,返回 nil 。
*/
// 整个列表值
System.out.println(jedis.lrange("lists", 0, -1)); // [5]
}
@Test
public void testSet() {
System.out.println("==Set==");
Jedis jedis = RedisUtil.getJedis("127.0.0.1",6379);
try {
jedis.sadd("myset", "1");
jedis.sadd("myset", "2");
jedis.sadd("myset", "3");
jedis.sadd("myset", "4");
Set<String> setValues = jedis.smembers("myset"); // Smembers命令返回集合中的所有的成员。 不存在的集合 key 被视为空集合。
System.out.println(setValues); //输出是无序的[3, 2, 1, 4]
// 移除noname
jedis.srem("myset", "4"); //Srem 命令用于移除集合中的一个或多个成员元素,不存在的成员元素会被忽略。当 key 不是集合类型,返回一个错误。
System.out.println(jedis.smembers("myset"));// 获取所有加入的value,输出[3, 2, 1]
System.out.println(jedis.sismember("myset", "4"));// 输出false。Sismember 命令判断成员元素是否是集合的成员。
System.out.println(jedis.scard("myset"));// 返回集合的元素个数 :3
} catch (Exception e) {
e.printStackTrace();
} finally {
RedisUtil.getPool("127.0.0.1",6379).returnResource(jedis);
}
// 清空数据
System.out.println(jedis.flushDB());
// 添加数据
jedis.sadd("sets", "HashSet");
jedis.sadd("sets", "SortedSet");
jedis.sadd("sets", "TreeSet");
// 判断value是否在列表中
System.out.println(jedis.sismember("sets", "TreeSet")); //true
// 整个列表值
System.out.println(jedis.smembers("sets")); //[SortedSet, TreeSet, HashSet]
// 删除指定元素
System.out.println(jedis.srem("sets", "SortedSet"));
// 出栈
System.out.println(jedis.spop("sets")); //Spop 命令用于移除并返回集合中的一个随机元素。
System.out.println(jedis.smembers("sets"));
//
jedis.sadd("sets1", "HashSet1");