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

提示:本文针对的是StackExchange.Redis

一、问题呈现

前段时间在开发的时候,遇到了redis批量读的问题,由于在StackExchange.Redis里面我确实没有找到PipeLine命令,找到的是Batch命令,因此对其用法进行了探究一下。

下面的代码是我之前写的:

 1 public List<StudentEntity> Get(List<int> ids)
 2 {
 3       List<StudentEntity> result = new List<StudentEntity>();
 4       try
 5       {
 6           var db = RedisCluster.conn.GetDatabase();
 7           foreach (int id in ids.Keys)
 8           {
 9               string key = KeyManager.GetKey(id);
10               var dic = db.HashGetAll(key).ToDictionary(k => k.Name, v => v.Value);
11               StudentEntity se = new StudentEntity();
12               if (dic.Keys.Contains(StudentEntityRedisHashKey.id.ToString()))
13               {
14                   pe.id = FormatUtils.ConvertToInt32(dic[StudentEntityRedisHashKey.id.ToString()], -1);
15               }
16               if (dic.Keys.Contains(StudentEntityRedisHashKey.name.ToString()))
17               {
18                   pe.name= dic[StudentEntityRedisHashKey.name.ToString()];
19               }
20               result.Add(se);
21          }
22             catch (Exception ex)
23             {
24             }
25             return result;
26 }

从上面的代码中可以看出,并不是批量读,经过性能测试,性能确实是要远远低于用Batch操作,因为HashGetAll方法被执行了多次。

下面给出批量方法:

二、解决问题方法

具体的用法是:

var batch = db.CreateBatch();

...//这里写具体批量操作的方法

batch.Execute();

2.1批量写

具体代码:

 1 public bool InsertBatch(List<StudentEntity> seList)
 2 {
 3       bool result = false;
 4       try
 5       {
 6            var db = RedisCluster.conn.GetDatabase();
 7            var batch = db.CreateBatch();
 8            foreach (var se in seList)
 9            {
10                 string key = KeyManager.GetKey(se.id);
11                 batch.HashSetAsync(key, StudentEntityRedisHashKey.id.ToString(), te.id);
12                 batch.HashSetAsync(key, StudentEntityRedisHashKey.name.ToString(), te.name);
13            }
14            batch.Execute();
15            result = true;
16       }
17       catch (Exception ex)
18       {
19       }
20       return result;
21 }

这个方法里执行的是批量插入学生实体数据,这里只是针对Hash,其它的也一样操作。

2.2批量读

具体代码:

 1 public List<StudentEntity> GetBatch(List<int> ids)
 2 {
 3       List<StudentEntity> result = new List<StudentEntity>();
 4       List<Task<StackExchange.Redis.HashEntry[]>> valueList = new List<Task<StackExchange.Redis.HashEntry[]>>();
 5       try
 6       {
 7            var db = RedisCluster.conn.GetDatabase();
 8            var batch = db.CreateBatch();
 9            foreach(int id in ids)
10            {
11                 string key = KeyManager.GetKey(id);
12                 Task<StackExchange.Redis.HashEntry[]> tres = batch.HashGetAllAsync(key);
13                 valueList.Add(tres);
14            }
15            batch.Execute();
16
17            foreach(var hashEntry in valueList)
18            {
19                var dic = hashEntry.Result.ToDictionary(k => k.Name, v => v.Value);
20                StudentEntity se= new StudentEntity();
21                if (dic.Keys.Contains(StudentEntityRedisHashKey.id.ToString()))
22                {
23                     se.id= FormatUtils.ConvertToInt32(dic[StudentEntityRedisHashKey.id.ToString()], -1);
24                }
25                if (dic.Keys.Contains(StudentEntityRedisHashKey.name.ToString()))
26                {
27                     se.name= dic[StudentEntityRedisHashKey.name.ToString()];
28                }
29                result.Add(se);
30             }
31       }
32       catch (Exception ex)
33       {
34       }
35       return result;
36 }

这个方法是批量读取学生实体数据,批量拿到实体数据后,将其转化成我们需要的数据。下面给出性能对比。

2.3性能对比

10条数据,约4-5倍差距:

1000条数据,约28倍的差距:

随着数据了增多,差距将越来越大。

三、源码测试案例

上面是批量读写实体数据,下面给出StackExchange.Redis源码测试案例里的批量读写写法:

 1         public void TestBatchSent()
 2         {
 3             using (var muxer = Config.GetUnsecuredConnection())
 4             {
 5                 var conn = muxer.GetDatabase(0);
 6                 conn.KeyDeleteAsync("batch");
 7                 conn.StringSetAsync("batch", "batch-sent");
 8                 var tasks = new List<Task>();
 9                 var batch = conn.CreateBatch();
10                 tasks.Add(batch.KeyDeleteAsync("batch"));
11                 tasks.Add(batch.SetAddAsync("batch", "a"));
12                 tasks.Add(batch.SetAddAsync("batch", "b"));
13                 tasks.Add(batch.SetAddAsync("batch", "c"));
14                 batch.Execute();
15
16                 var result = conn.SetMembersAsync("batch");
17                 tasks.Add(result);
18                 Task.WhenAll(tasks.ToArray());
19
20                 var arr = result.Result;
21                 Array.Sort(arr, (x, y) => string.Compare(x, y));
22                 ...
23             }
24         }

这个方法里也给出了批量写和读的操作。

好了,先说到这里了。

查看原文:http://www.cnblogs.com/zhangtingzu/

下面给出一些相关的参考文档:

1.http://www.cnblogs.com/huangxincheng/p/6212406.html

2.http://blog.csdn.net/ma_jiang/article/details/57085586

时间: 2024-10-13 10:30:54

Redis大幅性能提升之Batch批量读写的相关文章

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

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

Java使用Pipeline对Redis批量读写(hmset&amp;hgetall)

一般情况下,Redis Client端发出一个请求后,通常会阻塞并等待Redis服务端处理,Redis服务端处理完后请求命令后会将结果通过响应报文返回给Client.这有点类似于HBase的Scan,通常是Client端获取每一条记录都是一次RPC调用服务端.在Redis中,有没有类似HBase Scanner Caching的东西呢,一次请求,返回多条记录呢?有,这就是Pipline.官方介绍 http://redis.io/topics/pipelining 通过pipeline方式当有大批

Java使用Pipeline对Redis批量读写(hmset&hgetall)

一般情况下,Redis Client端发出一个请求后,通常会阻塞并等待Redis服务端处理,Redis服务端处理完后请求命令后会将结果通过响应报文返回给Client. 这有点类似于HBase的Scan,通常是Client端获取每一条记录都是一次RPC调用服务端. 在Redis中,有没有类似HBase Scanner Caching的东西呢,一次请求,返回多条记录呢? 有,这就是Pipline.官方介绍 http://redis.io/topics/pipelining 通过pipeline方式当

spring batch批量处理框架

spring batch精选,一文吃透spring batch批量处理框架 前言碎语 批处理是企业级业务系统不可或缺的一部分,spring batch是一个轻量级的综合性批处理框架,可用于开发企业信息系统中那些至关重要的数据批量处理业务.SpringBatch基于POJO和Spring框架,相当容易上手使用,让开发者很容易地访问和利用企业级服务.spring batch具有高可扩展性的框架,简单的批处理,复杂的大数据批处理作业都可以通过SpringBatch框架来实现. spring batch

深度学习性能提升的诀窍

深度学习性能提升的诀窍[转载] 原文: How To Improve Deep Learning Performance 作者: Jason Brownlee 提升算法性能的想法 这个列表并不完整,却是很好的出发点.我的目的是给大家抛出一些想法供大家尝试,或许有那么一两个有效的方法.往往只需要尝试一个想法就能得到提升.我把这个列表划分为四块: · 从数据上提升性能 · 从算法上提升性能 · 从算法调优上提升性能 · 从模型融合上提升性能 性能提升的力度按上表的顺序从上到下依次递减.举个例子,新的

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

[原文]https://www.toutiao.com/i6594620107123589635/ 摘要 Redis做为高性能的K-V数据库,由于其高性能,丰富的数据结构支持,易用等特性,而得到广泛的应用.但是由于redis单进程单线程的模型限制,单Redis Server QPS最高只能达到10万级别.本文试图通过对Redis做多线程的优化,来达到增强性能的目的. 二.背景 众所周知redis是单进程单线程模型(不完全是单进程单线程,还有若干后端线程主要做刷脏数据,关闭文件描述符等后台清理工作

Spring Boot 2.2.0,性能提升+支持Java13

随着 Spring Framework 5.2.0 成功发布之后,Spring Boot 2.2 也紧跟其后,发布了第一个版本:2.2.0.下面就来一起来看看这个版本都更新了些什么值得我们关注的内容. 组件版本更新 这些Spring框架组件更新了依赖版本: Spring AMQP 2.2 Spring Batch 4.2 Spring Data Moore Spring Framework 5.2 Spring HATEOAS 1.0 Spring Integration 5.2 Spring

老nginx集群向tengine集群的升级改造,性能提升数倍

集群服务器使用nginx+fpm(php)的结构,这种结构的性能很大程度的瓶颈在fpm这一层,随着业务发展,访问量的增加,为了保证用户体验,我们在通过各种手段去提升集群的吞吐量和服务质量--机器扩容.业务分池.MC/REDIS的local化等等,做下来看到的效果是明显的,不过量级上的提升还是迫切需要,于是想到了在web服务器上在下下功夫,集群使用的nginx版本有点历史,版本就不说了,不过一直跑的都很健壮,所以没从想过更换,一个简单的事情促使我想测试更换为tengine,那就是worker进程数

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

转载自http://blog.jobbole.com/94962/ 提升 Web 应用的性能变得越来越重要.线上经济活动的份额持续增长,当前发达世界中 5 % 的经济发生在互联网上(查看下面资源的统计信息). 我们现在所处的时代要求一直在线和互联互通,这意味着用户对性能有更高的期望.如果网站响应不及时,或者应用有明显的延迟,用户很快就会跑到竞争者那边去. 例如,Amazon 十年前做的一项研究表明,网页加载时间减少 100 毫秒,收入就会增加  1%.最近另一项研究凸显了一个事实,就是有一半以上