使用管道(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部分的操作就简单了. ...
随机推荐
- C阶段【01】 - C基础
一.进制 进位方法:逢几进一(也就是几进制) 举例:十进制 12 : 二进制 0b(计算机前缀) 0b1011 : 八进制 0 073 :十六进制 0x 0xABCDEF 十进 ...
- asp.net mvc 应用Bundle(捆绑和微小)压缩技术 启用 BundleConfig 配置web.config
从MVC4开始,我们就发现,项目中对Global.asax进行了优化,将原来在MVC3中使用的代码移到了 [App_Start]文件夹下,而Global.asax只负责初始化.其中的BundleCon ...
- VS2013崩溃,无法打开项目的解决方案
最近遇到VS2013,在打开解决方案时,报如下错误: “未找到与约束 ContractName Microsoft.Internal.VisualStudio.PlatformUI.ISolution ...
- Ubuntu/Windows双系统修复引导
Ubuntu/Windows双系统修复引导 首先说明:在Windows存在的前提下安装Ubuntu(或者Ubuntu系列)是不需要修复引导的.因为grub会自动搜索存在硬盘中的系统. 而在Ub ...
- PS网页设计教程——30个优秀的PS网页设计教程的中文翻译教程
PS网页设计教程--30个优秀的PS网页设计教程的中文翻译教程 作为编码者,美工基础是偏弱的.我们可以参考一些成熟的网页PS教程,提高自身的设计能力.套用一句话,"熟读唐诗三百首,不会作 ...
- W3School-CSS 字体(font)实例
CSS 字体(font)实例 CSS 实例 CSS 背景实例 CSS 文本实例 CSS 字体(font)实例 CSS 边框(border)实例 CSS 外边距 (margin) 实例 CSS 内边距 ...
- mysql 动态新建以及删除分区表
因为项目需要,最近研究了一下在mysql数据库下如何动态新建以及删除分区表.如果全部借助存储过程的话,新建以及删除分区表在逻辑上比较死板.不灵活,而且还容易出错.因此,我新建了一个数据表table_f ...
- Linux IPC System V 信号量
模型 #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> ftok() //获取key ...
- Linux vim(4)
vim相对于vi做了很多的提升: -VIM支持多集撤销 -VIM可以跨平台运行 —VIM支持语法高亮 -VIM支持图形界面 vim三大模式: command mode vi进入时的默认模式 esc进入 ...
- POJ1742 Coins[多重背包可行性]
Coins Time Limit: 3000MS Memory Limit: 30000K Total Submissions: 34814 Accepted: 11828 Descripti ...