どのように私は心配を停止し、キャッシュを愛して


ここで更新されたバージョンをチェックしてください


導入


この第2のエピソードは我々が始めたものに従います、そして、キャッシュライティング技術についてあります.

Please Note
If you're looking for an introduction about caching in general and reading techniques, you can go


え?書くテクニック?


I am still food drunk. GIMME THE CODE
私は、完全にあなたの驚きをここで見ます.読んでいるテクニックでは、すでにどのように、そして、いつキャッシュ層に書くかについて言及しました.
我々は実際に読書のアクションに関係している読書技術を呼び出している.たとえば、トランザクションのリストを取得します.だから、すでに書いていたとしても、実際には読書をする目的だけを書いている.
それで、書くテクニックは基本的に、キャッシュを移入するか、更新するために書く行動の間、使用される戦略です.あなたがそれらから得る利点の最大の部分は、あなたがその後データを読むつもりです.アクションを書く例としては、新しいトランザクションを作成し、ユーザ情報を編集するなどです.
このように、これらのパターンについて話します.
  • 通す
  • 後書きする
  • 書く
  • 前回は、参加者です

  • クライアント:データを必要とする人

  • キャッシュ:データを格納する場所

  • リソースマネージャー:クライアントにリソースを提供します

  • データアクセサー:アプリケーションの外部からデータを取得します.
  • write - through (インラインで書く)


    正確に読み込み(またはインラインインライン)のように、クライアントとデータアクセサーの間に行に座っているリソースマネージャーを持っています.
    この図は、Write - throughを使用している書き込みアクションのライフサイクルを示します

    次の手順を実行します.
  • クライアントはリソースマネージャを呼び出す書き込みアクションを開始する
  • リソースマネージャはキャッシュに書き込みます;
  • resource managerはデータのアクセサーの呼び出しを書き込む
  • 応答はクライアントに提供されます.
  • 根拠


    一見すると、それは賢い動きのように見えません:我々は実際に余分なステップを追加する要求を減速しています.では、この戦略から何を得ているのでしょうか.
    我々が複数回言ったように、キャッシュされたデータによる最大の問題の1つは、彼らが古くなるということです.さて、このパターンはこの問題を解決します.
    他の記事では、古いエントリに対処する1つの方法がTTLを使用していて、それがまだ本当であるということを見ました、しかし、その場合、我々がフェッチしていたデータを生産していなかった時から、満了は問題を解決する最も良い方法でした.今、我々は我々が読みたいデータをコントロールしています、そして、キャッシュされたエントリが決して古くなっていないことを確実とするデータを書くたびにキャッシュを更新します.
    もちろん、影のない光と書き込み待ち時間の他にありません1 , クライアントがしばしばデータを読む必要がないとき、このテクニックは有害になります.この場合、実際には、あなたは生きていて、読書利益を得ることなくキャッシュを同期させ続けるために必要なリソースを浪費します.

    後書きする


    この他のテクニックはまだリソースマネージャinlineを持っていますが、データアクセサーを通した書き込みは非同期的に起こります.

    これらはアクションライフサイクルに関わるステップです.
  • クライアントはリソースマネージャを呼び出す書き込みアクションを開始する
  • リソースマネージャはキャッシュに書き込みます;
  • 応答は、クライアントに提供されます
  • 最終的に、リソースマネージャはデータアクセサーの呼び出しを書き込みます.
  • 根拠


    なぜこのキャッシングテクニックが役に立つのかを理解する最良の方法は例を挙げることです.
    我々が現在発展していると仮定してくださいTrulyAwesomeBankAPI そして、私たちはPayment キャッシュを使用したトランザクションの作成.支払いは可能な限り速く起こる必要があります、しかし、我々のAPIを支持している本当にものすごい銀行はまだ非常によくピークを取り扱うことができない古い基盤にあります.
    私たちは、書くことを使うことに決めます.これは、私たちがPayment そのトランザクションをキャッシュに保存し、クライアントに応答を返します.その後、別のワーカールーチン(バックグラウンドで実行し、別のプロセスでは、cron式や何かに基づいて)これは本当に素晴らしい銀行に属している本物の元帳と元帳のキャッシュされたバージョンの同期の世話をする.本当に素晴らしい銀行が与えられた時間でサポートすることができますどのように多くの要求に関係なく、我々はすぐに応答を提供することができますこの方法.
    外部データソースを待つ必要がないので、パフォーマンスと安定性を得ています.これにより、アーキテクチャは外部サービスに対してより耐故障性を持ち、新たな弾力性の可能性が開きます.例えば、単純なリトライ戦略や、クライアントに影響を与えることなくサーキットブレーカを実装することができます.
    我々が支払っている価格は一貫性です:労働者が同期プロセスの実データ(本当にものすごい銀行に住んでいるデータのように)を完了する前に、そして、我々がサーブするデータ(キャッシュに住んでいるデータのように)は異なります、そして、我々がエラーケースに対処する方法について考え始めるならば、ものはより複雑になることができます2 .

    書く


    さて、完全性のためだけに、我々は書くことに言及するべきです、しかし、私にとって、それは本当のパターンに見えません.実際には、次の図では「キャッシュ」という単語のトレースは見つかりません.

    基本的には、「読む時間だけで直接データアクセサーとキャッシュデータを呼ぶ」ということは、「書くことなしにどんな読書戦略も適用する」という意味です.

    根拠


    あなたがこの非パターンを使用する理由は、上記の書き込みテクニックのどれもあなたのために良いからではありません.多分、あなたは、超一貫したデータを持っている必要があるかもしれません.
    これらの場合、書き込みテクニックを適用しない場合(または、書き込みを使用して、希望する場合)だけで動作します.

    何かコードを書きましたか。


    You can find a more detailed version of these examples here

    シカアン / デザインパターン

    実生活コードにおける設計パターンの使用例

    デザインパターン

    Examples of usage of design patterns in real life code

    These are the reference resources for


    はい.今回はPython.
    私がここで提供している例は、タイマーを使用した遅い書き込み外部サービスをシミュレートしています.特に、我々は何かをシミュレートすることですTrulyAmazingBankAPI : 保存するトランザクションを作成します.
    アプリを起動し、いくつかの秒では、正確に何が何を書くの間に発生し、背後にある書き込みを見ることができます.
    出力ケースをケースで調べましょう.
    書く
    >>> Save transaction
    [14:59:17.971960] CacheManager.set
    [14:59:17.971977] TrulyAwesomeBankAPIClient.save_transaction
    >>> Get transaction
    [14:59:19.974781] CacheManager.get
    
    ここで私たちが行う最初のことは、キャッシュ内のエントリを保存し、AwesomeBankに保存し、数秒後に私たちが保存したトランザクションを取得したい場合は、キャッシュを使用して取得します.
    後書きする
    >>> Save transaction
    [14:59:24.976378] CacheManager.set
    >>> Get transaction
    [14:59:21.978355] CacheManager.get
    
    --------------------------------------------
    |    AWESOME BANK DATABASE (before sync)   |
    --------------------------------------------
    {}
    
    [14:59:26.974325] TrulyAwesomeBankAPIClient.save_transaction
    
    --------------------------------------------
    |    AWESOME BANK DATABASE (after sync)    |
    --------------------------------------------
    {
       UUID('0f41f108-0859-11e9-a138-b46bfc6c5cb9'): {
          'id': UUID('0f41f108-0859-11e9-a138-b46bfc6c5cb9'), 
          'transaction': {
             'type': 'PAYMENT', 
             'amount': 100, 
             'currency': 'EUR'
          }
       }
    }
    
    私たちがリクエストの呼び出しを「設定トランザクション」と「GETトランザクション」のカップルに呼ぶならば、我々は、要求からの参加者だけがcachemanagerであるという要求の全人生の間、出力からわかることができます.
    私たちがTululyAwesmeBankapiclientを呼んでいるときの唯一の瞬間は、要求を終了した後5秒です.
    また、同期は、プロセスの意図的にダムであり、ここでタイマーのために遅くなることに注意してください.実世界での同期処理は、(通常は)方法よりも複雑になることができ、実際には、データの一貫性がゲームチェンジャーであるとき、それは主要な関心事である必要があります.
    同期の後、あなたが見ることができるように、データベースは我々がキャッシュに持っているものと最新の状態です.このエントリのこの時点から、最新の状態であり、それは常に、他の書き込みアクションが起こるまでされます.

    最終語


    さて、これはアクティブなキャッシュ部分を閉じます.
    まず第一に、前の記事のフィードバックに感謝!ネーミングはとても明確ではなかったので、ここで少し更新しました.私は彼らが目を出血させないように同様に図を再訪問する機会を取った.少なくともそうではない.
    フィードバックを続けてください❤
    次回まで!
    1 . ユーザーが通常レイテンシーを読むよりもレイテンシの方法を書くのを許容することに言及する価値があります.残念ながら、私はどこからこのデータを得たか覚えていないので、私はこれの本当のメトリックを示すことができません.これを塩で一杯ください.
    2 . これらの問題は、一般的に「最終的な一貫性」と呼ばれているものに関係しています、そして、これが私が「最終的に」アクションライフサイクルの最後のステップで語を使用した理由です.トピックは自分自身の記事に値するに十分な大きさですが、あなたは本当に何が起こっているの把握を取得したい.