首页 > 编程知识 正文

redis pipeline命令,redis管道技术pipeline

时间:2023-05-03 11:52:58 阅读:112875 作者:3634

一、pipeline出现的背景:

redis执行单个命令包括四个过程:发送命令、队列命令、执行命令和返回结果。

此过程运行运行时间(RTT,简称往返时间),mget mset有效地节约了RTT,但大多数命令(如hgetall、mhgetall )不支持批量操作,需要消耗n次RTT

二. pepeline性能

1、不使用pipeline执行n条指令

2、使用pipeline执行了n条指令

3、两者性能比较

总结:这是一组使用Pipeline执行速度比项目符号快的统计数据。 特别是客户端和服务端的网络延迟越大,性能就越好。

发布测试代码分析两者的性能差异。 @Test

公共语音管道比较

jedis redis=new jedis (' 192.168.1.111 ',6379 );

redis.auth(12345678 ); //许可证密码对应于redis.conf的requirepass密码

map数据=new hashmap (;

redis.select(8; 使用第//8个库

redis.flushDB (;//清空第8个库中的所有数据

//hm集

long start=system.current time millis (;

//直接hm集

for(intI=0; i 10000; I ) {

data.clear (;//清空映射

DATA.put('k_'I,' v_' i );

redis.hmset(key_I,data ); //循环执行10000个数据插入redis

}

longend=system.current time millis (;

System.out.println (共:(redis.dbsize ) ) ) ) ) ) );

system.out.println(1、批量设置值而不使用PIPE需要时间() (结束-开始)/1000 )秒……);

redis.select(8;

redis.flushDB (;

使用pipeline hmset

Pipeline pipe=redis.pipelined (;

start=System.currentTimeMillis (;

//

for(intI=0; i 10000; I ) {

data.clear (;

DATA.put('k_'I,' v_' i );

PIPE.hmset('key_'I,data ); 将值封装到PIPE对象中。 此时不执行,只停留在客户端

}

pipe.sync (; //将封装的PIPE一次性发送到redis

end=System.currentTimeMillis (;

system.out.println(pipe为:(redis.dbsize ) ) ) ) ) ) ) ) );

system.out.println(2,使用PIPE批量设置值需要时间((结束-开始)/1000 )秒.);

-----------------------------请参阅

//hmget

setkeys=redis.keys('key_* '; //检查设置上述值的所有结果键

直接使用Jedis hgetall

start=System.currentTimeMillis (;

Map result=new HashMap (;

for(stringkey:keys ) {

//这里,keys根据以上设定结果,一共循环10000个、10000次

result.put(key,redis.Hgetall ) ) key; 使用redis对象根据键值获取值,并将结果放入result对象中

}

end=System.currentTimeMillis (;

System.out.println (总值: ) redi

s.dbSize() + "]条 .. ");

System.out.println("3,未使用PIPE批量取值耗时 " + (end - start) / 1000 + "秒 ..");

// 使用pipeline hgetall

result.clear();

start = System.currentTimeMillis();

for (String key : keys) {

pipe.hgetAll(key); //使用PIPE封装需要取值的key,此时还停留在客户端,并未真正执行查询请求

}

pipe.sync(); //提交到redis进行查询

end = System.currentTimeMillis();

System.out.println(" PIPE共取值:[" + redis.dbSize() + "]条 .. ");

System.out.println("4,使用PIPE批量取值耗时" + (end - start) / 1000 + "秒 ..");

redis.disconnect();

}

三、原生批命令(mset, mget)与Pipeline对比

1、原生批命令是原子性,pipeline是非原子性

(原子性概念:一个事务是一个不可分割的最小工作单位,要么都成功要么都失败。原子操作是指你的一个业务逻辑必须是不可拆分的. 处理一件事情要么都成功,要么都失败,原子不可拆分)

2、原生批命令一命令多个key, 但pipeline支持多命令(存在事务),非原子性

3、原生批命令是服务端实现,而pipeline需要服务端与客户端共同完成

四、Pipeline正确使用方式

使用pipeline组装的命令个数不能太多,不然数据量过大,增加客户端的等待时间,还可能造成网络阻塞,可以将大量命令的拆分多个小的pipeline命令完成。

1、Jedis中的pipeline使用方式

大家知道redis提供了mset、mget方法,但没有提供mdel方法,如果想实现,可以借助pipeline实现。

2、Jedis中的pipeline使用步骤:获取jedis对象(一般从连接池中获取)

获取jedis对象的pipeline对象

添加指令

执行指令

测试类方法:@Test

public void testCommond() {

// 工具类初始化

JedisUtils jedis = new JedisUtils("192.168.1.111", 6379, "12345678");

for (int i = 0; i < 100; i++) {

// 设值

jedis.set("n" + i, String.valueOf(i));

}

System.out.println("keys from redis return =======" + jedis.keys("*"));

}

// 使用pipeline批量删除

@Test

public void testPipelineMdel() {

// 工具类初始化

JedisUtils jedis = new JedisUtils("192.168.1.111", 6379, "12345678");

List keys = new ArrayList();

for (int i = 0; i < 100; i++) {

keys.add("n" + i);

}

jedis.mdel(keys);

System.out.println("after mdel the redis return ---------" + jedis.keys("*"));

}

JedisUtils下的mdel方法:/**

* 删除多个字符串key 并释放连接

*

* @param keys*

* @return 成功返回value 失败返回null

*/

public boolean mdel(List keys) {

Jedis jedis = null;

boolean flag = false;

try {

jedis = pool.getResource();//从连接借用Jedis对象

Pipeline pipe = jedis.pipelined();//获取jedis对象的pipeline对象

for(String key:keys){

pipe.del(key); //将多个key放入pipe删除指令中

}

pipe.sync(); //执行命令,完全此时pipeline对象的远程调用

flag = true;

} catch (Exception e) {

pool.returnBrokenResource(jedis);

e.printStackTrace();

} finally {

returnResource(pool, jedis);

}

return flag;

}

使用pipeline提交所有操作并返回执行结果:@Test

public void testPipelineSyncAll() {

// 工具类初始化

Jedis jedis = new Jedis("192.168.1.111", 6379);

jedis.auth("12345678");

// 获取pipeline对象

Pipeline pipe = jedis.pipelined();

pipe.multi();

pipe.set("name", "james"); // 调值

pipe.incr("age");// 自增

pipe.get("name");

pipe.discard();

// 将不同类型的操作命令合并提交,并将操作操作以list返回

List list = pipe.syncAndReturnAll();

for (Object obj : list) {

// 将操作结果打印出来

System.out.println(obj);

}

// 断开连接,释放资源

jedis.disconnect();

}

五、redis事务

pipeline是多条命令的组合,为了保证它的原子性,redis提供了简单的事务。

1、redis的简单事务,

一组需要一起执行的命令放到multi和exec两个命令之间,其中multi代表事务开始,exec代表事务结束。

2、停止事务discard

3、命令错误,语法不正确,导致事务不能正常结束

4、运行错误,语法正确,但类型错误,事务可以正常结束

5、watch命令:

使用watch后, multi失效,事务失效

WATCH的机制是:在事务EXEC命令执行时,Redis会检查被WATCH的key,只有被WATCH的key从WATCH起始时至今没有发生过变更,EXEC才会被执行。如果WATCH的key在WATCH命令到EXEC命令之间发生过变化,则EXEC命令会返回失败。

更多redis知识请关注redis入门教程栏目。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。