redis的hGetAll函式的效能問題

2021-07-16 01:51:56 字數 1119 閱讀 8240

在沒關注這個函式之前,一直用的memcache的資料儲存方式,但是自從更換了redis之後,對於乙個hash的資料存與取 對於memcache方便甚多,但是問題來了,乙個hash的列表如果量不大的情況,用hgetall函式幾乎看不出問題,一旦這個列表超過50或者更多時,此時用hgetall函式便能很直觀的看到效能問題,這裡就不作資料分析了。

redis是單執行緒的!當它處理乙個請求時其他的請求只能等著。通常請求都會很快處理完,但是當我們使用hgetall的時候,必須遍歷每個欄位來獲取資料,這期間消耗的cpu資源和字段數成正比,如果還用了pipelining,無疑更是雪上加霜。

performance = cpus / operations

也就是說,此場景下為了提公升效能,要麼增加運算過程中的cpu數量;要麼降低運算過程中的運算元量。在為了繼續使用hash結構的資料,又要解決此問題,比較方便的方法就是將hash以序列化字串儲存,取的時候先取出反序列化的資料,再用hget(key,array(hash..))。

例如:

....

$arrkey = array('dbfba184bef630526a75f2cd073a6098','dbfba184bef630526a75f2cd0dswet98')

$strkey = 'test';

$obj->hget($strkey,$arrkey);

把原本的hgetall操作簡化為hget,也就是說,不再需要遍歷hash中的每乙個字段,因此即便不能讓多個cpu參與運算,但是卻大幅降低了運算元量,所以效能的提公升仍然是顯著的;當然劣勢也很明顯,和所有的冗餘方式一樣,此方案浪費了大量的記憶體。

有人會問,這樣雖然沒有了遍歷欄位的過程,但是卻增加了反序列化的過程,而反序列化的成本往往也是很高的,難道這樣也能提公升效能?問題的關鍵在於開始我們遍歷欄位的操作是在乙個cpu上完成的,後來反序列化的操作,不管是什麼語言,都可以通過多程序或多執行緒來保證是在多個cpu上完成的,所以效能總體上是提公升的。

另外,很多人直覺是通過執行redis多例項來解決問題。確實,這樣可以增加運算過程中的cpu數量,有助於提公升效能,但是需要注意的是,hgetall和pipelining往往會讓運算過程中的運算元量呈幾何級**式增長,相比之下,我們能增加的redis多例項數量簡直就是杯水車薪,所以本例中這種方法不能徹底解決問題。

記Redis那坑人的HGETALL

世上本沒有坑,摔的人多了,也便成了坑。早就聽人說過redis的hgetall是個坑,可我偏偏不信邪 不管什麼坑,一定要自己踩上去跺兩腳才肯罷休。說好聽點這是不到黃河心不死,說難聽點就是不見棺材不落淚。開始程式執行的非常穩定,穩定到我想送所有說hgetall是個坑的人乙個字 呸!此時的我就像溫水裡的青...

記Redis那坑人的HGETALL

世上本沒有坑,摔的人多了,也便成了坑。早就聽人說過redis的hgetall是個坑,可我偏偏不信邪 不管什麼坑,一定要自己踩上去跺兩腳才肯罷休。說好聽點這是不到黃河心不死,說難聽點就是不見棺材不落淚。開始程式執行的非常穩定,穩定到我想送所有說hgetall是個坑的人乙個字 呸!此時的我就像溫水裡的青...

記Redis那坑人的HGETALL

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!世上本沒有坑,摔的人多了,也便成了坑。早就聽人說過redis的hgetall是個坑,可我偏偏不信邪 不管什麼坑,一定要自己踩上去跺兩腳才肯罷休。說好聽點這是不到黃河心不死,說難聽點就是不見棺材不落淚。開始程式執行的非常穩定,穩定到我想送所有說hge...