前言
本文主要介紹的是關于Redis性能提升之Batch批量讀寫的相關內容,分享出來供大家參考學習,下面來看看詳細的介紹:
提示:本文針對的是StackExchange.Redis
一、問題呈現
前段時間在開發的時候,遇到了redis批量讀的問題,由于在StackExchange.Redis里面我確實沒有找到PipeLine命令,找到的是Batch命令,因此對其用法進行了探究一下。
下面的代碼是我之前寫的:
public List<StudentEntity> Get(List<int> ids){ List<StudentEntity> result = new List<StudentEntity>(); try { var db = RedisCluster.conn.GetDatabase(); foreach (int id in ids.Keys) { string key = KeyManager.GetKey(id); var dic = db.HashGetAll(key).ToDictionary(k => k.Name, v => v.Value); StudentEntity se = new StudentEntity(); if (dic.Keys.Contains(StudentEntityRedisHashKey.id.ToString())) { pe.id = FormatUtils.ConvertToInt32(dic[StudentEntityRedisHashKey.id.ToString()], -1); } if (dic.Keys.Contains(StudentEntityRedisHashKey.name.ToString())) { pe.name= dic[StudentEntityRedisHashKey.name.ToString()]; } result.Add(se); } catch (Exception ex) { } return result;}
從上面的代碼中可以看出,并不是批量讀,經過性能測試,性能確實是要遠遠低于用Batch操作,因為HashGetAll方法被執行了多次。
下面給出批量方法:
二、解決問題方法
具體的用法是:
var batch = db.CreateBatch();...//這里寫具體批量操作的方法batch.Execute();
2.1批量寫:
具體代碼:
public bool InsertBatch(List<StudentEntity> seList){ bool result = false; try { var db = RedisCluster.conn.GetDatabase(); var batch = db.CreateBatch(); foreach (var se in seList) { string key = KeyManager.GetKey(se.id); batch.HashSetAsync(key, StudentEntityRedisHashKey.id.ToString(), te.id); batch.HashSetAsync(key, StudentEntityRedisHashKey.name.ToString(), te.name); } batch.Execute(); result = true; } catch (Exception ex) { } return result;}
這個方法里執行的是批量插入學生實體數據,這里只是針對Hash,其它的也一樣操作。
2.2批量讀:
具體代碼:
public List<StudentEntity> GetBatch(List<int> ids){ List<StudentEntity> result = new List<StudentEntity>(); List<Task<StackExchange.Redis.HashEntry[]>> valueList = new List<Task<StackExchange.Redis.HashEntry[]>>(); try { var db = RedisCluster.conn.GetDatabase(); var batch = db.CreateBatch(); foreach(int id in ids) { string key = KeyManager.GetKey(id); Task<StackExchange.Redis.HashEntry[]> tres = batch.HashGetAllAsync(key); valueList.Add(tres); } batch.Execute(); foreach(var hashEntry in valueList) { var dic = hashEntry.Result.ToDictionary(k => k.Name, v => v.Value); StudentEntity se= new StudentEntity(); if (dic.Keys.Contains(StudentEntityRedisHashKey.id.ToString())) { se.id= FormatUtils.ConvertToInt32(dic[StudentEntityRedisHashKey.id.ToString()], -1); } if (dic.Keys.Contains(StudentEntityRedisHashKey.name.ToString())) { se.name= dic[StudentEntityRedisHashKey.name.ToString()]; } result.Add(se); } } catch (Exception ex) { } return result;}
這個方法是批量讀取學生實體數據,批量拿到實體數據后,將其轉化成我們需要的數據。下面給出性能對比。
2.3性能對比:
10條數據,約4-5倍差距:
1000條數據,約28倍的差距:
隨著數據了增多,差距將越來越大。
三、源碼測試案例
上面是批量讀寫實體數據,下面給出StackExchange.Redis源碼測試案例里的批量讀寫寫法:
public void TestBatchSent() { using (var muxer = Config.GetUnsecuredConnection()) { var conn = muxer.GetDatabase(0); conn.KeyDeleteAsync("batch"); conn.StringSetAsync("batch", "batch-sent"); var tasks = new List<Task>(); var batch = conn.CreateBatch(); tasks.Add(batch.KeyDeleteAsync("batch")); tasks.Add(batch.SetAddAsync("batch", "a")); tasks.Add(batch.SetAddAsync("batch", "b")); tasks.Add(batch.SetAddAsync("batch", "c")); batch.Execute(); var result = conn.SetMembersAsync("batch"); tasks.Add(result); Task.WhenAll(tasks.ToArray()); var arr = result.Result; Array.Sort(arr, (x, y) => string.Compare(x, y)); ... } }
這個方法里也給出了批量寫和讀的操作。
總結
好了,先說到這里了。以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對武林網的支持。
新聞熱點
疑難解答