日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2023/12/4 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 redis大幅性能提升之使用管道(PipeLine)和批量(Batch)操作 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前段時間在做用戶畫像的時候,遇到了這樣的一個問題,記錄某一個商品的用戶購買群,剛好這種需求就可以用到Redis中的Set,key作為productID,value就是具體的customerid集合,后續的話,我就可以通過productid來查看該customerid是否買了此商品,如果購買了,就可以有相關的關聯推薦,當然這只是系統中的一個小業務條件,這時候我就可以用到SADD操作方法,代碼如下:

static void Main(string[] args){ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("192.168.23.151:6379");var db = redis.GetDatabase();var productID = string.Format("productID_{0}", 1);for (int i = 0; i < 10; i++){var customerID = i;db.SetAdd(productID, customerID);}}

一:問題

但是上面的這段代碼很明顯存在一個大問題,Redis本身就是基于tcp的一個Request/Response protocol模式,不信的話,可以用wireshark監視一下:

從圖中可以看到,有很多次的192.168.23.1 => 192.168.23.151 之間的數據往返,從傳輸內容中大概也可以看到有一個叫做productid_xxx的前綴,那如果有百萬次局域網這樣的round trip,那這個延遲性可想而知,肯定達不到我們預想的高性能。

二:解決方案【Batch】

剛好基于我們現有的業務,我可以定時的將批量的productid和customerid進行分組整合,然后用batch的形式插入到某一個具體的product的set中去,接下來我可以把上面的代碼改成類似下面這樣:

static void Main(string[] args){ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("192.168.23.151:6379");var db = redis.GetDatabase();var productID = string.Format("productID_{0}", 1);var list = new List<int>();for (int i = 0; i < 10; i++){list.Add(i);}db.SetAdd(productID, list.Select(i => (RedisValue)i).ToArray());}

從截圖中傳輸的request,response可以看到,這次我們一次性提交過去,極大的較少了在網絡傳輸方面帶來的尷尬性。。

三:再次提出問題

product維度的畫像我們可以解決了,但是我們還有一個customerid的維度,也就是說我需要維護一個customerid為key的set集合,其中value的值為該customerid的各種平均值,比如說“總交易次數”,“總交易金額”。。。等等這樣的聚合信息,然后推送過來的是批量的customerid,也就是說你需要定時維護一小嘬set集合,在這種情況下某一個set的批量操作就搞不定了。。。原始代碼如下:

static void Main(string[] args){ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("192.168.23.151:6379");var db = redis.GetDatabase();//批量過來的數據:customeridlist, ordertotalprice,具體業務邏輯省略var orderTotalPrice = 100;var customerIDList = new List<int>();for (int i = 0; i < 10; i++){customerIDList.Add(i);}//foreach更新每個redis 的set集合foreach (var item in customerIDList){var customerID = string.Format("customerid_{0}", item);db.SetAdd(customerID, orderTotalPrice);}}

四:解決方案【PipeLine】

上面這種代碼在生產上當然是行不通的,不過針對這種問題,redis早已經提出了相關的解決方案,那就是pipeline機制,原理還是一樣,將命令集整合起來通過一條request請求一起送過去,由redis內部fake出一個client做批量執行操作,代碼如下:

static void Main(string[] args){ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("192.168.23.151:6379");var db = redis.GetDatabase();//批量過來的數據:customeridlist, ordertotalprice,具體業務邏輯省略var orderTotalPrice = 100;var customerIDList = new List<int>();for (int i = 0; i < 10; i++){customerIDList.Add(i);}var batch = db.CreateBatch();foreach (var item in customerIDList){var customerID = string.Format("customerid_{0}", item);batch.SetAddAsync(customerID, orderTotalPrice);}batch.Execute();}

然后,我們再看下面的wireshark截圖,可以看到有很多的SADD這樣的小命令,這就說明有很多命令是一起過去的,大大的提升了性能。

最后可以再看一下redis,數據也是有的,是不是很爽~~~

192.168.23.151:6379> keys *1) "customerid_0"2) "customerid_9"3) "customerid_1"4) "customerid_3"5) "customerid_8"6) "customerid_2"7) "customerid_7"8) "customerid_5"9) "customerid_6" 10) "customerid_4"

好了,先就說到這里了,希望本篇對你有幫助。

總結

以上是生活随笔為你收集整理的redis大幅性能提升之使用管道(PipeLine)和批量(Batch)操作的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。