使用管道(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部分的操作就简单了. ...
随机推荐
- Android实现欢迎界面,点击进入应用
在主线程中开启一个新线程,每隔100ms检查一下时间是否到达自己预设的显示时间,到达则进入应用 实现屏幕的触摸事件,当触摸的时候,进入应用 package com.example.administra ...
- 实战Ubuntu Server上配置LXDE+VNC环境
1.安装x-window 使用apt-get 安装 xorg sudo apt-get install xorg 如果提示以下内容,就说明需要update下源列表,使用sudo apt-get upd ...
- Maven项目无法引入 Maven Dependencies Libraries 问题
昨天在check下来maven项目之后一些配置好了,就是下载不是maven 依赖库,后面再网上找到如下解决方案. 在.classpath文件中加入如下代码就好了. <classpathentry ...
- mysql源码解读之事务提交过程(一)
mysql是一种关系型数据库,关系型数据库一个重要的特性就是支持事务,这是区别于no-sql产品的一个核心特性.当然了,no-sql产品支持键值查询,不能支持sql语句,这也是一个区别.今天主要讨论下 ...
- Sql Server之旅——第三站 解惑那些背了多年聚集索引的人
说到聚集索引,我想每个码农都明白,但是也有很多像我这样的猥程序员,只能用死记硬背来解决这个问题,什么表中只能建一个聚集索引, 然后又扯到了目录查找来帮助读者记忆....问题就在这里,我们不是学文科,, ...
- 简述java序列化
1. 什么是Java对象序列化 Java平台允许我们在内存中创建可复用的Java对象,但一般情况下,只有当JVM处于运行时,这些对象才可能存在,即,这些对象的生命周期不会比JVM的生命周期 ...
- python-1 python基础知识
python第一课代码笔记 hello world [root@heartbeat-data- python]# vim hello1.py #!/usr/bin/env python print ( ...
- C# 多线程,论多核时代爱恨情仇
为什么要学习多线程? 2010年1月21日是10年某市公务员考试的报名截止日.因从下午2点开始,用于报名的北京市人事考试网瘫痪,原定于昨天下午5点截止的报名时间延迟至今天上午11点. 2011年3月1 ...
- 走进云背后:微软Azure web 项目通过web service部署web site
探索云那不为人知的故事(一):Web Services部署web site 前奏:Windows Azure是微软基于云计算的操作系统,现在更名为“Microsoft Azure”,和Azure Se ...
- 朝花夕拾之--大数据平台CDH集群离线搭建
body { border: 1px solid #ddd; outline: 1300px solid #fff; margin: 16px auto; } body .markdown-body ...