mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-09-27 10:24:16 +00:00
master: check the reported volume digest and ask for the list on a mismatch
Compared after everything the heartbeat carried has been applied, so agreement means the master is current rather than that nothing changed. Servers reporting no digest are untouched, and a mismatch on a heartbeat that already carried the full list is reported rather than answered: there is nothing further to ask for, so asking again would loop. Nodes reporting one volume id twice are skipped for the same reason.
This commit is contained in:
@@ -275,9 +275,55 @@ func (ms *MasterServer) SendHeartbeat(stream master_pb.Seaweed_SendHeartbeatServ
|
||||
if len(message.NewVids) > 0 || len(message.DeletedVids) > 0 || len(message.NewEcVids) > 0 || len(message.DeletedEcVids) > 0 {
|
||||
ms.broadcastToClients(&master_pb.KeepConnectedResponse{VolumeLocation: message})
|
||||
}
|
||||
|
||||
// Checked after everything the heartbeat carried has been applied, so a
|
||||
// match means the master is current, not that nothing changed.
|
||||
if resend := ms.checkVolumeDigest(heartbeat, dn); resend {
|
||||
if err := stream.Send(&master_pb.HeartbeatResponse{ResendFullVolumeList: true}); err != nil {
|
||||
glog.Warningf("SendHeartbeat.Send resend request to %s:%d %v", dn.Ip, dn.Port, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// checkVolumeDigest compares the digest a volume server reported against the
|
||||
// master's own, and reports whether the master needs the full volume list to
|
||||
// recover. Servers that report no digest are left alone: they still send the
|
||||
// whole list every time.
|
||||
func (ms *MasterServer) checkVolumeDigest(heartbeat *master_pb.Heartbeat, dn *topology.DataNode) bool {
|
||||
if heartbeat.VolumeDigest == nil {
|
||||
return false
|
||||
}
|
||||
// One volume id mounted on two disks is reported twice but stored once, so
|
||||
// the digests cannot agree however often the list is resent. Asking would
|
||||
// loop forever.
|
||||
if dn.HasDuplicateVolumeIds() {
|
||||
stats.MasterReceivedHeartbeatCounter.WithLabelValues("volumeDigestNotComparable").Inc()
|
||||
return false
|
||||
}
|
||||
|
||||
reported := heartbeat.GetVolumeDigest()
|
||||
held := dn.VolumeDigest()
|
||||
if held == reported {
|
||||
stats.MasterReceivedHeartbeatCounter.WithLabelValues("volumeDigestMatch").Inc()
|
||||
return false
|
||||
}
|
||||
|
||||
stats.MasterReceivedHeartbeatCounter.WithLabelValues("volumeDigestMismatch").Inc()
|
||||
// A heartbeat that already carried the full list has nothing more to give;
|
||||
// asking again would just repeat. Say so instead, because at this point the
|
||||
// two ends genuinely disagree about what the server holds.
|
||||
if len(heartbeat.Volumes) > 0 || heartbeat.HasNoVolumes {
|
||||
glog.Warningf("volume server %s reported digest %d after a full volume list, master holds %d",
|
||||
dn.Url(), reported, held)
|
||||
return false
|
||||
}
|
||||
glog.V(0).Infof("volume server %s reported digest %d, master holds %d: requesting the full volume list",
|
||||
dn.Url(), reported, held)
|
||||
return true
|
||||
}
|
||||
|
||||
// KeepConnected keep a stream gRPC call to the master. Used by clients to know the master is up.
|
||||
// And clients gets the up-to-date list of volume locations
|
||||
func (ms *MasterServer) KeepConnected(stream master_pb.Seaweed_KeepConnectedServer) error {
|
||||
|
||||
Reference in New Issue
Block a user