1.Redis Java client
关于Redis Java客户端的demo可以参考我的例子:http://blog.youkuaiyun.com/caicongyang/article/details/50642979
2.Redis事务(测试结论)
1). 在Redis事务中的所有命令都将会被串行化的顺序执行(既单线程),事务执行期间,Redis不会再为其它客户端的请求提供任何服务,从而保证了事物中的所有命令被原子的执行。
2). 和关系型数据库中的事务相比,在Redis事务中如果有某一条命令执行失败,其后的命令仍然会被继续执行。
2). 和关系型数据库中的事务相比,在Redis事务中如果有某一条命令执行失败,其后的命令仍然会被继续执行。
3).调用jedis.watch(…)方法来监控key,如果调用后key值发生变化,则整个事务会执行失败。
3.命令行测试
MULTI/EXEC/DISCARD/WATCH
2.1成功执行事务
#初始化值
127.0.0.1:6379> set num 20
OK
#开启事务
127.0.0.1:6379> multi
OK
#将num增加1,可以看到redis并没有立即执行,而是加入了队列中
127.0.0.1:6379> incr num
QUEUED
#将num减去1,同样可以看到redis并没有立即执行,而是加入了队列中
127.0.0.1:6379> decr num
QUEUED
#提交执行,看到两次执行的结果
127.0.0.1:6379> exec
1) (integer) 21
2) (integer) 20
#最终确认数值正确为20
127.0.0.1:6379> get num
"20"
2.2失败执行事务
#初始化值
127.0.0.1:6379> set num 15
OK
#开启事务
127.0.0.1:6379> multi
OK
#将caicongyang减去1,可以看到redis并没有立即执行,而是加入了队列中
127.0.0.1:6379> decr caicongyang
QUEUED
#此命令为list的命令,执行应该报错!
127.0.0.1:6379> lpop caicongyang
QUEUED
#将caicongyang增加1,可以看到redis并没有立即执行,而是加入了队列中
127.0.0.1:6379> incr caicongyang
QUEUED
#执行结果,看到lpop 命令出错,其他的都正常执行
127.0.0.1:6379> exec
1) (integer) 14
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
3) (integer) 15
#最终结果也符合预期
127.0.0.1:6379> get caicongyang
"15"
2.3回滚
#初始化
127.0.0.1:6379> set num 10
OK
#开启事务
127.0.0.1:6379> multi
OK
#自增加
127.0.0.1:6379> incr num
QUEUED
#回滚
127.0.0.1:6379> discard
OK
#最终结果正确
127.0.0.1:6379> get num
"10"
127.0.0.1:6379>
3.Jedis测试demo
package com.caicongyang.redis;
import java.util.List;
import org.junit.Test;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.Transaction;
public class JedisAdvanceFeaturesDemo {
/**
* 回滚测试
*/
@Test
public void testTransaction(){
Jedis jedis = new Jedis("192.168.150.137",6379);
//---exec 执行事务队列内命令-------------
Transaction t = jedis.multi();//开始事务
t.set("husband", "Tom");
t.set("wife", "Mary");
t.exec();//执行事务
//------discard 取消执行事务内命令---------
Transaction t2 = jedis.multi();
t2.set("test", "0");
t2 = jedis.multi();
t2.set("test", "1");
t2.discard();
String husband = jedis.get("husband");
String wife = jedis.get("wife");
String test = jedis.get("test");
System.out.println("husband:" + husband);
System.out.println("wife:" + wife);
System.out.println("test:" + test); //null 原因:开启事务后未提交,则无结果
jedis.close();
}
/**
* 测试watch
* @throws Exception
*/
@Test
public void testWatch() throws Exception{
Jedis jedis = new Jedis("192.168.150.137",6379);
jedis.set("caicongyang", "goodboy");
jedis.watch("caicongyang");
Thread.sleep(3000L);
new Thread(new Runnable() {
@Override
public void run() {
Jedis j1 = new Jedis("192.168.150.137",6379);
Transaction multi = j1.multi();
multi.set("caicongyang", "good");
multi.exec();
System.out.println(j1.get("caicongyang"));//结果是:boy
j1.close();
}
}).start();
//未执行下面的事务;原因:我们调用jedis.watch(…)方法来监控key,如果调用后key值发生变化,则整个事务不会执行。
Transaction multi = jedis.multi();
multi.set("caicongyang", "boy");
List<Object> list = multi.exec();
//事务结果:异常应该上面的提交没有执行
System.out.println(list.get(0).toString()); //NullPointerExecption
String result = jedis.get("caicongyang");
System.out.println(result); //结果是:boy
}
/**
* 持久化测试
*/
@Test
public void testPersis(){
Jedis jedis = new Jedis("192.168.150.137",6379);
jedis.set("ccy", "handsome boy");
jedis.persist("ccy");
//重新启动机器依然存在
String value = jedis.get("ccy");
System.out.println(value);
jedis.close();
}
/**
* 测试管道
*/
@Test
public void testPipelined(){
Jedis jedis = new Jedis("192.168.150.137",6379);
Pipeline pipeline = jedis.pipelined();
long start = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
pipeline.set("p" + i, "p" + i);
}
//异步返回结果
List<Object> results = pipeline.syncAndReturnAll();
long end = System.currentTimeMillis();
System.out.println("Pipelined SET: " + ((end - start)/1000.0) + " seconds"); //10000次插入仅需不到1秒
System.out.println(results.size());
jedis.disconnect();
}
}
更多多线程精彩内容请继续关注我的博客:http://blog.youkuaiyun.com/caicongyang
记录与分享,你我共成长 -from
caicongyang