zoukankan      html  css  js  c++  java
  • Redis大幅性能提升之Batch批量读写

    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

  • 相关阅读:
    delphi xe10 FMX 启动参数
    delphi xe6 JSON 测试
    oracle实现http请求,oracle发送http请求。
    ORACLE存储过程调用Web Service
    新搭建的iis服务器,运行网站报 System.BadImageFormatException:未能加载文件或程序集”....“或它的某一个依赖项。
    c#的http请求工具类核心代码
    vue-cli3 取消关闭eslint 校验代码
    quartz.net数据库持久化教程
    sql备份一张表的数据
    iis 长期无访问导致定时任务不执行的解决方案
  • 原文地址:https://www.cnblogs.com/zhangtingzu/p/6939895.html
Copyright © 2011-2022 走看看