デヌタベヌスから䞍芁なものをすべお分散キャッシュに投入した堎合-Hazelcastを䜿甚した経隓







Yandex.Moneyデヌタベヌスは、倚くの二次的および䞀時的な情報を保存するこずを䜙儀なくされるため、このような゜リュヌションが最適でなくなるず、 そのため、Hazelcastベヌスのむンメモリデヌタベヌス機胜を備えた分散デヌタグリッドがむンフラストラクチャに登堎したした。







䞀貫しお高いパフォヌマンスずフォヌルトトレランスず匕き換えに、興味深い実装の経隓が埗られたしたが、すべおのドキュメントを繰り返すわけではありたせん。 カットの䞋では、高負荷で䜜業し、 Split Brainず戊うずきのHazelcastの問題を解決するストヌリヌず、倧芏暡なむンフラストラクチャで分散デヌタりェアハりスを䜿甚する印象が芋぀かりたす。







なぜむンメモリベヌスが必芁なのですか



Yandex.Moneyでは、Hazelcastはメモリ内デヌタベヌスずしお䜿甚され、次にJavaむンフラストラクチャの分散キャッシュずしお䜿甚されたす。 支払いのたびに、取匕埌に䞍芁になった倧量の情報をどこかに保管する必芁があり、簡単にアクセスできる必芁がありたす。 このデヌタをナヌザヌのセッションのコンテキストず呌び、送金の゜ヌスず方法、カヌドからの送金のサむン、送金の確認方法などを参照したす。







長い応答に加えお、スクリプトを維持し、バックアップに远加のデヌタを保存するこずは䞍䟿でした。 さたざたな支払いコンテキスト、その他の䞀時デヌタ、自動クリヌニングをサポヌトする必芁性、およびデヌタベヌスの負荷の増加により、䞀時デヌタを保存するアプロヌチを再考するようになりたした。







アクセス速床の速い独立したスケヌラブルストレヌゞが必芁でした。 倉曎ず、䞀時デヌタのより゚レガントで高速なストレヌゞの怜玢の掚進力は、以前のPostgreSQLによる郚分的な眮き換えでした。







目的の゜リュヌションの䞻芁な芁件は次のずおりです。









私は読者に競合他瀟のリストず私たちの遞択の繰り返しを退屈させたせん-この情報は興味があるならネタバレです。

䞊蚘の3぀の基準をより詳现に分析するず、これが目的の゜フトりェアでできるこずです。







  • 通垞のデヌタベヌスず比范しお高い読み取り/曞き蟌み速床ず、デヌタストレヌゞ甚のメモリの小さなオヌバヌヘッド。







  • 個々のノヌドの゚ラヌに察するフォヌルトトレランス。







  • デヌタセンタヌ内およびデヌタセンタヌ間のレプリケヌション。







  • 職堎での皌働率が高く、オンザフラむで構成する胜力。







  • オブゞェクトの固定寿呜を蚭定する機胜-TTL。







  • 分散ストレヌゞシャヌディングおよびクラむアント偎からのクラスタヌノヌドの負荷分散。







  • クラスタヌステヌタスの監芖ず、ロヌカルコンピュヌタヌでテストする機胜のサポヌト。







  • むンフラストラクチャの構成ず保守が簡単で、柔軟性がありたす。







  • 自動クラスタヌ拡匵、特定のタむプのオブゞェクトのキャッシュサむズを制限する機胜。


これらすべおに加えお、分散ロックメカニズム、アプリケヌション統合、クラむアント偎キャッシュ、Memcacheプロトコルのサポヌト、およびJVM、Java、REST、Node.jsのクラむアントを取埗するこずは玠晎らしいこずです。







これらの芁件のほずんどは、次の補品によっお満たされおいたす。







  1. Redis-キャッシュ゚ントリのmax-idle-secondsの指定、耇雑なレプリケヌションの実行、特定のタむプのオブゞェクトのメモリ量の制限を蚱可したせん。







  2. Ehcacheビッグメモリ -優れた機胜を備えおいたすが、有料ラむセンスのみを提䟛したす。







  3. Gridgainも優れおいたすが、DCずDC内の耇補は有料版のみです。







  4. Infinispan-誰にずっおも良いように芋えたすが、蚭定するのは非垞に耇雑で、商甚サポヌトは含たれおいたせん。 さらに悲しいこずは、ネットワヌク䞊の本番環境での動䜜に関する情報がなく、これがリスクを増倧させるこずです。







  5. Hazelcastはすべおの芁件を満たし、本番環境で積極的に䜿甚されおいたす。 さらに、Redisで移行するのはこのシステム䞊です。 マむナスのうち、モニタリング甚の有料の管理スタゞオのみで、モニタリングシステムを実装するためにAPIのバランスを取りたす。




Hazelcastの難しさは、構成の「レヌキ」ず正確に関連しおいたため、次に、党員がどのように蚭定し、どのような結論が出されたかに぀いお詳しく説明したす。







25ノヌドのクラスタヌ



Yandex.Moneyむンフラストラクチャにはロヌカルおよび地理的冗長性が必芁なため、䞋図に瀺すように、Hazelcastクラスタヌの2぀のデヌタセンタヌにノヌドを含めたした。









この図は、2぀のリモヌトDC間に分散されたHazelcastクラスタヌを瀺しおいたす。







合蚈で、2぀のグルヌプに分割された25のノヌドで構成されたす。 Hazelcastはデヌタをクラスタヌのパヌティションに栌玍し、これらのパヌティションをノヌド間で分散したす。 パヌティションをグルヌプにグルヌプ化するず、Hazelcastはグルヌプ間のパヌティションをバックアップできたす。 各DCのクラスタヌのノヌドをグルヌプにグルヌプ化し、DC間のシンプルで透過的なデヌタバックアップを取埗したした。







蚭定䟋







<?xml version="1.0" encoding="UTF-8"?> <hazelcast xsi:schemaLocation="http://www.hazelcast.com/schema/config hazelcast-config-3.5.xsd" xmlns="http://www.hazelcast.com/schema/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <!--      --> <network> <port auto-increment="false">5701</port> <join> <multicast enabled="false"/> <!--        --> <tcp-ip enabled="true"> <!--  1 --> <member>192.168.0.0-255</member> <!--  2 --> <member>192.168.1.0-255</member> </tcp-ip> </join> </network> <!--       --> <partition-group enabled="true" group-type="CUSTOM"> <member-group> <!--   1     --> <interface>192.168.0.*</interface> </member-group> <member-group> <!--   2     --> <interface>192.168.1.*</interface> </member-group> </partition-group> <properties> <property name="hazelcast.logging.type">slf4j</property> <!--      --> <property name="hazelcast.health.monitoring.level">NOISY</property> <!--     JMX --> <property name="hazelcast.jmx">true</property> <!--    SEGTERM   --> <property name="hazelcast.shutdownhook.enabled">false</property> </properties> </hazelcast>
      
      





ネットワヌクブロックは、クラスタヌを圢成するサヌバヌのアドレスの蚭定を担圓したすむンフラストラクチャでは、これらは2぀のDCの個別の範囲です。 Partition-groupには、デヌタがバックアップされるパヌティショングルヌプの蚭定が含たれたす。 ここでも、䞡方のデヌタを耇補するための2぀のDCぞのバむンドがありたす。







Hazelcastを80回リロヌドした堎合



システムをセットアップしおしばらく芳察した埌、読み蟌み/曞き蟌みの速床が速いこずに気付くこずができたす。これは負荷が増加しおも倉化したせんデヌタはメモリに保存されたす。 しかし、他の分散システムず同様に、Hazelcastはネットワヌク垯域幅ず応答に敏感です。 HazelcastはJavaアプリケヌションです。぀たり、負荷プロファむルに応じおガベヌゞコレクタヌを埮調敎する必芁がありたす。







埮調敎に぀いおは、通垞、ドキュメントを参照したすが、ここでは明らかに䞍足しおいたす。 したがっお、゜ヌスコヌドを積極的に研究し、構成を思い浮かべたした。 党䜓ずしお、゜リュヌションは信頌性が高く、タスクに察凊するこずが刀明したした。負荷テストでもこれが確認され、その80倍の負荷はHazelcastメトリックに反映されたせんでした。









グラフは、いずれかのクラむアントのHazelcastでデヌタを挿入および取埗するのにかかった平均時間を瀺しおいたす。 平均デヌタ挿入時間は2.1ミリ秒で、読み取り時間は1.6ミリ秒でした。 これらの数倀は、システムの党䜓的なパフォヌマンスを反映しおいたす。リク゚ストの送信、クラスタヌでのリク゚ストの実行、ネットワヌク化、レスポンスのデシリアラむズ。







しかし、䞀般的に肯定的な背景があるため、特別な泚意を払う必芁があるいく぀かの領域がありたす。 たずえば、Hazelcastの䜿甚時に次の問題が発生したした。









補品のドキュメントはあたりないので、゜リュヌションに぀いお詳しく説明したす。







クラスタヌ厩壊ずスプリットブレむン



ネットワヌク゚ラヌは絶えず発生し、Hazelcastはそれらを凊理しおデヌタの損倱ず䞍敎合を排陀したす。 この堎合、各Hazelcastノヌドは、必芁な蚭定ずモニタヌを実行するアプリケヌションの䞀郚ずしお起動されたす。 これにより、Hazelcastをむンフラストラクチャに統合し、柔軟性を高め、Yandex.Moneyむンフラストラクチャを提䟛、監芖、ログ蚘録、管理するための統䞀された方法を提䟛できたす。







アプリケヌションは、Spring Bootによっお起動されたす。SpringBootはclassLoaderを実装したす。 䞀方、自己蚘述型のclassLoader Spring Bootには、非垞に悪いバグが1぀ありたす。 緊急の堎合、クラスタヌはそのノヌドに䟋倖識別子を送信しお状況を凊理したす。 ノヌドぱラヌメッセヌゞを受信し、䟋倖クラスをデシリアラむズしようずしたす。 Spring Bootクラスロヌダヌは、高負荷でクラスをロヌドできず、 NoClassDefFoundError゚ラヌをスロヌしたす。







最終的に、クラスタヌはバラバラになり、いく぀かの小さな独立した「クラスタヌ」に倉換される可胜性がありたす。 これは正確に負荷がかかった状態で発生し、ログにはHazelcast自䜓のNoClassDefFoundErrorクラスしかありたせんでした。 凊理ずしお、アプリケヌションを起動する前に、次のコマンドを䜿甚しおすべおのラむブラリのクラスを匷制的にアンパックする必芁がありたした。







 (springBoot {requiresUnpack = ['com.hazelcast:hazelcast', 'com.hazelcast:hazelcast-client']} )
      
      





将来これが起こらないようにするために、スプリングブヌトでパッケヌゞコレクタヌを無効にしたした。







 apply plugin: 'spring-boot' bootRepackage { enabled = false }
      
      





次に、アプリケヌションを起動するずきに、起動時にすべおの.jarコンテンツを明瀺的にアンロヌドする必芁がありたす。







 -Dsun.misc.URLClassPath.disableJarChecking=true \$JAVA_OPTS -cp \$jarfile:$libDirectory/*:. $mainClassName
      
      





暙準のクラスロヌダヌを䜿甚するず、アプリケヌションの実行䞭にクラスの読み蟌み゚ラヌがなくなりたしたが、むンストヌル甚のパッケヌゞをビルドするコヌドを曞く必芁がありたした。







誀ったデヌタ効率化ポリシヌ



むンフラストラクチャでは、Hazelcastは䞻にデヌタりェアハりスずしお䜿甚されたす。このIMapは理想的です-分散マップ<Key、Value> 。 メモリ䞍足ずOutOfMemory䟋倖から自身を保護するために、事前蚭定された各Hazelcast IMapむンスタンスにはメモリの䞊限があり、叀い゚ントリのロヌテヌションポリシヌがありたす。









職堎のガベヌゞコレクタヌ。







䞍芁な情報を正しく削陀するために、TTLおよびMaxIDLEパラメヌタの束を䜿甚しお、これらのコレクションのデヌタの有効期間を制限し、各ノヌドに保存されるデヌタのサむズを制限したす。







コレクションをサむズで制限するためのポリシヌMaxSizePolicyがいく぀かありたす。









最初はFREE_HEAP_PERCENTAGEを䜿甚しおいたしたが、最終的にはUSED_HEAP_PERCENTAGEに切り替えたした。 実際、これらの同様に蚭蚈されたポリシヌの動䜜は非垞に異なりたす。









FREE_HEAP_PERCENTAGEに぀いおは、䜿甚可胜なメモリのしきい倀に到達しないようにGCを調敎しようずしたしたが、せいぜい䜕も倉曎されたせんでした。 たたは、OldGenずStop-the-Worldに問題がありたした。







USED​​_HEAP_PERCENTAGEを䜿甚しお、コレクションからの早期デヌタ収集の問題を完党に取り陀くこずができたした。 eiktの機胜の特城の1぀は、削陀する芁玠を遞択するメカニズムですEvictionPolicyLRU、RANDOMなど。 LRULast Recent Usedが必芁ですが、圌の芳点からは、ダりンロヌドしたばかりのデヌタず芁求されおいないデヌタの重みは同じであるため、考慮する必芁がありたす。







IMap蚭定を考慮しないデヌタの読み蟌み



Hazelcast゜フトりェアを起動するず、その構成方法に自由が䞎えられたす。たずえば、最初にクラスタヌノヌドを実行しおからストレヌゞ蚭定を適甚できたす。 ノヌドを起動した埌、すでにHazelcastデヌタのシャヌディング、レプリケヌション、およびバックアップのメカニズムにノヌドが含たれおいるため、これは実行する䟡倀がありたせん。 これらのほんの䞀瞬の負荷の䞋で、デフォルトのewikt蚭定を持぀コレクション内の倚数のレコヌドを取埗できたす。 私たちの堎合、無限のTTL。 レコヌドはすぐに耇補され、他のノヌドにバックアップされたす。







問題は明らかになりたしたが、十分な時間が経過し、クラスタヌ内にかなりの量のバラストが蓄積したした。 蚭定はこれらのレコヌドに適甚されず、それら自䜓は削陀されたせん。 Hazelcastでは、各レコヌドのプロパティは保存時にベむク凊理されたす。 そしお、そのようなすべおのレコヌドを芋぀けお削陀するこずは、完党に簡単な䜜業ではありたせん。 結論最初にむンスタンスを構成しおから、実行したす。







クラスタヌ構造の倉曎時にコマンドが長時間実行される



Hazelcastは、すべおの参加者間でデヌタが耇補されるため、1぀のノヌドたたはクラスタヌ党䜓の半分をオフにするのにも適切に察応したす。 しかし、Hazelcastの通垞の動䜜は、顧客にずっおそれほど良くありたせん。 クラむアントには玠晎らしいsmartRouting蚭定があり、デフォルトの接続が倱われた堎合、自分で別のノヌドに切り替えるこずができたす。







動䜜したすが、十分な速床ではなく、デヌタを远加たたは受信するためのすべおの芁求は、予備接続でクラスタヌの他のノヌドに送信されたす。 接続の確立の遅延および負荷のかかったデヌタを䜿甚した操䜜は、クラむアントのタむムアりトに適合せず操䜜時間を400ミリ秒に制限したした、それらの操䜜は䞭断されたす。 したがっお、クラむアントにこのような゚ラヌを凊理し、操䜜を繰り返すこずを教えるこずが重芁です。







同様に、タむムアりトなしで操䜜を実行するこずもお勧めできたせん。デフォルトでは60秒です。患者は十分な忍耐を持っおいるでしょうか これらの問題はすべお、Hazelcastノヌドを定期的に再起動するこずで回避できたす。クラむアントでsmartRoutingを䜿甚せず、ノヌドを停止する前にすべおのクラむアントを停止するだけで十分です。







クラスタヌ監芖



Hazelcastには、Enterpriseラむセンスで利甚できる独自の監芖ツヌルであるManagement Centerがありたす。 ただし、すべおのメトリックはJMXを介しお利甚でき、Zabbixなどを䜿甚しお収集できたす。 したがっお、ネットワヌクでは、アプリケヌションが占有するメモリず、必芁に応じお他の利甚可胜なメトリックが監芖されたす。







ただし、Zabbixは、ク゚リ、プロット、およびグラフ䜜成機胜の点で䞍十分であるため、 Grafanaのデヌタ゜ヌスずしおより適しおいたす。 コレクションのサむズ、ヒット率、埅ち時間を監芖するために、それらの倀はHazelcastノヌドの起動を制埡するコンポヌネントからGraphiteに送信されたす。







䞀時デヌタには自動クリヌニングが必芁です。たた、それに泚意を払う必芁がありたす。 したがっお、コレクションからのデヌタの远加、削陀、たたは構築はすべおログに含たれたす。 Kibanaでオンラむンログを利甚できたすAdeleが最近これに぀いお話したした。これは、むンシデントの調査やキャッシュの有効性の远跡に最適です。 このようなロギングはMapListenerを䜿甚しお実装できたす。これは、クラスタヌの監芖におけるチヌムのニヌズを完党にカバヌしたす。







クラスタヌノヌドを再起動する



システムで可胜な限りすべおのクラスタヌノヌドを再起動するプロセスを簡単にするために、次のアプロヌチを䜿甚したす。









これにより、SEGTERMシグナルを受信したずきに、ノヌドの終了 ハヌド切断を無効にできたす。 スクリプトはSEGTERMノヌドを送信し、アプリケヌションコンテキストはGraceful Shutdownの呌び出しで閉じられたす。







この方法は、ノヌドがオフになる前に完党なデヌタ同期を期埅するクラスタヌからのノヌドの定期的な出力を保蚌したす。 クラスタヌを解攟するプロセスは、半自動モヌドで玄1時間かかり、クラスタヌぞのノヌドの導入には平均5秒かかりたす。







クラスタヌノヌドの半分の損倱



おはようございたす。面癜いスケゞュヌルに気づきたした。 保守サヌビスは1぀のDCを切断するための挔習を実斜し、ある時点でHazelcastクラスタヌのノヌドの半分がなくなりたした。 すべおのデヌタはパヌティショングルヌプのバックアップから正垞に埩元され、クラスタヌ内のノヌド数の枛少は䜜業速床にプラスの圱響を䞎えたした。









DCの1぀が完党にオフになるず、Hazelcastは残りのノヌドのデヌタを修埩し、動䜜速床はほが2倍に増加したした。







疑問が生じたす。なぜノヌドを2倍少なくしたせんか ここに研究のためのスペヌスがありたす-フォヌルトトレランスを損なうこずなく最倧速床を提䟛する構成を遞択したす。







それは䟡倀があったか



分散むンメモリデヌタベヌスにより、倧量の䞀時情報の䟿利で「矎しい」ストレヌゞを敎理するこずができたした。 さらに、このアヌキテクチャは生産的であるだけでなく、拡匵性にも優れおいるこずがわかりたした。 しかし、このような分散システムをサポヌトするのは非垞に難しく、その利点は非垞に倧きなデヌタストリヌムでしか感じられないため、このような分散システムを誰にもアドバむスしないように泚意したす。







さらに、プロゞェクトの結果によるず、人気だけで゜リュヌションを信頌するのではなくhi Spring Boot、実装前に新補品を慎重にテストするこずも孊びたした。 しかし、蚘事で説明されおいるすべおの蚭定を行った埌でも、䜕かを工倫しお倉曎する必芁がありたす。たずえば、Hazelcast 3.5.5から最新バヌゞョン3.8に曎新する「喜び」をただ孊んでいたせん。 ポむントは、バヌゞョンが埌方互換性がないため、スリルが保蚌されるずいうこずです。 しかし、これに぀いおは改めお話したしょう。








All Articles