redisのhGetAll関数の性能の問題(Redisのあの人のHGETALLを覚えます)

3739 ワード

この関数に注目しないまではMemcacheのデータ格納方式を用いていたが、redisを交換してからは1つのhashに対するデータ格納と取得がMemcacheにとって非常に便利であったが、問題となったのは、1つのhashのリストが量が少ない場合、hGetAll関数で数えると問題が見えず、このリストが50以上になると、このときhGetAll関数で性能の問題が直感的に見られることであり、ここではデータ分析はしません.
Redisはシングルスレッドです!1つのリクエストを処理すると、他のリクエストは待つしかありません.通常、要求はすぐに処理されますが、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を演算に参加させることができなくても操作数を大幅に削減するため、性能の向上は依然として顕著である.もちろん、すべての冗長方式と同様に、このスキームは大量のメモリを浪費していることは明らかです.
フィールドを巡るプロセスはありませんが、逆シーケンス化のプロセスが増加し、逆シーケンス化のコストも高いことが多いので、パフォーマンスを向上させることができますか?問題の鍵は、フィールドを巡る操作が1つのcpuで完了したことであり、その後、逆シーケンス化された操作は、どの言語でも、マルチプロセスまたはマルチスレッドによって複数のcpuで完了することを保証することができるため、パフォーマンスが全体的に向上することです.
また,redisマルチインスタンスを実行することによって問題を解決すると直感する人が多い.確かに、このようにして演算中のCPU数を増やすことができ、性能の向上に役立つが、hGetAllとPIPELININGは演算中の操作数を幾何学的に爆発的に増加させることが多いことに注意しなければならない.それに比べて、我々が増加できるredisマルチインスタンス数はまるで焼け石に水であるため、本例ではこの方法では問題を徹底的に解決することはできない.
Redisあの坑人のHGETALLを覚えています
世の中にはもともと穴がなくて、転んだ人が多くなって、穴になりました.
RedisのHGETALLは穴だととっくに聞いていたが、私はどうしても邪を信じなかった.どんな穴でも、自分で足を踏み鳴らしてやめなければならない.よく言えば、これは黄河に行かないと心が死なないので、難しいと言えば棺が見えないと涙を流さない.
スタートプログラムは非常に安定していて、私がすべてのHGETALLが穴だと言った人に1つの字を送りたいほど安定しています:ふっ!この时の私はぬるま湯の中のカエルのように危険な存在を忘れて、时间はこのように一日一日の过去で、突然ある日需要が変わって、私はHASHデータの内容を十数フィールドから百以上のフィールドに広げなければならなくて、同时にPipeliningを使って一度に百以上のHGETALLの结果を取得しました.そこで私は穴に落ちました:サーバーがダウンタイムしました.
どうしてこんなことになったの?Redisはシングルスレッドです!1つのリクエストを処理すると、他のリクエストは待つしかありません.通常、要求はすぐに処理されますが、HGETALLを使用する場合は、各フィールドを巡回してデータを取得する必要があります.この間に消費されるCPUリソースはフィールド数に比例しています.PIPELININGを使用すると、さらに深刻になります.
どうやってこの問題を解決しますか?私がまじめに公式を与えることを許してください.
 
  
PERFORMANCE = CPUs / OPERATIONs

つまり、このシーンでは、パフォーマンスを向上させるために、演算中のCPUの数を増やすか、演算中の操作数を減らすか.具体的には、以下の方法を大まかに考えました.
Memcachedを借りる
Redisの保存方式は何も変更しないで、余分に、私达はMemcachedを借りて1セットのキャッシュを実现して、中はもともとRedisの中でHGETALLのHASHを保存する必要があって、もちろん、Memcachedの中で保存するのはすべて文字列なので、私达がHASHを保存する时、実际に保存するのはHASHのシーケンス化した文字列で、検索する时更に逆シーケンス化すればいいです通常、Memcachedクライアントドライバは、シーケンス化および逆シーケンス化のプロセスを透過的に実現することができる.このスキームの利点は、Memcachedがマルチスレッドをサポートするため、より多くのCPUを演算に参加させることができるとともに、各フィールドを巡回する必要がないため、対応する操作が減少することである.もちろん、新しいキャッシュレイヤが導入されたため、メモリが浪費され、複雑さが増すことも少なくありません.また、少数のフィールドのデータを取得するだけで、完全なデータをクエリーしてからフィルタリングしなければならない場合もあります.これは帯域幅を浪費するに違いありません.もちろんこの場合、Redisを直接問い合わせることができますが、複雑さが向上したに違いありません.
ちなみに、MemcachedはMultigetをサポートしており、Pipeliningのような効果を実現することができますが、Memcachedに関する穴、つまりMulitigtの底なしの穴の問題には特に注意してください.
シーケンス化フィールド冗長性
Redisは、HASHを格納する際に「all」というフィールドを1つ多く保存し、その内容は元のHASHデータのシーケンス化であり、実際に照会する場合は、HGETという冗長フィールドの後に逆シーケンス化すればよい.このスキームの利点は、フィールド冗長性をシーケンス化することによって、従来のHGETALL操作をHGETに簡略化することである.すなわち、HASHの各フィールドを巡回する必要がなくなり、複数のCPUを演算に参加させることができなくても、操作数を大幅に低減するため、性能の向上は依然として顕著である.もちろん、すべての冗長方式と同様に、このスキームは大量のメモリを浪費していることは明らかです.
フィールドを巡るプロセスはありませんが、逆シーケンス化のプロセスが増加し、逆シーケンス化のコストも高いことが多いので、パフォーマンスを向上させることができますか?問題の鍵は、フィールドを巡回する操作が1つのCPUで完了したことであり、その後、逆シーケンス化された操作は、どの言語でもマルチプロセスまたはマルチスレッドによって複数のCPUで完了することを保証することができるので、性能は全体的に向上します.

また,Redisマルチインスタンスを実行することで問題を解決すると直感する人が多い.確かに、このように演算中のCPU数を増やすことができ、性能の向上に役立つが、HGETALLやPIPELININGは演算中の操作数を幾何学的に爆発的に増加させることが多いことに注意しなければならない.

穴は、踏むためのものです.落ちるのを恐れないで、もちろん前提はあなたが自分で這い出すことができることです!