程序锅

  • 首页
  • 分类
  • 标签
  • 归档
  • 关于

  • 搜索
基础知识 Etcd LeetCode 计算机体系结构 Kubernetes Containerd Docker 容器 云原生 Serverless 项目开发维护 ELF 深入理解程序 Tmux Vim Linux Kernel Linux numpy matplotlib 机器学习 MQTT 网络基础 Thrift RPC OS 操作系统 Clang 研途 数据结构和算法 Java 编程语言 Golang Python 个人网站搭建 Nginx 计算机通用技术 Git

Etcd WAL 日志&&Snapshot

发表于 2022-12-13 | 分类于 Etcd | 0 | 阅读次数 2777

前言

之前讲 Raft 协议的提过,用户提交写请求之后,etcd 会将用户请求打包成一个 proposal,交给 raft 模块。raft 模块会将 proposal 打包成一条日志条目,之后会将该日志条目会发送给其他 follower 节点,同时也会将日志条目持久话存储到 WAL 日志中。因此,本文主要介绍 WAL 日志。

WAL 文件

WAL 文件名格式

WAL 文件的文件名格式为:seq-index.wal。其中:

  • seq:序列号,从 0 开始递增。
  • index:该 WAL 文件存储的第一条日志的索引。因此给定一个日志索引后,很快就能知道该索引的日志落在哪个 WAL 文件之中的。

WAL 文件内容

WAL 文件由多个 WAL 日志记录顺序追加写入组成,如下图所示。每条记录由以下三部分组成,

  • type:表示记录类型,目前支持元数据、日志数据、状态数据、校验初始值、快照数据 5 种。
  • crc:data 中的 crc32 校验码。
  • data:数据部分,存对应类型的数据。
message Record {
	optional int64 type  = 1 [(gogoproto.nullable) = false];
	optional uint32 crc  = 2 [(gogoproto.nullable) = false];
	optional bytes data  = 3;
}

元数据

  • 对于 Etcd 来说,元数据中的数据中包含了节点 ID、集群 ID 信息。Etcd 是在创建 WAL 文件的时候,就写入了元数据。

    metadata := pbutil.MustMarshal(
      &pb.Metadata{
        NodeID:    uint64(member.ID),
        ClusterID: uint64(cl.ID()),
      },
    )
    if w, err = wal.Create(cfg.WALDir(), metadata); err != nil {
      plog.Fatalf("create wal error: %v", err)
    }
    
  • 一个服务中如果有多个 WAL 文件,且这些文件中有多份元数据,那么这些元数据都必须一致,否则报错。

日志数据

日志数据包含了 leader term、日志条目的索引、日志类型(普通的命令日志、集群配置变更日志)、proposal 内容等内容。

message Entry {
	optional uint64     Term  = 2 [(gogoproto.nullable) = false]; // must be 64-bit aligned for atomic operations
	optional uint64     Index = 3 [(gogoproto.nullable) = false]; // must be 64-bit aligned for atomic operations
	optional EntryType  Type  = 1 [(gogoproto.nullable) = false];
	optional bytes      Data  = 4;
}

状态数据

保存当前“硬状态(HardState)”的记录:当前任期号、当前给哪个节点 ID 投票、当前已提交(commited)的最大日志条目索引。一个 WAL 日志文件会有多条状态数据,但是以最后的记录为准。

message HardState {
	optional uint64 term   = 1 [(gogoproto.nullable) = false];
	optional uint64 vote   = 2 [(gogoproto.nullable) = false];
	optional uint64 commit = 3 [(gogoproto.nullable) = false];
}

校验初始值

为上一个 WAL 文件的最后一条日志数据的 CRC 信息。在创建、切割 WAL 日志文件时,作为第一条记录写入到新的 WAL 文件,用于校验数据文件的完整性、准确性,如下所示。

  • 每个 WAL 文件必须有校验初始值类型的数据,后续所有写入该 WAL 文件的记录,都使用该初始值来计算 CRC 校验值。
  • 校验初始值位于 WAL 文件中第一条日志数据的前面,这样才能确保后续基于它计算出来的该日志数据的 crc 校验码正确。
  • 第一个 WAL 文件,即序列号为 0 的 WAL 文件,其校验初始值为 0。
  • 之后的 WAL 文件,以上一个 WAL 文件的最后一条日志数据的 CRC 校验码来做为该文件的校验初始值。

快照数据

存储的是当前快照的索引和任期号,而快照的详细数据都存在快照数据文件中。

snapshot 文件

etcd-raft 使用日志在集群节点之间进行状态同步,通过日志复制保持集群状态一致。节点可以通过重新顺序执行日志将节点的状态复原,此时日志相当于状态变化的记录。

如果将节点当前的状态保存下来,也就是对当前的状态进行快照的话,那么该时间点之前的日志其实都可以删除,因为这些日志最终执行的效果已经被保存下来了,所以之前的日志记录都可以删除了。

快照的使用有以下优势:

  • 控制日志的增长。维护集群状态一致性的日志随时间变得越来越长。日志存储了集群中每个状态改变的历史记录,随着更多的状态变更(如键值对更新)被记录,日志会不断增长。长期增长的日志会消耗大量的存储空间。定期创建快照可以删除已经不再需要的老旧日志项。
  • 加快数据恢复和新节点加入的速度。数据恢复和新节点的加入可以在快照的基础之上,应用快照之后的日志部分,大大减少了时间和资源开销。
  • 数据迁移和备份:快照文件提供了一种方便的数据迁移和备份手段。它是一个独立的数据副本,可以轻松地移到其他存储介质或环境中。这也为灾备策略提供了重要支持。
  • 逻辑上的数据隔离和一致性保障:快照是系统在某一时刻的全局一致视图,不同于 boltdb,boltdb 可能只包含部分数据更新的状态。这提供了逻辑上的隔离,保证了快照中数据的完整性和一致性。

snapshot 文件名格式

snapshot 文件的文件名格式为:任期号-索引号.snap。任期号和索引号就是上述 WAL 中快照数据的内容,同时也是下面 snapshot 文件中 metadata 的内容。

snapshot 文件内容

文件中存储快照数据的格式为:校验值及其快照数据。

message snapshot {
	optional uint32 crc  = 1 [(gogoproto.nullable) = false];
	optional bytes data  = 2;
}

其中快照数据(data 字段)的具体格式由存储快照数据的使用方来解释。在 etcd 中,上述 data 字段中的实际数据格式为 Snapshot,为:

  • data:v2store json 序列化后的数据。其中 v2store 是 key-value 在内存中的存储结构,相当于序列化了 key-value 数据。
  • metadata:index 为已 applied 的日志的最大索引,term 为已 applied 的日志的 term,conf_state 集群节点信息。
message Snapshot {
	optional bytes            data     = 1;
	optional SnapshotMetadata metadata = 2 [(gogoproto.nullable) = false];
}

message SnapshotMetadata {
	optional ConfState conf_state = 1 [(gogoproto.nullable) = false];
	optional uint64    index      = 2 [(gogoproto.nullable) = false];
	optional uint64    term       = 3 [(gogoproto.nullable) = false];
}

snapshot 创建流程

  1. 触发快照: 快照创建可以通过几种方式触发:

    • 自动触发:etcd 定期(根据配置项)自动生成快照。
    • 手动触发:可以手动发送请求给 etcd 以创建快照。
    • 基于日志大小:当日志达到配置的阈值大小时,etcd 会自动触发一次快照。
  2. 创建快照文件:冻结 boltdb 并从其中读取内容来生成快照内容,同时创建快照文件,将快照内容写入。生成的快照内容包含了能够重建 boltdb 的所有信息,包括键值数据和必要的元数据,如快照时的索引和任期(term)等。

  3. 清理日志:对内存和 WAL 文件中的日志进行 compact。

Etcd 快照相关配置

主要两个配置参数:

  • snapshot-count:表示执行多少条日志之后才能进行快照。
  • snapshot-catchup-entries:一个新的或落后的成员在请求发送快照以加快追赶之前,可以接受多少条日志条目。

相关 Etcd 配置可参考:https://doczhcn.gitbook.io/etcd/index/index-1/configuration

相关链接

etcd-raft snapshot实现分析:https://zhuanlan.zhihu.com/p/29865583

Etcd Raft库的日志存储:https://www.codedump.info/post/20210628-etcd-wal/

卷死我
dawnguo 微信支付

微信支付

dawnguo 支付宝

支付宝

  • 本文作者: dawnguo
  • 本文链接: /archives/267
  • 版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0 许可协议。转载请注明出处!
# Kubernetes # Etcd
Etcd 中 Raft 实现的概述
Etcd MVCC 机制
  • 文章目录
  • 站点概览
dawnguo

dawnguo

215 日志
24 分类
37 标签
RSS
Creative Commons
© 2018 — 2025 程序锅
0%