首页 > 代码库 > Redis大幅性能提升之Batch批量读写
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
Redis大幅性能提升之Batch批量读写