GoによるRedisの5永続化


前に書く
本明細書で実装Godisコードのバージョンは、v 0である.1
Redis持続化方式
RDB持続化
BGSAVEとSAVEコマンドはRDBファイルを生成し、データベース情報を格納する.サーバが起動すると、RDBファイルも元のデータとして近サービスメモリをロードします.ここでは、AOFの永続化がオンの場合、AOFファイルからのデータのロード、データベースの状態の復元が優先されるという優先順位の問題があります.
SAVEコマンドはサービスをブロックしますが、BGSAVEは独立したプロセスを派生し、ブロックしません.また、オプション構成によってRDBの永続化を自動的に実行するサイクルを設定することもできます.
Redisサービス側は、最初に述べたserver.dirtyフィールドのようないくつかのパラメータを記録することによって、前回のSAVE後にデータベースの変更が何回行われたかを記録します.定期的なバックグラウンド操作serverConが実行されると、データベースの更新ステータスがRDB永続化条件を満たしているかどうかを確認し、データベースステータスを保存します.注意:RDBのファイルはデータベースデータのストレージに対して、キー値ペアを格納する方法を採用しています.
AOF持続化
前述したRDBファイルは、データそのものを保存し、AOFファイルは、実行されたコマンドから変換されたプロトコルを格納する.RedisのAOF永続化をオンにして、いくつかのコマンドを操作した後、appendonly.aofファイルを参照してください.データのバックアップ操作なので、読み取りコマンドは記録する必要はなく、修正型の操作を記録するだけです.
AOF永続化が変更コマンドごとにファイルに計上されると、無効なコマンドが記録されます.次のようになります.
set alpha 123
set alpha 1
set alpha 321
set alpha 123

4つのコマンドはプロシージャであり、データベースレコードの最終値123がプロシージャの最終結果である.同一キーの操作に対する「無効コマンド」の記録を避けるため、Redisには、AOFファイルに追加するコマンドレコードとして現在のデータ状態を読み出すAOF書き換え機構がある.
GodisによるAOF持続化
GodisはAOF永続化のみを実現し,コマンドの書き換え集計操作は行わず,すべての修正操作がAOFファイルに記録される.これは、データ保存段階において、無効なI/O操作が多くなることを意味する.ロードフェーズでは、無効なコマンドが多数実行されます.
ディスクへのデータの永続化
Godisの符号化にはRedisのようなイベントループは用いられておらず,ここではserverに依存する.dirtyフィールドを識別します.dirty変化は持続化のタイミングである.
まず、コマンド呼び出しにAOF永続化判定を追加し、dirtyが変化すると永続化を行う.
func call(c *Client, s *Server) {
    dirty := s.Dirty
    c.Cmd.Proc(c, s)
    dirty = s.Dirty - dirty
    if dirty > 0 {//dirty        
        AppendToFile(s.AofFilename, c.QueryBuf)
    }

}

永続化操作を実行する関数AppendToFileも簡単で、ファイルに書き込みを追加し、すぐに閉じます.
func AppendToFile(fileName string, content string) error {
    //       ,    
    f, err := os.OpenFile(fileName, os.O_WRONLY|syscall.O_CREAT, 0644)
    if err != nil {
        log.Println("log file open failed" + err.Error())
    } else {
        n, _ := f.Seek(0, os.SEEK_END)
        _, err = f.WriteAt([]byte(content), n)
    }
    defer f.Close()
    return err
}

最後に、set命令のような修正型命令の実装において、serverを追加する.dirtyの更新.
func SetCommand(c *Client, s *Server) {
    ···
    s.Dirty++
    ···
}

効果をテストしてgodis-serverを再コンパイルします.go、set alpha 123を実行します.
ファイルにコマンドプロトコルが正常に書き込まれました.
サービス起動ロードデータ
永続化されたデータをファイルからメモリにロードする方法は、クライアント実行コマンドをシミュレートし、AOFファイルコマンドをサービス側に1本ずつ送信することです.
func LoadData() {
    c := godis.CreateClient()
    pros := core.ReadAof(godis.AofFilename)
    for _, v := range pros {
        c.QueryBuf = string(v)
        err := c.ProcessInputBuffer()
        if err != nil {
            log.Println("ProcessInputBuffer err", err)
        }
        godis.ProcessCommand(c)
    }
}

core.ReadAofはAOFファイルをメモリに読み込み、ストライプで格納します.その後のProcessCommandはset/getコマンド実装で紹介され、説明されません.
統合テスト
サービス側を閉じ、サービス側を再起動し、クライアントでget alphaを直接実行し、前のsetの値を取得できるかどうかを確認します.
AOFファイルをチェックして、コマンドgetに関するレコードを読みませんでした.
本編の問題
疑似クライアントが実行する時、持久化操作を実行しないで、Client構造に対して疑似端末フラグビットを増加して、持久化判断に用いる:
func LoadData() {
    c := godis.CreateClient()
    c.FakeFlag = true
    ···
}

小結
次回の予告はありません.この5つの短文の初志はGOを学ぶ際に書かれた小さなdemoを記録することであり、結果的に他の言語に費やされるまでの精力が予算を超えたため、その後もGodisの新しいfeatureを開発し続けることはなかった.
明日会社の仕事で忙しいプロジェクトの改造期间を迎えて、今日の端午の节句の小连休の最后の日に乗じて、V 0を理解しました.1バージョン.しかし、近い将来、次の連休には、前述したkeyの期限切れ、ネットワーク最適化、API開発、Streamなどの新しいfeatureと最適化が公開されるかもしれません.討論を歓迎する.