环境
jdk:1.7
jedis:2.6.0
事务
在jedis
为了使用事务,你需要把操作包裹在事务块中,这和管道非常类似:
jedis.watch (key1, key2, ...);
Transaction t = jedis.multi();
t.set("foo", "bar");
t.exec();
注意:当你有返回值的方法时,你需要这样做:
Transaction t = jedis.multi();
t.set("fool", "bar");
Response<String> result1 = t.get("fool");
t.zadd("foo", 1, "barowitch");
t.zadd("foo", 0, "barinsky");
t.zadd("foo", 0, "barikoviev");
// get the entire sortedset
Response<Set<String>> sose = t.zrange("foo", 0, -1);
// dont forget it
t.exec();
// use Response.get() to retrieve things from a Response
String foolbar = result1.get();
// on sose.get() you can directly call Set methods!
int soseSize = sose.get().size();
// you could still get all results at once, as before
// List<Object> allResults = t.exec();
注意:
在执行
t.exec()
被执行之前response
对象不包括结果。没有执行exec
方法将会抛出异常redis.clients.jedis.exceptions.JedisDataException
,在上面代码的最后一行,你将看到在版本2之前是如何处理事务/管道
。你现在仍然可以使用这个方法,但是接着你需要从列表中提取对象,其中还包含redis
状态信息。
注意2:
redis
不允许在同一个事务中的使用中间结果。下面的代码不会工作
// this does not work! Intra-transaction dependencies are not supported by Redis!
jedis.watch(...);
Transaction t = jedis.multi();
if(t.get("key1").equals("something"))
t.set("key2", "value2");
else
t.set("key", "value");
However, there are some commands like setnx, that include such a conditional execution. Those are of course supported within transactions. You can build your own customized commands using eval/ LUA scripting.
Pipelining 管道
有时你需要发送一堆不同命令。使用管道,这么做会非常酷,这种方式会有非常好的性能。这种方式发送的命令不会进行等待响应,并且你会在最后读取到响应,这样非常快。
具体该怎么做呢?:
Pipeline p = jedis.pipelined();
p.set("fool", "bar");
p.zadd("foo", 1, "barowitch"); p.zadd("foo", 0, "barinsky"); p.zadd("foo", 0, "barikoviev");
Response<String> pipeString = p.get("fool");
Response<Set<String>> sose = p.zrange("foo", 0, -1);
p.sync();
int soseSize = sose.get().size();
Set<String> setBack = sose.get();
我做了下打印:
public static void pipelined(){
JedisPool pool = new JedisPool(new JedisPoolConfig(), "192.168.116.19");
try(Jedis jedis = pool.getResource()){
jedis.flushDB();
Pipeline p = jedis.pipelined();
p.set("fool", "bar");
p.zadd("foo", 1, "barowitch");
p.zadd("foo", 0, "barinsky");
p.zadd("foo", 0, "barikoviev");
Response<String> pipeString = p.get("fool");
Response<Set<String>> sose = p.zrange("foo", 0, -1);
p.sync();
//这里一定要注意
//该段代码不能再p.sync()方法之前,否则报错
String pp = pipeString.get();
System.out.println(pp);
int soseSize = sose.get().size();
System.out.println(soseSize);
Set<String> setBack = sose.get();
System.out.println(setBack);
}
}
注意:pipeString.get()
这个是获取结果,所以肯定是先执行了才会有结果,即:必须要在p.sync()
之后,否则报错:
Please close pipeline or multi block before calling this method.
更多的详情请查看 事务 章节部分中的代码注释。
Publish/Subscribe 发布/订阅
在jedis
中订阅一个频道,需要创建一个JedisPubSub
并且在该jedis
实例中调用subscribe
方法:
class MyListener extends JedisPubSub {
public void onMessage(String channel, String message) {
}
public void onSubscribe(String channel, int subscribedChannels) {
}
public void onUnsubscribe(String channel, int subscribedChannels) {
}
public void onPSubscribe(String pattern, int subscribedChannels) {
}
public void onPUnsubscribe(String pattern, int subscribedChannels) {
}
public void onPMessage(String pattern, String channel,
String message) {
}
}
MyListener l = new MyListener();
jedis.subscribe(l, "foo");
注意:订阅是一个阻塞操作,因为其会在线程中轮循jedis
调用subscribe
的响应。一个JedisPubSub
实例可以被订阅多个频道。你可以在现有的JedisPubSub
实例中调用subscribe
和psubscribe
来改变你的订阅。