redis的hGetAll函数的性能问题
在沒(méi)關(guān)注這個(gè)函數(shù)之前,一直用的Memcache的數(shù)據(jù)存儲(chǔ)方式,但是自從更換了redis之后,對(duì)于一個(gè)hash的數(shù)據(jù)存與取 對(duì)于Memcache方便甚多,但是問(wèn)題來(lái)了,一個(gè)hash的列表如果量不大的情況,用hGetAll函數(shù)幾乎看不出問(wèn)題,一旦這個(gè)列表超過(guò)50或者更多時(shí),此時(shí)用hGetAll函數(shù)便能很直觀的看到性能問(wèn)題,這里就不作數(shù)據(jù)分析了。
Redis是單線(xiàn)程的!當(dāng)它處理一個(gè)請(qǐng)求時(shí)其他的請(qǐng)求只能等著。通常請(qǐng)求都會(huì)很快處理完,但是當(dāng)我們使用HGETALL的時(shí)候,必須遍歷每個(gè)字段來(lái)獲取數(shù)據(jù),這期間消耗的CPU資源和字段數(shù)成正比,如果還用了PIPELINING,無(wú)疑更是雪上加霜。
PERFORMANCE = CPUs / OPERATIONs也就是說(shuō),此場(chǎng)景下為了提升性能,要么增加運(yùn)算過(guò)程中的CPU數(shù)量;要么降低運(yùn)算過(guò)程中的操作數(shù)量。在為了繼續(xù)使用hash結(jié)構(gòu)的數(shù)據(jù),又要解決此問(wèn)題,比較方便的方法就是將hash以序列化字符串存儲(chǔ),取的時(shí)候先取出反序列化的數(shù)據(jù),再用hGet(key,array(hash..))。
例如:
.... $arrKey = array('dbfba184bef630526a75f2cd073a6098','dbfba184bef630526a75f2cd0dswet98') $strKey = 'test'; $obj->hGet($strKey,$arrKey);把原本的hGetAll操作簡(jiǎn)化為hGet,也就是說(shuō),不再需要遍歷hash中的每一個(gè)字段,因此即便不能讓多個(gè)CPU參與運(yùn)算,但是卻大幅降低了操作數(shù)量,所以性能的提升仍然是顯著的;當(dāng)然劣勢(shì)也很明顯,和所有的冗余方式一樣,此方案浪費(fèi)了大量的內(nèi)存。
有人會(huì)問(wèn),這樣雖然沒(méi)有了遍歷字段的過(guò)程,但是卻增加了反序列化的過(guò)程,而反序列化的成本往往也是很高的,難道這樣也能提升性能?問(wèn)題的關(guān)鍵在于開(kāi)始我們遍歷字段的操作是在一個(gè)cpu上完成的,后來(lái)反序列化的操作,不管是什么語(yǔ)言,都可以通過(guò)多進(jìn)程或多線(xiàn)程來(lái)保證是在多個(gè)cpu上完成的,所以性能總體上是提升的。
另外,很多人直覺(jué)是通過(guò)運(yùn)行redis多實(shí)例來(lái)解決問(wèn)題。確實(shí),這樣可以增加運(yùn)算過(guò)程中的CPU數(shù)量,有助于提升性能,但是需要注意的是,hGetAll和PIPELINING往往會(huì)讓運(yùn)算過(guò)程中的操作數(shù)量呈幾何級(jí)爆炸式增長(zhǎng),相比之下,我們能增加的redis多實(shí)例數(shù)量簡(jiǎn)直就是杯水車(chē)薪,所以本例中這種方法不能徹底解決問(wèn)題。
總結(jié)
以上是生活随笔為你收集整理的redis的hGetAll函数的性能问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Jedis干什么用的
- 下一篇: 记Redis那坑人的HGETALL