redis中pipeline详解


redis中pipeline详解

一、pipeline出现的背景:

redis执行一条命令有四个过程:发送命令、命令排队、命令执行、返回结果;

这个过程称为Round trip time(简称RTT, 往返时间),mget mset有效节约了RTT,但大部分命令(如hgetall,并没有mhgetall)不支持批量操作,需要消耗N次RTT ,这个时候需要pipeline来解决这个问题。

二、pepeline的性能

1、未使用pipeline执行N条命令

1.jpg

2、使用了pipeline执行N条命令

2.jpg

3、两者性能对比

3.jpg

小结:这是一组统计数据出来的数据,使用Pipeline执行速度比逐条执行要快,特别是客户端与服务端的网络延迟越大,性能体能越明显。

下面贴出测试代码分析两者的性能差异:

	@Test
	public void pipeCompare() {
		Jedis redis = new Jedis("192.168.1.111", 6379);
		redis.auth("12345678");//授权密码 对应redis.conf的requirepass密码
		Map<String, String> data = new HashMap<String, String>();
		redis.select(8);//使用第8个库
		redis.flushDB();//清空第8个库所有数据
		// hmset
		long start = System.currentTimeMillis();
		// 直接hmset
		for (int i = 0; i < 10000; i++) {
			data.clear();  //清空map
			data.put("k_" + i, "v_" + i);
			redis.hmset("key_" + i, data); //循环执行10000条数据插入redis
		}
		long end = System.currentTimeMillis();
		System.out.println("    共插入:[" + redis.dbSize() + "]条 .. ");
		System.out.println("1,未使用PIPE批量设值耗时" + (end - start) / 1000 + "秒..");
		redis.select(8);
		redis.flushDB();
		// 使用pipeline hmset
		Pipeline pipe = redis.pipelined();
		start = System.currentTimeMillis();
		//
		for (int i = 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批量设值耗时" + (end - start) / 1000 + "秒 ..");
//--------------------------------------------------------------------------------------------------
		// hmget
		Set<String> keys = redis.keys("key_*"); //将上面设值所有结果键查询出来
		// 直接使用Jedis hgetall
		start = System.currentTimeMillis();
		Map<String, Map<String, String>> result = new HashMap<String, Map<String, String>>();
		for (String key : keys) {
			//此处keys根据以上的设值结果,共有10000个,循环10000次
			result.put(key, redis.hgetAll(key)); //使用redis对象根据键值去取值,将结果放入result对象
		}
		end = System.currentTimeMillis();
		System.out.println("    共取值:[" + redis.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();
	}

4.jpg

三、原生批命令(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对象(一般从连接池中获取)

    aspx1财付通支付接口源码 aspx1财付通支付接口源码

    本支付接口的特点,主要是用xml文件来记录订单详情和支付详情。代码比较简单,只要将里面的商户号、商户key换成你自己的,将回调url换成你的网站,就可以使用了。通过这个实例也可以很好的了解一般在线支付接口的基本工作原理。其中的pay.config文件记录的是支付详情,order.config是订单详情

    aspx1财付通支付接口源码 0 查看详情 aspx1财付通支付接口源码
  • 获取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<String> keys = new ArrayList<String>();
		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<String> 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<Object> list = pipe.syncAndReturnAll();

		for (Object obj : list) {
			// 将操作结果打印出来
			System.out.println(obj);
		}
		// 断开连接,释放资源
		jedis.disconnect();
	}

五、redis事务

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

1、redis的简单事务,

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

5.jpg

2、停止事务discard

6.JPG

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

7.jpg

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

8.jpg

5、watch命令:

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

9.jpg

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

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

以上就是redis中pipeline详解的详细内容,更多请关注其它相关文章!


# 自己的  # 南通网站优化经验  # 衡阳网站页面优化  # 宜兴百度营销推广  # seo综合网站  # 许昌网站优化汉狮效果  # 营销推广后台托管  # 贴吧关键词综合排名  # 芜湖seo费用  # seo转sem容易吗  # h5网站不利于优化吗  # redis  # 如何实现  # 清空  # 网络带宽  # 商户  # 发生过  # 停留在  # 服务端  # 客户端  # 多个 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 优化推广96088 】 【 技术知识133117 】 【 IDC资讯59369 】 【 网络运营7196 】 【 IT资讯61894


相关推荐: 《飞猪旅行》购买汽车票方法  mysql中如何配置字符集和排序规则_mysql字符集排序配置  mysql镜像配置如何设置用户权限组_mysql镜像配置用户组与权限分级管理方法  sublime text 4如何安装_最新版sublime下载与汉化教程  如何在CSS中使用absolute实现登录弹窗居中_transform translate结合  Win10锁屏时间怎么设置 Win10调整自动锁屏时间方法  search中maxlength属性用法解析  PHP odbc_fetch_array 返回值处理:如何正确访问嵌套数组元素  yy漫画登录页面官方入口_yy漫画在线阅读网址入口  修复UI元素交互障碍:从“开始”按钮到信息框的平滑过渡实现  TikTok收藏夹无法删除视频如何解决 TikTok收藏管理优化方法  《随手记》启用语音备注方法  铁路12306座位怎么选_12306官方选座操作方法  FullCalendar自定义按钮样式定制指南  TikTok私信无法发送表情怎么办 TikTok消息表情发送修复方法  mysql数据库索引类型有哪些_mysql索引类型解析  Lar*el Eloquent:高效删除多对多关系中无关联子记录的父模型  PHP 4 函数中引用参数的默认值限制与解决方案  《星露谷物语》克林特好感度事件介绍  在Spring Boot Thymeleaf中利用布尔属性实现容器的条件显示  iPhone 13 Pro Max如何设置桌面小组件_iPhone 13 Pro Max小组件添加指南  招商淘客入门指南  谷歌浏览器怎么把网页翻译成中文_Chrome网页翻译功能使用方法  b站怎么查看视频的码率_b站视频码率查看方法  红手指专业版app注册教程  告别繁琐SEO!如何使用SyliusSitemap插件自动化生成网站地图,提升搜索引擎排名  在J*a中如何实现在线问答与评分系统_问答评分项目开发方法说明  windows10怎么设置电源按钮_windows10按下电源键功能修改  如何取消数字签名  《书耽》更换手机号方法  PHP页面重载后变量状态保持:实现用户档案连续浏览的教程  cad视图选项卡不见了怎么办_cad视图标签恢复显示方法  使用Python和GBGB API高效抓取指定日期范围和赛道比赛结果教程  Word 2003字体大小设置方法  顺丰快递在线查询系统 顺丰快递官方查单入口  极兔快递官网查询入口手机版 手机极兔快递登录查询入口官方  Win10如何彻底关闭OneDrive Win10禁用云同步功能【纯净】  如何解决Casbin日志与应用日志不统一的问题,使用casbin/psr3-bridge实现无缝集成  iSpring三分屏制作教程  视频号视频怎么免费保存到相册?保存到相册需要注意什么?  《绿竹漫游》关闭消息通知方法  背部总是隐隐作痛怎么回事 背痛如何改善  如何在解析前预检查XML文件的完整性? 比如检查文件大小或特定结束标签  《美篇》取消会员自动续费方法  如何测试您的网站全球打开速度-网站海外测速工  Go语言反射机制下访问嵌入结构体中的被遮蔽方法  金牛福袋获取攻略  《火花chat》搜索好友方法  PySimpleGUI中实现键盘按键与按钮事件绑定教程  51漫画网实时入口 51漫画网页版官方免费漫画入口 

 2020-05-27

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

运城市盐湖区信雨科技有限公司


运城市盐湖区信雨科技有限公司

运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。

 8156699

 13765294890

 8156699@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.