トランザクション、キャッシュ、ソート、メッセージ通知、スペースの節約

5167 ワード

この章では、redisの強力なソート機能と、手当たり次第に得られるトランザクション機能が最も注目されています.多くの場合、技術自体に問題はありませんが、抽象的で複雑すぎて、問題を解決するのは問題そのものに焦点を当てるのではなく、さまざまな周辺のツールです.Redisは強力な問題解決のツールとして、間違いなく非常に際立っている.

取引


私の固有の印象では、トランザクションはsqlデータベースに属してこそ独自の特権ですが、no-sqlデータベースが成熟するにつれて、この点は確かに変わりました.
redisのトランザクション機能は、簡単で直感的で、実際のビジネスで機能します.一般的な事務の使い方は2つあります.
  • Multiキーワードパッケージを使用してMultiキーワードを使用し、必要な文を同時にredis-server側に送信して処理することができる.文に構文エラーがある場合は、すべて終了します(redis 2.6.5以降).しかし、実行中にハッシュmapのkeyがセットされているなどの実行時エラーが発生した場合、ロールバック操作ができなくなることに特に注意する必要があります.しかし、一般的には、このようなエラーはテスト段階で発見され、回避できるはずです.

  • ここではredisを用いてマイクロブログの注目関係を保存する例を挙げる.ユーザごとに注目の集合があるfollowingSet,注目されるユーザにも注目の集合があるfollowedSet,注目関係が発生するたびにバインド関係は必ず双方向である.
    $ret = $redis->multi()
        ->SADD("{$userIdA}:followingSet",userIdB)
        ->SADD("{$userIdB}followedSet",userIdA)
        ->exec();
    
  • watchキーワードを使用する場合、独占的な変数を修正する過程で、変数の値が他人に変更されると、一致しない問題が発生しやすいため、中断されたくないことが多い.これは、招待コードを奪い取り、ギフト券を受け取るなど、一般的なビジネスシーンで必要です.だからこの時はwatchとmultiキーワードを結合するのが一般的です.

  • ギフト券を受け取る例を挙げます.
    //    100            key
    $redis->watch("giftcnt");
    //        ,     1,             
    $ret = $redis->multi()
        ->incrBy("giftcnt",-1)
        ->set("user:hasgift",1)
        ->exec();
    

    静的条件が発生した場合、ユーザAがトランザクション操作を実行している間にgiftcntが自分で取得したものではないことに気づいた場合、彼の操作は終了し、数量と表示状態の一致性を保証する必要がある.Watchのアイデアは、楽観的なロックであり、もう一度試して、静的な条件に遭遇しないことを望んでいます.一般的なトランザクションが正常に実行されると、watchのプロセスも完了します.

    有効期限


    期限切れという点では,redisがキャッシュとしての機能を最も体現している.これも私がredisを深く理解する前に唯一の概念を持っていた点です.これまでテンセントで自研していたCKVの中で最も多く使われていたため、確かにこのexpireの特性でもある.
    keyのexpire特性は、キャッシュを使用する一般的な方法を最も体現していると言えます.それは受動キャッシュで、データはmysqlに着地し、同時に期限切れのredisをキャッシュし、期限切れになったらclientは再び取得し、キャッシュに書き込まれる.データが変更されるとmysqlに書き込み、キャッシュに書き込みます.しかし、左耳ネズミのブログでの共有によると、この方法は一般的なアクセスが高くないシーンを満たすことができますが、高い同時性の場合は問題があります.クライアントAがcacheにアクセスすることを想定し、missを発見し、mysqlを読み取り、cacheに書き込む.しかし同時にクライアントBはmysqlに書き込まれ、この時間はAが古いデータをcacheに注入した後である.これで問題が発生した.この問題についてはもう深く研究しないが,見てもよい.http://coolshell.cn/articles/17416.htmlこの文章.
    redisでexpireコマンド、stringタイプに対するキー:EXPIRE key secondsPEXPIRE key milisecondsPERSIST/SET keyコマンドを使用してkeyを永続化することもできます.
    使用シーンの上から見ると、比較的一般的なシーンの一つは、アクセスの周波数制御を実現することです.唯一のユーザー+インタフェースに対して、彼のアクセス頻度を毎分100回などの一定回数に制限したいと考えています.では、次のような方法で実現できます.
    $listLength = LLEN rate.limiting:$IP
    if $listLength < 100
        LPUSH rate.limiting:$IP, noew()
    else 
        $time = LINDEX rate.limiting:$IP, -1 
        if now() - $time < 60
            print "        "
        else 
            MULTI
            LPUSH rate.limiting:$IP, now()
            LTRIM rate.limiting:$IP, 0, 99   
            EXEC    
    

    また、非常に一般的なシーンは、純粋なキャッシュとして使用されます.ここでは、2つの点に注意してください.
  • キャッシュ時間の設定expireコマンドは単独で実行する必要があり、原子操作ではなく、トランザクションで梱包することが望ましい
  • キャッシュサーバとして使用する場合は、redisが使用する最大メモリを制限し、一定のポリシーを用いてキー値の淘汰を行い、メモリ利用の最大化を図る必要がある
  • maxmemory
  • memory-policy


  • ツールバーの


    正直、この部分に触れる前にredisのソートは秩序集合を用いて配列するだけだと思います.しかし、redisには非常に強力なSORTなどのコマンドが内蔵されており、様々なソート、特にクエリーのソートを接続する機能があります.
    すべての文章idを含む秩序化された集合ソートを相対的に含めると、SORT articles:score DESC LIMIT 1 2文章idの大きさに応じて降順に並べるだけでなく、limitが返す数によってページをめくるのが便利になります.
    さらに複雑なソート要件では、BYキーを使用する必要があります.もし、articleの時間順にソートする必要があるとしたら、articleのhashmapの構造を使う必要があります:SORT articles:score BY article:*->time DESCそのうちの*号は集合中の要素に置き換えられ、articles:scoreに対してforeachを作って、ワイルドカード*に置き換えられたことが理解できます.この使い方は確かに耳目を一新させた.
    ハッシュ・テーブルの要素を使用するだけでなく、文字列タイプのキーもソートのkeyとして使用できます.
    もう1つのソートを使用してよく関心を持つ問題は、返される結果のフォーマットです.上記のSORTの使い方に従って、一連のソートされた文章idが返され、hgetのデータを手動で削除する必要があります.GETキーワードはこの問題を解決することができます.SORT articles:score BY article:*->time DESC GET article"*->title GET article"*->time GET ##号はid取得を示す.
    返された結果をリスト形式で格納したい場合は、:SORT articles:score BY article:*->time DESC GET article"*->title GET article"*->time GET # STORE sort.resultEXPIREコマンドに合わせることで、キャッシュを行うことができ、SORTのような高消費時間の操作がそれほど頻繁に実行されないことを保証します.
    性能的にはSORTの時間的複雑度はO(n+mlog(m))であり、同時にredisは長さnの容器を事前に確立して並べ替えられる要素を格納する.使用時には必ず注意してください.
  • ソート対象キーの要素数をできるだけ減らす(Nを減らす)
  • LIMITパラメータで必要なデータのみ取得(M削減)
  • STOREコマンドを活用して必要なキャッシュを行う
  • メッセージ通知


    キャッシュに加えて、もう一つのredisが最も広く伝えられているのは、簡単なキューを実現することです.業界の使用から見ると、rabbitMQ、rocketMQ、CMQ、KAFUKAなどの専門的なキュー実装案はますます成熟している.しかしredisはキューとしての簡潔で効率的であり、多くのキュー処理能力が要求されていないシーンでの選択肢である.
    一般的なシーンの1つは、ユーザーが登録した後、検証されたメールを送信することです.では1つのキューを定義するqueue:verifymailでは、1つのプロセスを開き、ブロックしてキューを待ち、どのように処理するかを決定するだけでよい:BRPOP queue:verifymail 0しかし、キューには、パスワードを取り戻したメールや登録に成功した通知メールなど、優先度が異なる場合もあります.優先順位キューのブロック待ちを行うことができます:BRPOP queue:findpassword queue:verifymail 0キュータスクの実装に加えて、redisは、異なるチャンネルのパブリケーションとサブスクリプションを実装し、バックグラウンドタスクのよりスムーズなフローを実現するために使用することもできます.また,発行者と購読者の定義については,使用するPUBLISH SUBSCRIBE.異なるチャンネルは業務の隔離を実現することができる.
    例えば、1つのチャンネルを定義してユーザーがコメントを送ると、ポイントサービス、レビューサービスなどがこのチャンネルを購読している可能性があります.それでは、対応する通知を受け取った後、レビューを行うか、ユーザーのポイントを増やすなど、対応する操作を行うことができます.