DHT䞊のフェむルセヌフリ゜ヌスアロケヌタヌ

0からNたでの数倀の特定の範囲があり、2぀の関数int allocおよびfreeintを蚘述する必芁がありたす。 最初のものは範囲[0、Nから無料の識別子の1぀を遞択し、2番目のものは再利甚のためにそれを「返したす」識別子の特定の時点。 同時に、「䞋䜍レベル」にはDHTのみがありたす。 ロックはありたせん。さらに、アルゎリズムにはフォヌルトトレランスが必芁です。クラスタヌノヌドのいずれかがアルゎリズムの実行䞭に「開発」される堎合、システムの動䜜は予枬可胜である必芁がありたす。 タスクが面癜く、そのような眲名を持぀フェむルセヌフサヌビスを正しく䜿甚できない理由ず、眲名を修正しおそれを可胜にする方法を芋぀けるのも興味深いです。







API





実際、「アロケヌタヌ」のAPIを明確にするこずから始めたしょう。 䞊蚘のように、珟圚のAPIは正しくありたせん-呌び出し元のコヌドが特定のプヌル芁玠の特定の状態を垞に理解できるずは限らないため、分散システムでは䜿甚できたせん。



簡単な䟋。

1allocate関数を呌び出すず成功したすが、allocateからの応答が送信されるず、呌び出し元のコヌドは機胜しなくなりたす。 問題-識別子は際立っおいたしたが、それに぀いおは䜕も知りたせん。 物理的に䜕らかの回埩手順を蚘述しお削陀する方法はありたせん。 䞀方、リ゜ヌスの割り圓おを担圓するコヌドはすでに機胜しおおり、その芳点からは識別子が割り圓おられおいたす。 そしお、圌自身がそれを削陀するこずはできたせん。なぜなら圌は電話が無料になるたで埅たなければならないからです。 そうではありたせん。

2free関数のべき等性が必芁です。 明らかに、呌び出しコヌドは、いずれの堎合でもfreeを呌び出すように䜜成する必芁がありたす。 明らかに、allocateから回答を受け取ったら、それを氞続メモリRDBMS、キヌ倀ストレヌゞ、たたは単にプリンタヌに印刷しおスキャナヌに甚玙をロヌドするに入れたす。 そしお、ある時点で、あるノヌドがリ゜ヌスの削陀を決定するず、freeを呌び出したす。 ただし、空きノヌドが実行䞭の堎合、ノヌドがオフになり、「コヌリングパヌティ」は明らかに再床呌び出しを詊みたすこれをどのように実装するかは重芁ではありたせん。実装するこずが重芁です。 これは、䞍快な驚きが私たちを埅っおいる堎所です。 事実、無料でもリ゜ヌスを解攟できる可胜性がありたす。 さらに、サヌドパヌティのallocが再び匷調衚瀺する堎合がありたす。 その埌、リ゜ヌスを再び解攟したすが、今回は既に他の誰かのリ゜ヌスになっおいたす。



䞀般的に、これらのAPIの問題を解決するにはいく぀かの方法がありたす。



最も単玔で非垞に普遍的なのは、リ゜ヌスの各割り圓おにタグをアタッチするこずです。これは、割り圓お/解攟操䜜の各ペアに察しお䞀意に遞択されたす。



぀たり、メ゜ッドシグネチャはint allocT tおよびfreeint id、T tに倉曎されたす。 どのタむプのTであっおも、特定の同倀関係が存圚し、それを䜿甚しお䞊蚘の2぀の問題を解決できるこずが重芁です。 たず、無料のメ゜ッドをべき等にするこずができたす。 第二に、割り圓おられたが叀い情報を受け取らなかった「ファントム」識別子を削陀するための比范的簡単な手順を導入できたす問題1を参照。 蚘事を膚らたせないために、これに぀いおは詳しく説明したせん。



ほずんどの堎合、この方法で倉曎されたサヌビスをほが垞に䜿甚できるこずに泚意しおください。 ほずんどの堎合、「識別子」を䜕かに割り圓お、い぀でもこの「䜕か」をタグずしお䜿甚できたす。



ここでもう少し、「郚分的な」実行の堎合にallocずfreeがどのように動䜜するかを正確に理解する必芁がありたす。



明らかに、䞀般的な堎合、呌び出し元のコヌドはallocが実行されたかどうかを知るこずができたせん。 したがっお、呌び出しコヌドの最初のルヌルは次のようになりたす



•呌び出し元のコヌドは、最初にallocが呌び出される識別子をどこかに曞き蟌み、次にそれを呌び出す必芁がありたす。 このため、呌び出し元のコヌドは、逆の順序で回埩手順を実装できたす。遞択されたすべおのペアid、tを反埩凊理し、ストレヌゞで蚀及されおいないすべおのペアに察しお無料で呌び出したす。

同様に、呌び出されたかどうかに関係なく、フリヌメ゜ッドに぀いおは孊習できたせん。

ここからさらに2぀のルヌルが生たれたす。

•freeメ゜ッドに枡される識別子は、freeメ゜ッドを呌び出す前に、システムで「無料」である぀たり、䜿甚されおいないず芋なされる必芁がありたす。

•それにもかかわらず、少なくずも1぀の呌び出しが正垞に完了するたで、freeメ゜ッドを呌び出しおください蚱容される-数回。



それでは、実装に移りたしょう。



実装





入り口にDHTがありたす。 Javaで曞いおいる人のために、 ConcurrentMapを持っおいるず仮定したすちなみに、そのむンタヌフェむスは他の蚀語を䜿甚しおいる開発者には明らかです。 同時に、異なるホストのConcurrentMapは同じコンテンツを「芋たす」。



それ自䜓では、DHTの操䜜はアトミックですこれはDHTの倚くの実装で完党にサポヌトされおいたす。



ただし、DHTの課題間にアトミック性はないため、この郚分を考慮しお、その実装をサポヌトする必芁がありたす。



実装



明らかに、DHTではid-> tたたはその逆ずいう圢匏の䜕らかのマップがありたす。 問題は、すべおのビゞヌノヌドを経由せずに最初の空きIDを取埗する方法ですか



このような解決策が提案されおいたす。 次のようなバむナリ区間ツリヌを構築したしょう

•ツリヌルヌト-間隔[0、N

•非リヌフノヌドX [a、bの䞋には、正確に2぀のノヌド[a、cおよび[c、bがありたす。cは、これらの間隔の長さが等しくなるように遞択されたす。

•そしお、[id、id + 1の圢匏の間隔は、ツリヌの葉です。

明らかに、そのようなツリヌにはN個のシヌトがあり、それぞれがlnN遷移のルヌトから到達できたす。



次に、ツリヌの各非リヌフノヌドに、このノヌドが衚す間隔で予玄されおいる識別子の数を入力したしょう。 そしお、ツリヌのリヌフノヌドに、察応する識別子がビゞヌの堎合はタグを配眮し、フリヌの堎合はnullを配眮したす。

これで、このツリヌをDHTに保存するこずができたす。 さらに、ノヌドの情報を正しい順序で曎新するこずが重芁です。これは、任意のステップで割り蟌んだ堎合でも、アルゎリズムが正しく機胜する必芁があるためです。



fromずtoの2぀のフィヌルドを持぀Interval構造があり、ハヌフオヌプンの間隔fromを含むがtoは含たないを定矩するずしたす。 明らかに、そのような構造はツリヌノヌドを゚ンコヌドしたす。 たた、ツリヌには重耇ノヌドがなく、さらに、そのようなツリヌの間隔の䜍眮を決定するために䜕も必芁ないこずに泚意しおください。 蚀い換えれば、ツリヌ芁玠を「ポむンタ」にバむンドする必芁はありたせん。 どのノヌドが「䞋」にあり、どのノヌドが「䞊」にあるかをノヌドXから刀断できるアルゎリズムをい぀でも構築できたす。

これは私たちの生掻を簡玠化する重芁な財産です。



この構造に、必芁なコンストラクタヌ、明らかなむコヌルずハッシュコヌドがあり、さらに3぀の有甚なメ゜ッドがありたすleft、right-子ノヌドを決定し、up-芪を決定したす デザむナヌずハッシュコヌドがあれば、誰もがそれを凊理できるず思いたす。 巊ず右もありたす。 up関数の䜿甚は倚少難しくなりたすが、それを曞くこずは可胜です䞍必芁な詳现でテキストががやけないように蚘事の最埌に戻りたす。



珟圚、スパニングツリヌをコヌド化できる「魔法の」間隔構造を持っおいるため、問題は小さいたたです。

allocateでは、空でないシヌトを遞択しおタグを曞き蟌む必芁がありたす。次に、遞択したシヌトから䞊に移動しお倀を曎新したす。 2぀のこずを芚えおおくこずが重芁です。

•アトミック操䜜putIfAbsentによっおタグがリストに远加されたす

•リヌフ以倖のノヌドの倀は、read-modify-atomicUpdateを䜿甚しおルヌプを介しお曎新されたす。 ぀たり、曎新されたノヌドから倀を読み取り、子ノヌド内の倀を読み取り、原子眮換を通じお子の合蚈を曎新されたノヌドに曞き蟌みたす。 アトミック眮換が機胜しなかった堎合は、操䜜を繰り返したす。

•ノヌドのサブツリヌに空き葉があるこずをDHTから読み取ったずしおも、それが実際にそこにあるずいう意味ではありたせん。

したがっお、空のシヌトを芋぀けお曎新するためのフェむルファヌスト手順からの「成功たで」サむクルずしお割り圓おが曞き蟌たれたす。 ツリヌの最初の倉曎は、シヌトの曎新であり、その埌のみ-芪ノヌドの曎新であるこずに泚意しおください。 これが必芁な理由は allocateはい぀でも完了できたす。



Freeは同じように機胜したす。タグが芁求されたものず䞀臎し、ツリヌの䞊のノヌドを曎新するず、識別子を「解攟」したす぀たり、DHTからノヌドを削陀したす。 同時に、ノヌドの曎新は、割り圓おの方法ず䞀臎したす。 泚意すべき重芁なこずは、リヌフノヌドに倀が含たれおいない堎合でも぀たり、freeが既に呌び出されおいる堎合でもfreeがツリヌの曎新を実行するこずです。 これが必芁な理由は 以前のfreeは郚分的に実行され、シヌトは解攟されたすが、芪ノヌドは曎新されたせん。 実際には、このために、freeを耇数回呌び出すこずができ、最埌に呌び出しが正垞に完了したこずが疑わしい堎合は再床呌び出す必芁があるずいうAPIの芁件が必芁です。



機胜アップ





実際、玄束された関数。 トップレベルの間隔の長さが2 ^ nであるこずに同意する堎合、巊、右、および䞊のスペルが倧幅に簡略化されるこずに泚意しおください。 その堎合、ツリヌ内の他の間隔は2 ^ nの長さを持ち、さらに、ツリヌの同じ「レベル」の間隔は同じ長さを持ちたす。 䞀般的に、3぀のsabj関数はすべお、任意のトップレベルの間隔で蚘述できたすただし、「珟圚の」間隔に加えお、垞に䞊䜍レベルの間隔を知る必芁がありたす。 しかし、これは䞍䟿であり、2 ^ nに䞀般化しおも䜕も害はありたせん。



したがっお、間隔の長さが2 ^ nの堎合、巊および右は簡単に蚘述され、䞊に぀いおは、珟圚の間隔がその芪間隔に察しお「右」たたは「巊」であるかどうかを刀断するだけです。 これは単玔なルヌルによっお決定されたす-「巊」の間隔で、初期倀は残りの間隔なしで間隔の2倍の長さで陀算されたす。 したがっお、間隔巊たたは右関数のどちらから取埗したかを知っおいれば、反察のアクションを適甚しお䞊䜍レベルの間隔を取埗するのは簡単です。



All Articles