前段时间在做用户画像的时候,遇到了这样的一个问题,记录某一个商品的用户购买群,刚好这种需求就可以用到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}", ); for (int i = ; i < ; 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中去,

接下来我可以把上面的代码改成类似下面这样:

         static void Main(string[] args)
{
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("192.168.23.151:6379"); var db = redis.GetDatabase(); var productID = string.Format("productID_{0}", ); var list = new List<int>(); for (int i = ; i < ; i++)
{
list.Add(i);
} db.SetAdd(productID, list.Select(i => (RedisValue)i).ToArray());
}

从截图中传输的request,response可以看到,这次我们一次性提交过去,极大的较少了在网络传输方面带来的尴尬性。。

三:再次提出问题

  product维度的画像我们可以解决了,但是我们还有一个customerid的维度,也就是说我需要维护一个customerid为key的set集合,其中value的值为

该customerid的各种平均值,比如说“总交易次数”,“总交易金额”。。。等等这样的聚合信息,然后推送过来的是批量的customerid,也就是说你需要定时

维护一小嘬set集合,在这种情况下某一个set的批量操作就搞不定了。。。原始代码如下:

         static void Main(string[] args)
{
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("192.168.23.151:6379"); var db = redis.GetDatabase(); //批量过来的数据: customeridlist, ordertotalprice,具体业务逻辑省略
var orderTotalPrice = ; var customerIDList = new List<int>(); for (int i = ; i < ; i++)
{
customerIDList.Add(i);
} //foreach更新每个redis 的set集合
foreach (var item in customerIDList)
{
var customerID = string.Format("customerid_{0}", item); db.SetAdd(customerID, orderTotalPrice);
}
}

四:解决方案【PipeLine】

上面这种代码在生产上当然是行不通的,不过针对这种问题,redis早已经提出了相关的解决方案,那就是pipeline机制,原理还是一样,将命令集整合起来通过

一条request请求一起送过去,由redis内部fake出一个client做批量执行操作,代码如下:

         static void Main(string[] args)
{
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("192.168.23.151:6379"); var db = redis.GetDatabase(); //批量过来的数据: customeridlist, ordertotalprice,具体业务逻辑省略
var orderTotalPrice = ; var customerIDList = new List<int>(); for (int i = ; i < ; i++)
{
customerIDList.Add(i);
} var batch = db.CreateBatch(); foreach (var item in customerIDList)
{
var customerID = string.Format("customerid_{0}", item); batch.SetAddAsync(customerID, orderTotalPrice);
} batch.Execute();
}

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

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

192.168.23.151:> keys *
) "customerid_0"
) "customerid_9"
) "customerid_1"
) "customerid_3"
) "customerid_8"
) "customerid_2"
) "customerid_7"
) "customerid_5"
) "customerid_6"
) "customerid_4"

好了,先就说到这里了,希望本篇对你有帮助。

redis大幅性能提升之使用管道(PipeLine)和批量(Batch)操作的更多相关文章

  1. Redis大幅性能提升之Batch批量读写

    Redis大幅性能提升之Batch批量读写 提示:本文针对的是StackExchange.Redis 一.问题呈现 前段时间在开发的时候,遇到了redis批量读的问题,由于在StackExchange ...

  2. Spring Boot 2.2 正式发布,大幅性能提升 + Java 13 支持

    之前 Spring Boot 2.2没能按时发布,是由于 Spring Framework 5.2 的发布受阻而推迟.这次随着 Spring Framework 5.2.0 成功发布之后,Spring ...

  3. Redis 管道pipeline

    Redis是一个cs模式的tcp server,使用和http类似的请求响应协议. 一个client可以通过一个socket连接发起多个请求命令. 每个请求命令发出后client通常会阻塞并等待red ...

  4. memcache 与 redis 为web app 带来的性能提升

    memcache 与 redis 为web app 带来的性能提升 参考: 1. http://www.cnblogs.com/ToDoToTry/p/3513688.html

  5. 【Redis】1、Jedis对管道、事务以及Watch的操作来应对高并发

    对于一个互联网平台来说,高并发是经常会遇到的场景.最有代表性的比如秒杀和抢购.高并发会出现三个特点: 1.高并发读取 2.高并发写入(一致性) 3.出现超卖问题 前端如何应对? 1.缓存静态数据,例如 ...

  6. VNF网络性能提升解决方案及实践

    VNF网络性能提升解决方案及实践 2016年7月 作者:    王智民 贡献者:     创建时间:    2016-7-20 稳定程度:    初稿 修改历史 版本 日期 修订人 说明 1.0 20 ...

  7. 【转】Redis学习---阿里云Redis多线程性能增强版详解

    [原文]https://www.toutiao.com/i6594620107123589635/ 摘要 Redis做为高性能的K-V数据库,由于其高性能,丰富的数据结构支持,易用等特性,而得到广泛的 ...

  8. paip.cache 缓存架构以及性能提升总结

    paip.cache 缓存架构以及性能提升总结 1         缓存架构以及性能(贯穿读出式(LookThrough) 旁路读出式(LookAside) 写穿式(WriteThrough) 回写式 ...

  9. Web 应用性能提升 10 倍的 10 个建议

    转载自http://blog.jobbole.com/94962/ 提升 Web 应用的性能变得越来越重要.线上经济活动的份额持续增长,当前发达世界中 5 % 的经济发生在互联网上(查看下面资源的统计 ...

随机推荐

  1. JAVA语言中的修饰符

    JAVA语言中的修饰符 -----------------------------------------------01--------------------------------------- ...

  2. Canvas坐标系转换

    默认坐标系与当前坐标系 canvas中的坐标是从左上角开始的,x轴沿着水平方向(按像素)向右延伸,y轴沿垂直方向向下延伸.左上角坐标为x=0,y=0的点称作原点.在默认坐标系中,每一个点的坐标都是直接 ...

  3. Android业务组件化之现状分析与探讨

    前言: 从个人经历来说的话,从事APP开发这么多年来,所接触的APP的体积变得越来越大,业务的也变得越来越复杂,总来来说只有一句话:这是一个APP臃肿的时代!所以为了告别APP臃肿的时代,让我们进入一 ...

  4. PhotoView实现图片随手势的放大缩小的效果

    项目需求:在listView的条目中如果有图片,点击条目,实现图片的放大,并且图片可以根据手势来控制图片放大缩小的比例.类似于微信朋友圈中查看好友发布的照片所实现的效果. 思路是这样的:当点击条目的时 ...

  5. CSS 3学习——transform 2D转换

    首先声明一点,transform属性不为none的元素是它的定位子元素(绝对定位和固定定位)的包含块,而且对内创建一个新的层叠上下文. 注意:可以通过 transform-box 属性指定元素的那个盒 ...

  6. CSharpGL(33)使用uniform块来优化对uniform变量的读写

    CSharpGL(33)使用uniform块来优化对uniform变量的读写 +BIT祝威+悄悄在此留下版了个权的信息说: Uniform块 如果shader程序变得比较复杂,那么其中用到的unifo ...

  7. 关于BAPI_PATIENT_CREATE(病患主数据创建)

    第一次使用BAPI,遇到几个问题.现总结如下. CALL FUNCTION 'BAPI_PATIENT_CREATE' EXPORTING client = * INSTITUTION = '*' * ...

  8. 编译器开发系列--Ocelot语言2.变量引用的消解

    "变量引用的消解"是指确定具体指向哪个变量.例如变量"i"可能是全局变量i,也可能是静态变量i,还可能是局部变量i.通过这个过程来消除这样的不确定性,确定所引用 ...

  9. angularjs 1 开发简单案例(包含common.js,service.js,controller.js,page)

    common.js var app = angular.module('app', ['ngFileUpload']) .factory('SV_Common', function ($http) { ...

  10. sqlyog导出json数据格式支持mysql数据转存mongodb

    <!-------------知识的力量是无限的(当然肯定还有更简单的方法)-----------!> 当我考虑将省市区三级联动数据从mysql转入mongodb时遇到了网上无直接插入mo ...