pipeline出现的背景:
redis客户端执行一条命令分4个过程:
发送命令-〉命令排队-〉命令执行-〉返回结果
这个过程称为Round trip time(简称RTT, 往返时间),mget mset有效节约了RTT,但大部分命令(如hgetall,并没有mhgetall)不支持批量操作,需要消耗N次RTT ,这个时候需要pipeline来解决这个问题
未使用pipeline执行N条命令
使用pipeline执行N条命令
使用pipeline和未使用pipeline的性能对比
总结:使用pipeline执行速度比逐条执行要快,客户端与服务端的网络延迟越大,性能体现越明显
原生的批命令(mset, mget等)与pipeline的对比
- 原生批命令是原子性,pipeline是非原子性, (原子性概念:一个事务是一个不可分割的最小工作单位,要么都成功要么都失败。原子操作是指你的一个业务逻辑必须是不可拆分的. 处理一件事情要么都成功要么都失败,其实也引用了生物里概念,分子-〉原子,原子不可拆分)
- 原生批命令一命令多个key, 但pipeline支持多命令(存在事务),非原子性
- 原生批命令是服务端实现,而pipeline需要服务端与客户端共同完成
pipeline正确使用方式
使用pipeline组装的命令个数不能太多,不然数据量过大,增加客户端的等待时间,还可能造成网络阻塞,可以将大量命令的拆分多个小的pipeline命令完成
事务
pipeline是多条命令的组合,为了保证它的原子性,redis提供了简单的事务,什么是事务?事务是指一组动作的执行,这一组动作要么成功,要么失败。
redis的简单事务,将一组需要一起执行的命令放到multi和exec两个命令之间,其中multi代表事务开始,exec代表事务结束,
注:在multi前set user:age 4 //初始化值
停止事务discard
命令错误,语法不正确,导致事务不能正常结束
运行错误,语法正确,但类型错误,事务可以正常结束
可以看到redis不支持回滚功能
watch命令
redis提供了简单事务,之所以说简单,不支持事务回滚
代码示例:
public class SexCompareTest {
public static void main(String[] args ){
//初始化一批数—— 用来删除
RedisTools.initRedisData();
long t = System.currentTimeMillis();
delPipe(RedisTools.keys);
System.out.println(System.currentTimeMillis()-t);
}
public static void dels(String... keys){
Jedis jedis = new Jedis(RedisTools.ip, RedisTools.port);
for(String id : keys){
jedis.del(id);
}
jedis.close();
}
public static void delPipe(String... keys){
Jedis jedis = new Jedis(RedisTools.ip, RedisTools.port);
Pipeline pipe = jedis.pipelined();
for(String id : keys){
pipe.del(id); //提交一次, append
}
pipe.sync(); //真正提交
jedis.close();
}
}
public class RedisTools {
public static int arraylength = 10000;
public static String ip = "127.0.0.1";
public static int port = 6379;
public static String[] keys = new String[arraylength/2];
/**
* 初始化数据,批量设值
* redis提供的批量设值mset 批量取值 mget,但没有批量删除mdel指令
*/
//String[]{"key:0","v0","key:1","v1","key:2","v2","key:3","v3","key:4","v4"......."key:4999","v:4999"})
public static void initRedisData() {
Jedis jedis = new Jedis(ip, port);
String[] str = new String[arraylength]; //10000
int j = 0;
for(int i = 0 ; i < str.length/2; i ++ ){
str[j] = "key:"+i;
str[j+1] = "v"+i;
j = j+2;
keys[i]= "key:"+i;
}
jedis.mset(str);
jedis.close();
}
}