Redis研究(十一)-データの持続化


Redisの強力なパフォーマンスは、すべてのデータがメモリに格納されているため、Redisが再起動してもデータが失われないように、メモリからハードディスクに何らかの形で同期する必要があるため、永続化されます.
       Redisは2つの方式の持続化をサポートし,1つはRDB方式,1つはAOF方式である.どちらかを単独で使用したり、両方を組み合わせて使用したりすることができます.
1.RDB方式
       RDB方式の永続化はスナップショット(snapshotting)によって行われ、一定の条件を満たすとRedisはメモリ内のすべてのデータを自動的にスナップショットしてハードディスクに格納する.スナップショットを行う条件は、時間と変更されたキーの数という2つのパラメータで構成されるプロファイルでユーザーがカスタマイズできます.指定した時間内に変更されたキーの数が指定した値より大きい場合にスナップショットが行われます.RDBはRedisのデフォルトで採用されている永続化方式であり、プロファイルにはすでに3つの条件がプリセットされている.
save  900 1
save  300 10
save  60 10000

saveパラメータは、スナップショット条件を指定します.複数の条件が存在し、条件間は「または」の関係です.上述したように、save 900 1は、15分(900秒)以内に少なくとも1つのキーが変更された場合にスナップショットを行うことを意味する.
自動スナップショットを無効にするには、すべてのsaveパラメータを削除するだけです.
Redisでは、デフォルトで現在のディレクトリのdump.rdbファイルにスナップショットファイルが格納されます.dirとdbfilenameの2つのパラメータを構成して、スナップショットファイルの格納パスとファイル名をそれぞれ指定できます.
Redisがスナップショットを実装するプロセスを整理することは、スナップショットファイルの特性を理解するのに役立ちます.スナップショットの手順は次のとおりです.(1)Redisはfork関数を使用して現在のプロセス(親プロセス)のコピー(サブプロセス)をコピーする.(2)親プロセスはクライアントからのコマンドを受信して処理し続け、サブプロセスはメモリ内のデータをハードディスク内の一時ファイルに書き込むことを開始する.(3)サブプロセスがすべてのデータを書き込んだ後、古いRDBファイルをその一時ファイルに置き換え、このスナップショット操作が完了する
できます.
     forkが実行されると、オペレーティングシステム(クラスUnixオペレーティングシステム)は、書き込み時レプリケーション(copy-on-write)ポリシーを使用します.すなわち、fork関数が発生した瞬間の親子プロセスは同じメモリデータを共有し、親プロセスが書き込みコマンドを実行するなど、データを変更する場合、サブプロセスのデータが影響を受けないように、システムがデータをコピーします.したがって、新しいRDBファイルはforkを実行する瞬間のメモリデータを格納します.
     上記の手順により、Redisはスナップショットの実行中にRDBファイルを変更することはなく、スナップショットが終了した後にのみ古いファイルを新しいものに置き換え、すなわちいつでもRDBファイルが完全であることがわかる.これにより、RDBファイルを定期的にバックアップすることで、Redisデータベースのバックアップを実現できます.RDBファイルは圧縮(rdbcompressionパラメータを構成して圧縮を無効にしてCPU占有を節約できる)されたバイナリ形式であるため、メモリ内のデータサイズよりも消費されるスペースが小さく、伝送に有利である.
     自動スナップショットに加えて、SAVEまたはBGSAVEコマンドを手動で送信してRedisにスナップショットを実行させることもできます.2つのコマンドの違いは、前者はメインプロセスによってスナップショット操作を行い、他の要求をブロックし、後者はforkサブプロセスによってスナップショット操作を行うことです.
    
     Redisが起動するとRDBスナップショットファイルが読み込まれ、ハードディスク(HDD)からメモリにデータがロードされます.この時間は、データ量の大きさや構造、サーバのパフォーマンスによって異なります.
通常、1千万個の文字列タイプキーを記録し、1 GBのサイズのスナップショットファイルをメモリにロードするには20~30秒かかります.
     RDB方式で永続化を実現し、Redisが異常終了すると、最後のスナップショット以降に変更されたすべてのデータが失われます.これは,開発者が具体的な応用場面に応じて,自動スナップショット条件を組み合わせて設定することで発生する可能性のあるデータ損失を許容できる範囲に制御する必要がある.損失に耐えられないほどデータが重要である場合、AOF方式による永続化が考えられる.
2.AOF方式
      デフォルトではRedisはAOF(append only)をオンにしていません  file)方式の持続化はappendonlyパラメータで開くことができる:
appendonly yes

     AOF永続化をオンにすると、Redisのデータを変更するコマンドが実行されるたびに、Redisはそのコマンドをハードディスク(HDD)のAOFファイルに書き込みます.AOFファイルの保存場所はRDBファイルの場所と同じで、dirパラメータで設定されています.デフォルトのファイル名はappendonly.aofで、appendfilenameパラメータで変更できます.
append file name  appendonly.aof

以下、AOF永続化の具体的な実装について説明し、AOF永続化をオンにした場合、以下の4つのコマンドが実行されたと仮定する.
SET foo 1
SET foo 2
SET foo 3
GET foo

Redisは、AOFファイルに最初の3つのコマンドを書き込みます.この場合、AOFファイルの内容は次のようになります.
*2
$6
SELECT
$1
0
*3
$3
set
$3
foo
$1
1
*3
$3
set
$3
foo
$1
2
*3
$3
set
$3
foo
$1
3

     AOFファイルは、RedisクライアントからRedisに送信された元の通信プロトコルの内容である純粋なテキストファイルであることがわかります(読みやすいように、
ここでは実際のコマンド部分を太字で表示する)ことから,Rediは確かに最初の3つのコマンドのみを記録していることがわかる.しかし、この場合、最初の2つのコマンドは実際には冗長であるという問題があります.この2つのコマンドの実行結果は3番目のコマンドで上書きされるからです.実行するコマンドが増えるにつれて、AOFファイルのサイズも大きくなり、メモリに実際のデータがあまりない可能性があります.自然に、RediはAOFファイルを自動的に最適化することを望んでいます.前例では、最初の2つの不要なレコードを削除し、3つ目だけを残します.実際にはRedisもそうしています.一定の条件に達するたびに、RedisはAOFファイルを自動的に書き換えます.この条件はプロファイルで設定できます.
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size  64mb

Autoaof-aof-rewrite-percentageパラメータの意味は、現在のAOFファイルサイズが前回の書き換え時のAOFファイルサイズの何パーセントを超えると書き換えが再開され、以前に書き換えたことがない場合は、起動時のAOFファイルサイズに基づいています.
Autoaof-aof-rewrite-min-sizeパラメータは、書き換えを許可する最小のAOFファイルサイズを制限し、通常、AOFファイルが小さい場合、冗長なコマンドが多くてもあまり関心を持っていません.
Redisが自動的に書き換えを実行するほか、BGREWRITEAOFコマンドを使用して手動でAOF書き換えを実行することもできます.
前例のAOFファイルの書き換え後の内容は次のとおりです.
*2
$6
SELECT
$1
0
*3
$3
SET
$3
foo
$1
3

     冗長なコマンドが削除されたことがわかります.書き換えのプロセスはメモリ内のデータのみに関係し,以前のAOFファイルとは無関係であり,これはRDBとよく似ているが,両者のファイルフォーマットは全く異なる.
     起動時にRedisはAOFファイルのコマンドを1つずつ実行してハードディスク(HDD)のデータをメモリにロードし、RDBよりもロード速度が遅くなります.
     AOFは、データベースの内容を変更する操作を実行するたびにAOFファイルにコマンドを記録するが、実際には、オペレーティングシステムのキャッシュメカニズムのため、データがハードディスクに実際に書き込まれるのではなく、システムのハードディスクキャッシュに入る.デフォルトでは、システムは30秒ごとに同期操作を実行し、ハードディスクキャッシュの内容をハードディスクに実際に書き込みます.この30秒の間にシステムが異常に終了すると、ハードディスクキャッシュのデータが失われます.一般的にAOF永続化を有効にするアプリケーションでは、このような損失は許容できません.これは、RedisがAOFファイルに書き込みた後、システムにキャッシュ内容をハードディスクに同期するようにアクティブに要求する必要があります.
    Redisでは、appendfsyncパラメータを使用して同期のタイミングを設定できます.
# appendfsync always
appendfsync everysec
# appendfsync no

      デフォルトでは、Redisはeverysecルールを使用します.つまり、同期操作は1秒に1回実行されます.Alwaysは、書き込みを実行するたびに同期を実行することを示します.これは最も安全で最も遅い方法です.Noは、同期操作をアクティブに行わないで、オペレーティングシステムに完全に任せる(すなわち、30秒ごとに行う)ことを示し、これは最も速いが最も安全ではない方法である.一般的にデフォルトeverysecを使用すれば十分で、パフォーマンスとセキュリティを両立させます.
     Redisは、AOFとRDBを同時にオンにすることを可能にし、データセキュリティ(AOF)を保証し、バックアップ(RDB)などの操作を容易にする.このときRedisを再起動すると、AOF方式の永続化で失われる可能性のあるデータがより少ないため、AOFファイルを使用してデータを復元します.