Compat接口首先会更新当前server已压缩的版本号,并将耗时昂贵的压缩任务保存到FIFO队列中异步执行,压缩任务执行时,首先会压缩treeIndex模块中的keyIndex
索引,其次会遍历boltdb中的key,删除已废弃的key。
压缩的本质是回收历史版本,目标对象仅是历史版本,不包括一个key-value数据的最新版本。
精细化的控制本质:
- 1.使用etcd server的自带自动压缩机制(按时间周期性压缩和保留版本号的压缩)。
- 2.自定义压缩:定时任务中主动触发压缩。
周期性压缩
参数 | 参数值 | 解释 |
---|---|---|
auto-compaction-mode | periodic | 启用时间周期性压缩 |
auto-compaction-retention | 1h | 保留的时间周期 |
auto-compaction-mode | revision | 启动版本号压缩模式 |
auto-compaction-retention | 10000 | 保留的历史版本号 |
auto-compaction-retention 为0时,将关闭自动压缩策略。
周期性压缩模式的原理:
etcd server启动后,根据配置的模式periodic,会创建periodic Compactor,它会异步的获取、记录过去一段时间的版本号。periodic Compact组件
获取你设置的压缩间隔参数为1h,并将其划分成10个区间,也就是每个区间6分钟,每隔6分钟,它会通过etcd MVCC模块的地址获取当前的server版本号,
追加到rev数组中。如果只保留过去1小时的历史版本,periodic Compactor组件会通过当前时间减去上一次成功执行Compact操作的时间,如果大于一个
小时,它会取出rev数组的首元素,通过etcd server的compact接口,发起压缩操作。
版本号压缩
etcd server启动后会根据你的压缩模式,创建revision Compactor。revision Compactor会根据你设置的保留版本号数,每隔5分钟定时获取当前server
的最大版本号,减去想要保留的历史版本数,然后通过etcd server的compact接口发起如下的压缩操作即可。
压缩原理
etcd server 收到Compact请求后,它是如何执行的,核心原理是什么?
Compact请求经过Raft日志同步给多数节点后,etcd会从Raft日志取出Compact请求,应用此请求到状态机执行。
MVCC模块的Compact接口首先会检查Compact请求的版本号rev是否被压缩过,若是则返回ErrCompacted错误给client。其次会检查rev是否大于当前etcd
server的最大版本号,若是则返回ErrFutureRev给client。
Compact接口会通过boltdb的API在meta bucket中更新当前已调度的压缩版本号,然后将压缩任务追加到FIFO Scheduled中,异步调度执行。
为什么Compact接口需要持久化存储当前已调度的压缩版本号到boltdb中?
etcd通过持久化存储scheduledCompactedRev,节点crash重启后,会重新向FIFO Scheduled中添加压缩任务,已保证各个节点数据的一致。
异步的执行压缩任务会做那些工作?
- 压缩treeIndex中的各key历史索引,清理已删除key,并将有效的版本号保存到map数据结构中。
- 删除boltdb中废弃的历史版本数据。基本原理是根据版本号遍历boltdb已压缩区间范围内的key,遍历keyIndex返回的有效索引map数据结构判断key是否有效,
无效则通过boltdb API删除它。
为什么压缩后db大小不减少
boltdb删除大量的key,在事务提交后B+Tree经过分裂、平衡,会释放出若干branch/leaf page页面,然而boltdb并不会将其释放给磁盘,调整db大小操作是昂贵的,
会对性能有较大的损害。boltdb是通过freelist page记录这些空闲页的分布位置,当收到新的写请求时,优先从空闲页数组中申请若干连续页使用,实现高性能的读写。
boltdb大小不变的原因是存放key-value数据的branch和leaf页,它们释放后变成空闲页,并不会将空闲释放给磁盘。boltdb通过freelist page来管理一系列
空闲页,后续新增的写请求优先从freelist中申请空闲页使用,以提高性能。
网友评论