使用管道(PipeLine)和批量(Batch)操作
使用管道(PipeLine)和批量(Batch)操作
前段时间在做用户画像的时候,遇到了这样的一个问题,记录某一个商品的用户购买群,刚好这种需求就可以用到Redis中的Set,key作为productID,value
就是具体的customerid集合,后续的话,我就可以通过productid来查看该customerid是否买了此商品,如果购买了,就可以有相关的关联推荐,当然这只是系统中
的一个小业务条件,这时候我就可以用到SADD操作方法,代码如下:

static void Main(string[] args)
{
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("192.168.23.151:6379"); var db = redis.GetDatabase(); var productID = string.Format("productID_{0}", 1); for (int i = 0; i < 10; i++)
{
var customerID = i; db.SetAdd(productID, customerID);
}
}

一:问题
但是上面的这段代码很明显存在一个大问题,Redis本身就是基于tcp的一个Request/Response protocol模式,不信的话,可以用wireshark监视一下:

从图中可以看到,有很多次的192.168.23.1 => 192.168.23.151 之间的数据往返,从传输内容中大概也可以看到有一个叫做productid_xxx的前缀,
那如果有百万次局域网这样的round trip,那这个延迟性可想而知,肯定达不到我们预想的高性能。
二:解决方案【Batch】
刚好基于我们现有的业务,我可以定时的将批量的productid和customerid进行分组整合,然后用batch的形式插入到某一个具体的product的set中去,
接下来我可以把上面的代码改成类似下面这样:

1 static void Main(string[] args)
2 {
3 ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("192.168.23.151:6379");
4
5 var db = redis.GetDatabase();
6
7 var productID = string.Format("productID_{0}", 1);
8
9 var list = new List<int>();
10
11
12 for (int i = 0; i < 10; i++)
13 {
14 list.Add(i);
15 }
16
17 db.SetAdd(productID, list.Select(i => (RedisValue)i).ToArray());
18 }


从截图中传输的request,response可以看到,这次我们一次性提交过去,极大的较少了在网络传输方面带来的尴尬性。。
三:再次提出问题
product维度的画像我们可以解决了,但是我们还有一个customerid的维度,也就是说我需要维护一个customerid为key的set集合,其中value的值为
该customerid的各种平均值,比如说“总交易次数”,“总交易金额”。。。等等这样的聚合信息,然后推送过来的是批量的customerid,也就是说你需要定时
维护一小嘬set集合,在这种情况下某一个set的批量操作就搞不定了。。。原始代码如下:

1 static void Main(string[] args)
2 {
3 ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("192.168.23.151:6379");
4
5 var db = redis.GetDatabase();
6
7
8 //批量过来的数据: customeridlist, ordertotalprice,具体业务逻辑省略
9 var orderTotalPrice = 100;
10
11 var customerIDList = new List<int>();
12
13 for (int i = 0; i < 10; i++)
14 {
15 customerIDList.Add(i);
16 }
17
18 //foreach更新每个redis 的set集合
19 foreach (var item in customerIDList)
20 {
21 var customerID = string.Format("customerid_{0}", item);
22
23 db.SetAdd(customerID, orderTotalPrice);
24 }
25 }

四:解决方案【PipeLine】
上面这种代码在生产上当然是行不通的,不过针对这种问题,redis早已经提出了相关的解决方案,那就是pipeline机制,原理还是一样,将命令集整合起来通过
一条request请求一起送过去,由redis内部fake出一个client做批量执行操作,代码如下:

1 static void Main(string[] args)
2 {
3 ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("192.168.23.151:6379");
4
5 var db = redis.GetDatabase();
6
7
8 //批量过来的数据: customeridlist, ordertotalprice,具体业务逻辑省略
9 var orderTotalPrice = 100;
10
11 var customerIDList = new List<int>();
12
13 for (int i = 0; i < 10; i++)
14 {
15 customerIDList.Add(i);
16 }
17
18 var batch = db.CreateBatch();
19
20 foreach (var item in customerIDList)
21 {
22 var customerID = string.Format("customerid_{0}", item);
23
24 batch.SetAddAsync(customerID, orderTotalPrice);
25 }
26
27 batch.Execute();
28 }

然后,我们再看下面的wireshark截图,可以看到有很多的SADD这样的小命令,这就说明有很多命令是一起过去的,大大的提升了性能。

最后可以再看一下redis,数据也是有的,是不是很爽~~~

192.168.23.151:6379> keys *
1) "customerid_0"
2) "customerid_9"
3) "customerid_1"
4) "customerid_3"
5) "customerid_8"
6) "customerid_2"
7) "customerid_7"
8) "customerid_5"
9) "customerid_6"
10) "customerid_4"

好了,先就说到这里了,希望本篇对你有帮助。
使用管道(PipeLine)和批量(Batch)操作的更多相关文章
- redis使用管道pipeline提升批量操作性能(php演示)
Redis是一个TCP服务器,支持请求/响应协议. 在Redis中,请求通过以下步骤完成: 客户端向服务器发送查询,并从套接字读取,通常以阻塞的方式,用于服务器响应. 服务器处理命令并将响应发送回客户 ...
- Redis 管道pipeline
Redis是一个cs模式的tcp server,使用和http类似的请求响应协议. 一个client可以通过一个socket连接发起多个请求命令. 每个请求命令发出后client通常会阻塞并等待red ...
- PreparedStatement批量(batch)插入数据
JDBC操作数据库的时候,需要一次性插入大量的数据的时候,如果每次只执行一条SQL语句,效率可能会比较低.这时可以使用batch操作,每次批量执行SQL语句,调高效率. public Boolean ...
- redis 批量删除操作
redis 批量删除操作 需要在redis里面清空一批数据,redis没有支持通配符删除, 只有del key1 key2 ... 但是可以通配符获取 KEYS PATTERN 然后利用linux管道 ...
- [并发并行]_[线程模型]_[Pthread线程使用模型之一管道Pipeline]
场景 1.经常在Windows, MacOSX 开发C多线程程序的时候, 经常需要和线程打交道, 如果开发人员的数量不多时, 同时掌握Win32和pthread线程 并不是容易的事情, 而且使用Win ...
- 【转】批量复制操作(SqlBulkCopy)的出错处理:事务提交、回滚
原文地址:http://blog.csdn.net/westsource/article/details/6658109 默认情况下,批量复制操作作为独立的操作执行. 批量复制操作以非事务性方式发生, ...
- 使用Ajax实现的批量删除操作(C#)
今天做了一个简单的批量删除操作,虽然简单,但是很多问题出现,终究还是技术不够熟练. 现在在这里跟大家分享一下.仅供学习... 1.在前台获取用户点击的信息id,把这里id封装到一个数组里面:(rows ...
- mySql事务_ _Java中怎样实现批量删除操作(Java对数据库进行事务处理)?
本文是记录Java中实现批量删除操作(Java对数据库进行事务处理),在开始之前先来看下面这样的一个页面图: 上面这张图片显示的是从数据库中查询出的出租信息,信息中进行了分页处理,然后每行的前面提 ...
- C#利用SqlDataAdapte对DataTable进行批量数据操作
C#利用SqlDataAdapte对DataTable进行批量数据操作,可以让我们大大简化操作数据的代码量,我们几乎不需要循环和不关心用户到底是新增还是修改,更不用编写新增和修改以及删除的SQL语句, ...
- MyBatis魔法堂:各数据库的批量Update操作
一.前言 MyBatis的update元素的用法与insert元素基本相同,因此本篇不打算重复了.本篇仅记录批量update操作的sql语句,懂得SQL语句,那么MyBatis部分的操作就简单了. ...
随机推荐
- FMDB的简单使用
1.什么是FMDB? FMDB是iOS平台的SQLite数据库框架 FMDB以OC的方式封装了SQLite的C语言API. 无论项目中使用 ARC 还是 MRC,对 FMDB 都没有任何影响,FMDB ...
- Zend Studio 12 安装及破解
安装: 1.下载最新版本Zend Studio:http://downloads.zend.com/studio-eclipse/12.0.0/ZendStudio-12.0.0-win32.win3 ...
- 《AngularJS高级程序设计》学习笔记
一.AngularJS应用剖析 AngularJS存在一些最主要的构件,如模型,视图和控制器.但AngularJS中也有许多其他可供灵活使用的部件,包括模块,指令,过滤器,工厂和服务. 一 . 1 ...
- Android搭建junit测环境
在AndroidManifest.xml文件中增加两个东西,分别是: 1.uses-library ,位于application里面. 2.instrumentation,与application同级 ...
- Linux[Fedora]查找文件包含的字段
find 与 grep组合查找 find . –name '文件类型' | xargs grep –n '查找内容'文件类型可正则表达式通配, [.]表示当前目录下进行查找,也可自由指定目录.比如: ...
- 烂泥:源码安装apache
本文由秀依林枫提供友情赞助,首发于烂泥行天下. 最近要开始学习nagios监控方面的知识了,但是nagios与apache结合的比较紧密,所以本篇文章就先把apache的源码安装学习下. 我们现在分以 ...
- make
make会自动搜索当前目录下的makefile或Makefile文件进行编译,也可以通过-f选项读取其他文件. make [-abvijm etc] -C dir表示到dir指定的路径去搜索文件 -f ...
- 2------------NLPIR(ICTCLAS2016)分词系统添加用户词典功能
备注:win7 64位系统,netbeans编程 基本代码框架参见我的另一篇文章:NLPIR分词功能 代码实现: package cwordseg; import java.io.Unsupporte ...
- (转)Yii的组件机制之一:组件基础类CComponent分析
Yii的组件机制 组件机制,是Yii整个体系的思想精髓,在使用Yii之前,最应该先了解其组件机制,如果不了解这个机制,那么阅读Yii源代码会非常吃力.组件机制给Yii框架赋予了无穷的灵活性和可扩展性, ...
- Android中dip、dp、sp、pt和px的区别
1.概述 过去,程序员通常以像素为单位设计计算机用户界面.例如:图片大小为80×32像素.这样处理的问题在于,如果在一个每英寸点数(dpi)更高的新显示器上运行该程序,则用户界面会显得很小.在有些情况 ...