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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章