@@ -109,6 +109,7 @@ const (
109
109
readyPercentThreshold = 0.9
110
110
111
111
DowngradeEnabledPath = "/downgrade/enabled"
112
+ memorySnapshotCount = 100
112
113
)
113
114
114
115
var (
@@ -291,9 +292,10 @@ type EtcdServer struct {
291
292
clusterVersionChanged * notify.Notifier
292
293
293
294
* AccessController
294
- // forceSnapshot can force snapshot be triggered after apply, independent of the snapshotCount.
295
+ // forceDiskSnapshot can force snapshot be triggered after apply, independent of the snapshotCount.
295
296
// Should only be set within apply code path. Used to force snapshot after cluster version downgrade.
296
- forceSnapshot bool
297
+ // TODO: Replace with flush db in v3.7 assuming v3.6 bootstraps from db file.
298
+ forceDiskSnapshot bool
297
299
corruptionChecker CorruptionChecker
298
300
}
299
301
@@ -741,10 +743,11 @@ func (s *EtcdServer) ReportSnapshot(id uint64, status raft.SnapshotStatus) {
741
743
}
742
744
743
745
type etcdProgress struct {
744
- confState raftpb.ConfState
745
- snapi uint64
746
- appliedt uint64
747
- appliedi uint64
746
+ confState raftpb.ConfState
747
+ diskSnapshotIndex uint64
748
+ memorySnapshotIndex uint64
749
+ appliedt uint64
750
+ appliedi uint64
748
751
}
749
752
750
753
// raftReadyHandler contains a set of EtcdServer operations to be called by raftNode,
@@ -809,10 +812,11 @@ func (s *EtcdServer) run() {
809
812
s .r .start (rh )
810
813
811
814
ep := etcdProgress {
812
- confState : sn .Metadata .ConfState ,
813
- snapi : sn .Metadata .Index ,
814
- appliedt : sn .Metadata .Term ,
815
- appliedi : sn .Metadata .Index ,
815
+ confState : sn .Metadata .ConfState ,
816
+ diskSnapshotIndex : sn .Metadata .Index ,
817
+ memorySnapshotIndex : sn .Metadata .Index ,
818
+ appliedt : sn .Metadata .Term ,
819
+ appliedi : sn .Metadata .Index ,
816
820
}
817
821
818
822
defer func () {
@@ -979,7 +983,7 @@ func (s *EtcdServer) applyAll(ep *etcdProgress, apply *toApply) {
979
983
// storage, since the raft routine might be slower than toApply routine.
980
984
<- apply .notifyc
981
985
982
- s .triggerSnapshot (ep )
986
+ s .snapshotIfNeededAndCompactRaftLog (ep )
983
987
select {
984
988
// snapshot requested via send()
985
989
case m := <- s .r .msgSnapC :
@@ -998,15 +1002,15 @@ func (s *EtcdServer) applySnapshot(ep *etcdProgress, toApply *toApply) {
998
1002
lg := s .Logger ()
999
1003
lg .Info (
1000
1004
"applying snapshot" ,
1001
- zap .Uint64 ("current-snapshot-index" , ep .snapi ),
1005
+ zap .Uint64 ("current-snapshot-index" , ep .diskSnapshotIndex ),
1002
1006
zap .Uint64 ("current-applied-index" , ep .appliedi ),
1003
1007
zap .Uint64 ("incoming-leader-snapshot-index" , toApply .snapshot .Metadata .Index ),
1004
1008
zap .Uint64 ("incoming-leader-snapshot-term" , toApply .snapshot .Metadata .Term ),
1005
1009
)
1006
1010
defer func () {
1007
1011
lg .Info (
1008
1012
"applied snapshot" ,
1009
- zap .Uint64 ("current-snapshot-index" , ep .snapi ),
1013
+ zap .Uint64 ("current-snapshot-index" , ep .diskSnapshotIndex ),
1010
1014
zap .Uint64 ("current-applied-index" , ep .appliedi ),
1011
1015
zap .Uint64 ("incoming-leader-snapshot-index" , toApply .snapshot .Metadata .Index ),
1012
1016
zap .Uint64 ("incoming-leader-snapshot-term" , toApply .snapshot .Metadata .Term ),
@@ -1017,7 +1021,7 @@ func (s *EtcdServer) applySnapshot(ep *etcdProgress, toApply *toApply) {
1017
1021
if toApply .snapshot .Metadata .Index <= ep .appliedi {
1018
1022
lg .Panic (
1019
1023
"unexpected leader snapshot from outdated index" ,
1020
- zap .Uint64 ("current-snapshot-index" , ep .snapi ),
1024
+ zap .Uint64 ("current-snapshot-index" , ep .diskSnapshotIndex ),
1021
1025
zap .Uint64 ("current-applied-index" , ep .appliedi ),
1022
1026
zap .Uint64 ("incoming-leader-snapshot-index" , toApply .snapshot .Metadata .Index ),
1023
1027
zap .Uint64 ("incoming-leader-snapshot-term" , toApply .snapshot .Metadata .Term ),
@@ -1132,7 +1136,8 @@ func (s *EtcdServer) applySnapshot(ep *etcdProgress, toApply *toApply) {
1132
1136
1133
1137
ep .appliedt = toApply .snapshot .Metadata .Term
1134
1138
ep .appliedi = toApply .snapshot .Metadata .Index
1135
- ep .snapi = ep .appliedi
1139
+ ep .diskSnapshotIndex = ep .appliedi
1140
+ ep .memorySnapshotIndex = ep .appliedi
1136
1141
ep .confState = toApply .snapshot .Metadata .ConfState
1137
1142
1138
1143
// As backends and implementations like alarmsStore changed, we need
@@ -1188,31 +1193,26 @@ func (s *EtcdServer) applyEntries(ep *etcdProgress, apply *toApply) {
1188
1193
}
1189
1194
1190
1195
func (s * EtcdServer ) ForceSnapshot () {
1191
- s .forceSnapshot = true
1196
+ s .forceDiskSnapshot = true
1192
1197
}
1193
1198
1194
- func (s * EtcdServer ) triggerSnapshot (ep * etcdProgress ) {
1195
- if ! s .shouldSnapshot (ep ) {
1199
+ func (s * EtcdServer ) snapshotIfNeededAndCompactRaftLog (ep * etcdProgress ) {
1200
+ //TODO: Remove disk snapshot in v3.7
1201
+ shouldSnapshotToDisk := s .shouldSnapshotToDisk (ep )
1202
+ shouldSnapshotToMemory := s .shouldSnapshotToMemory (ep )
1203
+ if ! shouldSnapshotToDisk && ! shouldSnapshotToMemory {
1196
1204
return
1197
1205
}
1198
- lg := s .Logger ()
1199
- lg .Info (
1200
- "triggering snapshot" ,
1201
- zap .String ("local-member-id" , s .MemberID ().String ()),
1202
- zap .Uint64 ("local-member-applied-index" , ep .appliedi ),
1203
- zap .Uint64 ("local-member-snapshot-index" , ep .snapi ),
1204
- zap .Uint64 ("local-member-snapshot-count" , s .Cfg .SnapshotCount ),
1205
- zap .Bool ("snapshot-forced" , s .forceSnapshot ),
1206
- )
1207
- s .forceSnapshot = false
1208
-
1209
- s .snapshot (ep .appliedi , ep .confState )
1206
+ s .snapshot (ep , shouldSnapshotToDisk )
1210
1207
s .compactRaftLog (ep .appliedi )
1211
- ep .snapi = ep .appliedi
1212
1208
}
1213
1209
1214
- func (s * EtcdServer ) shouldSnapshot (ep * etcdProgress ) bool {
1215
- return (s .forceSnapshot && ep .appliedi != ep .snapi ) || (ep .appliedi - ep .snapi > s .Cfg .SnapshotCount )
1210
+ func (s * EtcdServer ) shouldSnapshotToDisk (ep * etcdProgress ) bool {
1211
+ return (s .forceDiskSnapshot && ep .appliedi != ep .diskSnapshotIndex ) || (ep .appliedi - ep .diskSnapshotIndex > s .Cfg .SnapshotCount )
1212
+ }
1213
+
1214
+ func (s * EtcdServer ) shouldSnapshotToMemory (ep * etcdProgress ) bool {
1215
+ return ep .appliedi > ep .memorySnapshotIndex + memorySnapshotCount
1216
1216
}
1217
1217
1218
1218
func (s * EtcdServer ) hasMultipleVotingMembers () bool {
@@ -2128,23 +2128,33 @@ func (s *EtcdServer) applyConfChange(cc raftpb.ConfChange, confState *raftpb.Con
2128
2128
}
2129
2129
2130
2130
// TODO: non-blocking snapshot
2131
- func (s * EtcdServer ) snapshot (snapi uint64 , confState raftpb.ConfState ) {
2132
- d := GetMembershipInfoInV2Format (s .Logger (), s .cluster )
2133
- // commit kv to write metadata (for example: consistent index) to disk.
2134
- //
2135
- // This guarantees that Backend's consistent_index is >= index of last snapshot.
2136
- //
2137
- // KV().commit() updates the consistent index in backend.
2138
- // All operations that update consistent index must be called sequentially
2139
- // from applyAll function.
2140
- // So KV().Commit() cannot run in parallel with toApply. It has to be called outside
2141
- // the go routine created below.
2142
- s .KV ().Commit ()
2143
-
2131
+ func (s * EtcdServer ) snapshot (ep * etcdProgress , toDisk bool ) {
2144
2132
lg := s .Logger ()
2133
+ d := GetMembershipInfoInV2Format (lg , s .cluster )
2134
+ if toDisk {
2135
+ s .Logger ().Info (
2136
+ "triggering snapshot" ,
2137
+ zap .String ("local-member-id" , s .MemberID ().String ()),
2138
+ zap .Uint64 ("local-member-applied-index" , ep .appliedi ),
2139
+ zap .Uint64 ("local-member-snapshot-index" , ep .diskSnapshotIndex ),
2140
+ zap .Uint64 ("local-member-snapshot-count" , s .Cfg .SnapshotCount ),
2141
+ zap .Bool ("snapshot-forced" , s .forceDiskSnapshot ),
2142
+ )
2143
+ s .forceDiskSnapshot = false
2144
+ // commit kv to write metadata (for example: consistent index) to disk.
2145
+ //
2146
+ // This guarantees that Backend's consistent_index is >= index of last snapshot.
2147
+ //
2148
+ // KV().commit() updates the consistent index in backend.
2149
+ // All operations that update consistent index must be called sequentially
2150
+ // from applyAll function.
2151
+ // So KV().Commit() cannot run in parallel with toApply. It has to be called outside
2152
+ // the go routine created below.
2153
+ s .KV ().Commit ()
2154
+ }
2145
2155
2146
2156
// For backward compatibility, generate v2 snapshot from v3 state.
2147
- snap , err := s .r .raftStorage .CreateSnapshot (snapi , & confState , d )
2157
+ snap , err := s .r .raftStorage .CreateSnapshot (ep . appliedi , & ep . confState , d )
2148
2158
if err != nil {
2149
2159
// the snapshot was done asynchronously with the progress of raft.
2150
2160
// raft might have already got a newer snapshot.
@@ -2153,21 +2163,25 @@ func (s *EtcdServer) snapshot(snapi uint64, confState raftpb.ConfState) {
2153
2163
}
2154
2164
lg .Panic ("failed to create snapshot" , zap .Error (err ))
2155
2165
}
2166
+ ep .memorySnapshotIndex = ep .appliedi
2156
2167
2157
2168
verifyConsistentIndexIsLatest (lg , snap , s .consistIndex .ConsistentIndex ())
2158
2169
2159
- // SaveSnap saves the snapshot to file and appends the corresponding WAL entry.
2160
- if err = s .r .storage .SaveSnap (snap ); err != nil {
2161
- lg .Panic ("failed to save snapshot" , zap .Error (err ))
2162
- }
2163
- if err = s .r .storage .Release (snap ); err != nil {
2164
- lg .Panic ("failed to release wal" , zap .Error (err ))
2165
- }
2170
+ if toDisk {
2171
+ // SaveSnap saves the snapshot to file and appends the corresponding WAL entry.
2172
+ if err = s .r .storage .SaveSnap (snap ); err != nil {
2173
+ lg .Panic ("failed to save snapshot" , zap .Error (err ))
2174
+ }
2175
+ ep .diskSnapshotIndex = ep .appliedi
2176
+ if err = s .r .storage .Release (snap ); err != nil {
2177
+ lg .Panic ("failed to release wal" , zap .Error (err ))
2178
+ }
2166
2179
2167
- lg .Info (
2168
- "saved snapshot" ,
2169
- zap .Uint64 ("snapshot-index" , snap .Metadata .Index ),
2170
- )
2180
+ lg .Info (
2181
+ "saved snapshot to disk" ,
2182
+ zap .Uint64 ("snapshot-index" , snap .Metadata .Index ),
2183
+ )
2184
+ }
2171
2185
}
2172
2186
2173
2187
func (s * EtcdServer ) compactRaftLog (snapi uint64 ) {
@@ -2188,7 +2202,6 @@ func (s *EtcdServer) compactRaftLog(snapi uint64) {
2188
2202
if snapi > s .Cfg .SnapshotCatchUpEntries {
2189
2203
compacti = snapi - s .Cfg .SnapshotCatchUpEntries
2190
2204
}
2191
-
2192
2205
err := s .r .raftStorage .Compact (compacti )
2193
2206
if err != nil {
2194
2207
// the compaction was done asynchronously with the progress of raft.
@@ -2198,7 +2211,7 @@ func (s *EtcdServer) compactRaftLog(snapi uint64) {
2198
2211
}
2199
2212
lg .Panic ("failed to compact" , zap .Error (err ))
2200
2213
}
2201
- lg .Info (
2214
+ lg .Debug (
2202
2215
"compacted Raft logs" ,
2203
2216
zap .Uint64 ("compact-index" , compacti ),
2204
2217
)
0 commit comments