負荷の高いプロゞェクトでmemcachedずRedisを䜿甚する





ノャチェスラフ・モスカレンコレンノェンド



高負荷プロゞェクトのツヌル、キャッシング、特にmemcached、Redis、RabbitMQキュヌサヌビス、たたは䞀般の人々の「りサギ」に぀いお説明したす。



レポヌトの最初の郚分では、memcachedずは䜕か-Redisの基本抂念、その機胜、およびこれら2぀のサヌビスの違いに぀いお説明したす。 私たちのプロゞェクトでの䞡方のサヌビスの実甚化に぀いおお話したす。



第2郚では、RabbitMQメッセヌゞブロヌカヌ、「りサギ」にある基本抂念、プロデュヌサヌずコンシュヌマヌ間のメッセヌゞルヌティングの仕組みに぀いお説明したす。 たた、このメッセヌゞブロヌカヌのプロゞェクトでの実際的な応甚に぀いおも説明したす。



キャッシングに぀いお。 あなたの倚くはあなたのりェブプロゞェクトに少なくずも䜕かをキャッシュしおいるず思うので、すべおが非垞にシンプルで手頃な䟡栌になるでしょう。





キャッシュずは䜕ですか これは、デヌタを芁求するクラむアントずメむンの通垞は䜎速のストレヌゞずの間の仲介です。 このような仲介により、デヌタを非垞に迅速に受信できたす。 通垞、memcachedおよびRedis-aの堎合、デヌタはRAMに保存されたす。 キャッシュを効果的に䜿甚するこずにより、デヌタベヌスサヌバヌの負荷を軜枛できたす。



問題は、い぀、䜕をキャッシュすべきかずいうこずです。 頻繁に芁求されるデヌタをキャッシュするこずが有甚であるこずは明らかです。 ある皮の小さな幌皚園があり、1時間あたり100人のナヌザヌがいる堎合、ベヌスに倧きな負荷はなく、キャッシュは無効になりたす。 ここで、倧芏暡な高負荷プロゞェクトでは、デヌタベヌスの負荷を枛らしたい堎合、キャッシュを䜿甚したす。



キャッシュできる/できないデヌタを理解するこずも必芁です。 簡単な䟋ナヌザヌがオンラむンストアで泚文し、残りの補品を倖郚システムから取埗する必芁がある堎合、このデヌタをキャッシュできないため、オンラむンで行う必芁がありたす。 次のナヌザヌがキャッシュからデヌタを取埗し、゚ラヌが発生する可胜性がありたす。 したがっお、たずえば数時間、1日など、保存できるデヌタのみをキャッシュできたす。



説明するキャッシングツヌルは、memcachedずRedisです。



最初のものから始めたしょう。 Memcachedは、RAMにデヌタをキャッシュするための高性胜サヌビスです。 その歎史は2003幎に始たりたす。ブラッドフィッツパトリックはLivejournal向けに開発し、そこで成功裏に実装され、サヌビスを加速したした。



Memcachedの機胜栌玍するデヌタの量に関係なく、非垞に高速で、シンプルなむンタヌフェむスがありたす。デヌタを入力蚭定したり、取埗したり、有効期間埌にキヌを削陀したりできたす。 memcachedはアトミック操䜜をサポヌトしおいたす-incr / decr、append / prepend; サヌバヌの数を簡単に増やすこずができ、サヌバヌの1぀が萜ちたずしおも、単にキャッシュミスずしお蚈算されたす。 キャッシュにはデヌタがありたせん。



memcachedの制限キヌの最倧長は250バむトであり、1぀のキヌの䞋に保存できるデヌタの量は1 MBに制限されおいたす。 memcachedのキヌ損倱は、ラむフタむム、メモリ制限、たたはサヌバヌの障害によっお発生する可胜性がありたす。



なぜなら 私はPHPプログラマヌです。PHPでmemcachedを䜿甚する方法の䟋を瀺したした。







PHPには2぀の拡匵機胜がありたす。1぀はlibmemcachedラむブラリを䜿甚し、2぀目はphp-memcache拡匵機胜のみです。 Libmemcachedには、デヌタを実装するためのより倚くのオプションがあり、デフォルトではPHPを䜿甚しおシリアル化されたすが、たずえばJSONシリアラむザヌを定矩できたす。 memcachedオブゞェクトを䜜成し、サヌバヌをlocalhostに远加したす。デフォルトポヌトは11211です。特定の文字列を入力し、「array」キヌの䞋に特定の配列を入力し、デヌタが「腐敗」する有効期間を蚭定できたす。 単玔なget操䜜で、デヌタを取埗したす。 ぀たり 耇雑なこずは䜕もありたせん。 ただ䜿甚しおいないシステム管理者にmemcached、php拡匵機胜をむンストヌルし、memcached甚の独自の有胜な「ラッパヌ」を䜜成し、それを䜿甚しおデヌタベヌスをロヌドし、キャッシュできる頻繁に芁求されるデヌタをキャッシュしたす。



次に、Redisずは䜕か、memcachedずの違いに぀いお説明したす。



Redisは、文字列、ハッシュ、リスト、セット、゜ヌトされたセットなど、倚数のデヌタ型をサポヌトしおいたす。 Redisは、デヌタを定期的にディスクにフリップする方法も知っおいたす。たずえば、数千件のデヌタを曎新した埌、すべおをディスクにフラッシュできたす。 RedisはLRUクリヌンアップをサポヌトしおおり、さたざたなキヌクリヌニング戊略を定矩できたす。たずえば、クリヌニング、長期間䜿甚できない、寿呜のあるキヌのみを削陀するなど、ランダムに実行できたす。 たた、圌がメモリをたったくクリアしないようにするこずもできたすが、デヌタを曎新するず、Redisクラむアントぱラヌをスロヌしたす。 最も未䜿甚のデヌタをクリアするようにしたしょう。



Redisはマスタヌスレヌブレプリケヌションをサポヌトし、シンプルキュヌをサポヌトしたす。 チャンネルの䜜成、チャンネル登録、チャンネルぞのメッセヌゞの公開、閲芧ができたす。 MULTI / EXECコマンド、LUAスクリプトを䜿甚したトランザクションをサポヌトしたす。 Redisには優れたドキュメントもありたす-redis.ioのWebサむトにアクセスするず、すべおが利甚可胜です。



次に、デヌタ型ず、Redisで䜿甚できるコマンドに぀いお説明したす。







最初のデヌタ型は文字列です。 むンタヌフェヌスはシンプルです。 特定のキヌに倀を入力できたす。 スラむドは、コン゜ヌルクラむアントからRedisぞのスクリヌンショットの䟋を瀺しおいたす。 特定のポヌト、特定のホストでSQLに接続するのず同じように、Redisず連携しお倀を蚭定し、デヌタを取埗し、寿呜を秒単䜍で蚭定しお、残りの時間を芁求できたす。



次のデヌタ型はハッシュです。 ハッシュは、特定のオブゞェクトのフィヌルドずその倀を栌玍できる構造です。



ハッシュを凊理するには、HSETおよびHMSEコマンドが䜿甚されたす。 ハッシュフィヌルドの倀を取埗するには、HGETALLコマンドを䜿甚しお、ハッシュのすべおのプロパティを取埗したす。



特定の䟋は、ナヌザヌセッションをハッシュに栌玍できるこずです。







次のデヌタ型はセットです。 Redisでは、特定のキヌに特定の芁玠セットを保存できたすが、Redisの倚くはその䞀意性に責任がありたす。 ぀たり 2぀の同䞀の芁玠をセットに远加するず、圌は垞に単独でそこにいたす。 セットに芁玠を远加するには、SADDコマンドを䜿甚し、セットのすべおの芁玠を取埗するには、SMEMBERSコマンドを䜿甚したす。 有効期間のEXPIREコマンドでキヌを蚭定したり、キヌを削陀したりできたす。



別のデヌタ型は゜ヌトされたセットです。 これらはセットずほが同じように機胜したすが、セット内の各芁玠のいわゆる「ポむント」を蚭定できるこずを陀きたす。 䞊蚘のスラむドの䟋にあるように、コメントでTIMESTAMPを蚘事13に枡したした。 キヌに名前を付けお、これが第13条のコメントであるこずを明確にしたす。



2぀の芁玠をセットに远加するず、ポむントの降順たたは昇順で䞊べ替えられたリストを取埗できたす。



Redisにはただリストなどのデヌタ型がありたす。 ここで、巊偎、右偎の芁玠セットにプッシュしお、特定のむンデックスから特定のむンデックスに芁玠を取埗できたす。



PHPのクラむアントは䜕ですか



phpredis拡匵機胜があり、Cで蚘述されおいたす。PHP、Rediska、RedisServerで蚘述されたPredisラむブラリもありたす。特定のポヌトで゜ケットを開き、Redisず通信するクラスです。ResidentはRedisServerのフォヌクですが、それでも拡匵機胜を䜿甚したすスピヌドずパフォヌマンスの向䞊のためのphpredis。



もちろん、phpredisを䜿甚するこずをお勧めしたす。これは、すべおのベンチマヌクずテストで高速であり、Cで蚘述されおおり、すべおのphp実装が遅いためです。



次のスラむドは、memcachedずRedisの違いを瀺しおいたす。







実際、Redisずmemcachedの䞡方を特定のタスクに䜿甚する必芁がありたす。 デヌタ構造、セット、゜ヌトされたセットの䞀郚を保存する必芁があり、デヌタを倱うこずができない堎合は、もちろん、Redisが助けになりたす。 Redisはシングルスレッドであるこずに泚意しおください。



次に䟋に぀いお説明したす。







どういうわけか、プロゞェクトでは、補品のクむックビュヌカヌドを衚瀺するだけでした。 このペヌゞには補品のミニチュアがあり、クリックするず補品の詳现な説明を衚瀺する必芁がありたす。 タスクは、バック゚ンドの負荷を可胜な限り枛らすようになりたした。 デヌタベヌスぞのアクセスの枛少など。



このように決定したした







぀たり AJAXリク゚ストがNgnixフロント゚ンドに到着するず、Ngnixにはmemcachedで動䜜できるモゞュヌルがありたす。 最初にキヌでmemcachedのデヌタを芁求し、デヌタがある堎合そしおそこに補品のJSONがある堎合、すぐにこのJSONを返したす。 非垞に高速に動䜜したす。



デヌタがない堎合、リク゚ストはPHPにプロキシされ、2぀の状況がありたす-補品カヌドは、JSONの圢匏でRedisにあり、Redisから取埗しおmemcachedに保存し、クラむアントに枡したす。



Redisずmemcachedのどちらにもない堎合は、MySQLから補品カヌドをリク゚ストし、Redisに保存し、このデヌタをmemcachedに耇補しお返したす。 以䞋のリク゚ストで、補品カヌドはすでにmemcachedから盎接発行されおいたす。



ほずんどのRedisデヌタ型が䜿甚される次のより耇雑な䟋は、パラメトリック怜玢です。







カタログにはカテゎリがあり、各セクションには独自のフィルタセット、぀たり暙準のフィルタパネルがありたす。 各フィルタヌグルヌプには独自のオプションがあり、特定のオプションを遞択する堎合、これらのフィルタヌを満たす補品のリストをナヌザヌに衚瀺する必芁がありたす。



以前は、これはすべおMySQLのク゚リによっお行われ、耇雑な遞択、分析、あらゆる皮類のプロパティがありたした。このセクションにはどのフィルタがありたすかなど。 それはすべお非垞にゆっくりず働きたした。 デヌタストレヌゞモデルを完党に倉曎し、Redisを䜿甚するこずにしたした。 同時に、セクションのフィルタヌオプションごずに、各オプションを満たす補品IDを保存するこずにしたした。







たずえば、IDが100のカテゎリ「電話」には、「メヌカヌ」ず「色」ずいう2぀のフィルタヌグルヌプがありたす。



SamsungのRedisの4぀の補品-201、202、203、204、およびPhilips-301、302、303の4぀の補品があるずしたす。それぞれのキヌには、カテゎリID、フィルタヌ、フィルタヌオプションが含たれおいたす。 ナヌザヌがフィルタヌパネルでSamsungを遞択した堎合、Redisにリク゚ストし、補品IDを取埗しお補品リストコンポヌネントに枡したす。コンポヌネントには4぀の補品が衚瀺されたす。 ナヌザヌが別のフィリップスメヌカヌを遞択した堎合、Redisで2぀のク゚リを䜜成し、これらのセットを結合しお、カタログに7぀の芁玠を衚瀺したす。



さらに、ナヌザヌが別のフィルタヌグルヌプからフィルタヌオプションを遞択した堎合、たずえば、赀色が衚瀺されたす。 サムスンずフィリップスのすべおを赀くしたいので、最初の2぀のオプションを組み合わせお、それぞれ赀の携垯電話ず亀差させ、202、303の2぀の商品を取埗したす。



この実装の機胜-MySQLを䜿甚するよりもはるかに高速ですが、1぀だけありたす。゚ンティティの倉曎ごずに必芁です。 補品のプロパティが倉曎された堎合-補品が芋出しから芋出しに移動し、メヌカヌの補品が倉曎され、補品が有効化/無効化され、フィルタヌが䜜成、倉曎、削陀された堎合、これらすべおのセットを再蚈算する必芁がありたす。 ぀たり これが私たちがしなければならない䞻な仕事であり、キュヌを通しお実装しおいたす。 RabbitMQメッセヌゞブロヌカヌを䜿甚しおセットを再蚈算したす。これに぀いおは埌で説明したす。



キュヌずいえば、「りサギ」に぀いお話したす。 RabbitMQは、AMQPプロトコルを介しおメッセヌゞングシステムを実装するプラットフォヌムです。 このサヌビスの機胜は、信頌性、柔軟なメッセヌゞルヌティングシステム、クラスタリングのサポヌト、キュヌのステヌタスを確認できるさたざたなプラグむンのサポヌト、キュヌ内のメッセヌゞ数の確認、凊理するコンシュヌマヌ、カスタムプラグむンを䜜成しお暙準動䜜を倉曎するこずですブロヌカヌ。 ErlangのRabbitMQによっお曞かれたした。 たた、Java、Ruby、Python、.NET、PHP、Perl、C / C ++など、ほずんどの蚀語の「りサギ」を操䜜するクラむアントがいたす。りサギのWebサむトには、優れたチュヌトリアルず十分に文曞化された機胜がありたす。 各蚀語には䟋もあり、すべおがアクセス可胜な蚀語で蚘述されおいたす。



「りサギ」を䜿甚する際の基本的な抂念は䜕ですか



「りサギ」に含たれる亀換機の皮類、ルヌティングの進行状況に぀いお説明し、プロデュヌサヌからコンシュヌマヌぞのメッセヌゞがワヌクフロヌでどのように発生するかを瀺す図を瀺したす。







プロデュヌサヌPは、メッセヌゞを送信するプログラムです。 メッセヌゞはキュヌに盎接入らず、゚クスチェンゞャヌ-ExchangeXを経由したす。゚クスチェンゞャヌはこのメッセヌゞたたはそのメッセヌゞを送信するキュヌをすでに決定しおいたす。 メッセヌゞが栌玍されるキュヌが存圚するこずは明らかであり、コンシュヌマ、これらのキュヌを読み取り、䜕らかの方法で凊理するプログラムもありたす。



最も単玔なワヌクフロヌ-プロデュヌサヌは亀換機にメッセヌゞを送信し、亀換機はバむンディングキヌを䜿甚しおメッセヌゞを送信するキュヌを決定し、コンシュヌマヌは既に特定のキュヌを読み取っおいたす。 キュヌからメッセヌゞを受信するず、コンシュヌマヌは、はい、受信、凊理、メッセヌゞをキュヌから削陀できるこずを確認できたす。 メッセヌゞが「りサギ」で凊理されるこずを確認するメカニズムがありたす。 消費者がメッセヌゞを受け取っお突然萜ちた堎合、メッセヌゞが凊理されたこずを確認するたでメッセヌゞはキュヌに残りたす。



キュヌからの読み取りを蚭定しお、コンシュヌマヌが取埗したメッセヌゞが垞にピックアップされるようにするこずができたす。 自動確認をtrueに蚭定し、重芁でない堎合は䜕も確認する必芁はありたせん。



どの亀換機がありたすか







最初のタむプは盎接亀換であり、その本質は次のずおりです。亀換機はさたざたなルヌルのキュヌにバむンドできたす。 たずえば、ここでは、バむンドキヌ゚ラヌを介しおExchangeにバむンドされた䞊䜍キュヌ、および譊告キヌを介しお゚クスチェンゞャヌにバむンドされた䞋䜍キュヌがありたす。 亀換機にメッセヌゞを送信するプロデュヌサヌは、メッセヌゞのルヌティングキヌを枡したす。たずえば、スラむド䞊で、赀いメッセヌゞにルヌティングキヌ゚ラヌがあり、バむンドキヌず䞀臎する堎合、リストの先頭に移動したす。 メッセヌゞに譊告ルヌティングキヌがある堎合、぀たり ルヌティングキヌず特定のキュヌのバむンディングキヌずの厳密な䞀臎。 異なる消費者に異なるメッセヌゞを提䟛できたす。



次のタむプの亀換機はファンアりトです。







ここでのポむントは、どのキヌに関係なくキュヌが゚クスチェンゞャヌにバむンドされ、バむンドされるだけで、FanoutタむプでExchangeに送信されるすべおのメッセヌゞがこの゚クスチェンゞャヌにバむンドされるすべおのキュヌに分類されるこずです。 したがっお、1぀のメッセヌゞを送信するこずで、いく぀かの情報を耇数のサヌビスに送信する必芁がある堎合、Fanoutタむプの亀換機を䜿甚でき、メッセヌゞは䞡方の消費ルヌムに分類されたす。



次のタむプは、タむプがトピックの亀換機です。







このタむプの゚クスチェンゞャヌは、キヌを䜿甚しおキュヌにバむンドできたす。キヌには、アスタリスク*やラティスなどの特殊文字を含めるこずができたす。 これはどういう意味ですか バむンディングキヌのアスタリスクは1぀の単語に眮き換えるこずができ、ラティスは0個以䞊の単語に眮き換えるこずができたす。



この䟋では、Q 1キュヌは* .orange。*キヌを䜿甚しおバむンドされ、2番目のキュヌは2぀のキヌにバむンドされたす。 圌女は怠zyで始たるメッセヌゞを受信し、残りは重芁ではありたせん-奜きなだけ他の単語があり、単語はドットで区切られ、2番目のバむンディングキヌは3単語です最初の2぀は重芁ではなく、重芁なのは「うさぎ。」



プロデュヌサヌがスラむドの最初の䟋のようなルヌティグキヌを持぀メッセヌゞを送信した堎合、3぀の単語で構成され、2番目の単語にはオレンゞが含たれ、最埌にりサギずいう単語があるため、䞡方のキュヌに分類されたす。



実際のRabbitMQ。



たずえば、Redis-eのデヌタを再蚈算する堎合䞊蚘参照、「りサギ」を倚く䜿甚したす。 ぀たり デヌタを倉曎する倚くのプロデュヌサヌプロセスがあり、これらのコマンドをキュヌの倉曎に送信したす。2぀のキュヌはありたせん。さらに倚くあり、コンシュヌマは既に特定のメッセヌゞを凊理しおいたす。 たずえば、アむテムAは無効になっおいるため、削陀する必芁がありたす。 JSONの圢匏でメッセヌゞを送信し、次に消費者がそれを読み取り、Redisに接続し、そこにマスタヌスレヌブレプリケヌションがあり、それぞれマスタヌに曞き蟌み、このJSONを解析し、そのようなものを削陀する必芁があるこずがわかりたすそのようなカテゎリやそのようなセットから商品を削陀し、フロント゚ンドはすでにスレヌブのRedisから読み取り、曎新されたデヌタを衚瀺したす。



実際、これがこれらの単玔なツヌル-キャッシングずキュヌ-に぀いお䌝えたかったこずのすべおです。 質問がありたすか



聎衆からの質問 キャッシュの「ディケむ」がどのように実装されおいるか、具䜓的に教えおください。 どのように蚈算し、どのような倀を蚭定したすか たずえば、補品カヌドを衚瀺し、たずえば䟡栌が倉曎された堎合、キャッシュはどれくらいの速さで曎新されたすか



回答 実際、すべおがそこで単玔です-䟡栌を曎新するずき、キャッシュは曎新したせん、タスクの条件に埓っお特に重芁ではありたせん、1時間だけキャッシュしたす、1時間埌にこのデヌタは「悪くなりたす」、すなわち 䟡栌は1時間で曎新されたす。



聎衆からの質問 それでは、より関連性が高いでしょうか プロモヌション䟡栌で販売されおいる補品があるずしたす。明らかに、すぐに出荷されたす。 次に、どのくらいの頻床で残高を曎新したすか



回答 残高をキャッシュしたせん。 , , , memcached , ID, .



: — ?



: , . , memcached, memcached. .



: - , , ? ?



: .



: ?



: 20- «». , Redis, , , , , , 
 20 , . , MySQL. , , , - .



: Redis-. ?



: , , ID , .. , ID .



: — memcached, Redis. , , , memcached , ?



: emcached , ngnix , memcached , Redis , , Redis. , , , popup. Redis , , , , popup, memcached, PHP, , framework, Redis. , . , Redis- , framework, MySQL Redis memcached.



: , - ?



: , , «», , munin- - .



: , , , , . . , , , memcached , , ?



: , , , -



: RabbitMQ , , «» - ?



: , . callback, , .



: RabbitMQ? , , , , , , , , ?



: , , , , . , .



: , RabbitMQ , , ?



: , , .



: , Redis , memcached. memcached ?



: , Redis , memcached, Redis, memcached. , Redis-e . - , , , memcached, . , , .



: memcached? 10%, 20%, 50%?



: , , — - , - , Redis 10% , memcached, . , , . , . .



— HighLoad++ .



- HighLoad.Guide — , , , . 30 . !



— " - ", , HighLoad++ Junior . , , , —



All Articles