详解redis大幅性能提升之使用管道(PipeLine)和批量(Batch)操作

 更新时间:2016年12月23日 08:45:56   作者:一线码农  
这篇文章主要介绍了详解redis大幅性能提升之使用管道(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中去,接下来我可以把上面的代码改成类似下面这样:

     static void Main(string[] args)
     {
       ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("...:");
 
       var db = redis.GetDatabase();
 
       var productID = string.Format("productID_{}", );
 
       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("...:");
 
       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_{}", item);
 
         db.SetAdd(customerID, orderTotalPrice);
       }
     }

四:解决方案【PipeLine】

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

     static void Main(string[] args)
     {
       ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("...:");
 
       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_{}", item);
 
         batch.SetAddAsync(customerID, orderTotalPrice);
       }
 
       batch.Execute();
     }

然后,我们再看下面的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"

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Redis中Bitmap的使用示例

    Redis中Bitmap的使用示例

    本文主要介绍了Redis中Bitmap的使用示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-05-05
  • Redis权限和访问控制的实现示例

    Redis权限和访问控制的实现示例

    Redis提供了一些机制来保护敏感数据和限制对Redis服务器的访问,本文主要介绍了Redis权限和访问控制的实现示例,具有一定的参考价值,感兴趣的可以了解一下
    2023-12-12
  • Redis server 主从复制配置实现

    Redis server 主从复制配置实现

    从复制是指将一个Redis服务器的数据复制到其他Redis服务器的过程,本文主要介绍了Redis server 主从复制配置实现,具有一定的参考价值,感兴趣的可以了解一下
    2024-02-02
  • 浅谈redission锁的默认失效时间

    浅谈redission锁的默认失效时间

    Redisson是一个基于Redis的Java驻留库,提供了许多分布式对象和服务,包括分布式锁,本文主要介绍了浅谈redission锁的默认失效时间, 具有一定的参考价值,感兴趣的可以了解一下
    2024-02-02
  • Redis中key的操作命令

    Redis中key的操作命令

    本文主要介绍了Redis中key的操作命令,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-06-06
  • Redis请求处理的流程分析

    Redis请求处理的流程分析

    这篇文章主要介绍了Redis 是如何进行请求处理,这篇文章介绍了整个 Redis 的请求处理模型到底是怎样的。从注册监听 fd 事件到执行命令,到最后将数据回写给客户端都做了个大概的分析,需要的朋友可以参考下
    2022-07-07
  • 详解如何发现并解决Redis热点Key问题

    详解如何发现并解决Redis热点Key问题

    Redis 热点 Key 是指在某一时间段内,被大量的读写操作命中的 Key,这种情况可能会导致性能瓶颈,数据一致性问题,缓存击穿等问题,所以本文给大家介绍了如何发现并解决Redis热点Key问题,需要的朋友可以参考下
    2024-05-05
  • Redis实现分布式锁的方法示例

    Redis实现分布式锁的方法示例

    本篇文章主要介绍了Redis实现分布式锁的方法示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10
  • Redis实现分布式锁的实例讲解

    Redis实现分布式锁的实例讲解

    在本篇文章里小编给大家整理了一篇关于Redis实现分布式锁的实例讲解内容,有兴趣的朋友们可以学习参考下。
    2021-12-12
  • redis如何取hash的值

    redis如何取hash的值

    这篇文章主要介绍了redis如何取hash的值问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-01-01

最新评论