Skip to content
This repository has been archived by the owner on Sep 30, 2024. It is now read-only.

Independent multi-match #92

Merged
merged 6 commits into from
Mar 7, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ vagrant/db4-post-install.sh
vagrant/vagrant-ssh-key
vagrant/vagrant-ssh-key.pub
Godeps/_workspace
main
2 changes: 1 addition & 1 deletion RELEASE_VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.0.2
2.0.3
2 changes: 2 additions & 0 deletions go/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ type Configuration struct {
PseudoGTIDMonotonicHint string // subtring in Pseudo-GTID entry which indicates Pseudo-GTID entries are expected to be monotonically increasing
DetectPseudoGTIDQuery string // Optional query which is used to authoritatively decide whether pseudo gtid is enabled on instance
PseudoGTIDCoordinatesHistoryHeuristicMinutes int // Significantly reducing Pseudo-GTID lookup time, this indicates the most recent N minutes binlog position where search for Pseudo-GTID will heuristically begin (there is a fallback on fullscan if unsuccessful)
PseudoGTIDPreferIndependentMultiMatch bool // if 'false', a multi-replica Pseudo-GTID operation will attempt grouping replicas via Pseudo-GTID, and make less binlog computations. However it may cause servers in same bucket wait for one another, which could delay some servers from being repointed. There is a tradeoff between total operation time for all servers, and per-server time. When 'true', Pseudo-GTID matching will operate per server, independently. This will cause waste of same calculations, but no two servers will wait on one another.
BinlogEventsChunkSize int // Chunk size (X) for SHOW BINLOG|RELAYLOG EVENTS LIMIT ?,X statements. Smaller means less locking and mroe work to be done
BufferBinlogEvents bool // Should we used buffered read on SHOW BINLOG|RELAYLOG EVENTS -- releases the database lock sooner (recommended)
SkipBinlogEventsContaining []string // When scanning/comparing binlogs for Pseudo-GTID, skip entries containing given texts. These are NOT regular expressions (would consume too much CPU while scanning binlogs), just substrings to find.
Expand Down Expand Up @@ -323,6 +324,7 @@ func newConfiguration() *Configuration {
PseudoGTIDMonotonicHint: "",
DetectPseudoGTIDQuery: "",
PseudoGTIDCoordinatesHistoryHeuristicMinutes: 2,
PseudoGTIDPreferIndependentMultiMatch: false,
BinlogEventsChunkSize: 10000,
BufferBinlogEvents: true,
SkipBinlogEventsContaining: []string{},
Expand Down
54 changes: 54 additions & 0 deletions go/inst/instance_topology.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"regexp"
"sort"
"strings"
"sync"
"time"

"github.com/github/orchestrator/go/config"
Expand Down Expand Up @@ -1695,9 +1696,62 @@ func GetSortedReplicas(masterKey *InstanceKey, stopReplicationMethod StopReplica
return replicas, err
}

func MultiMatchBelowIndependently(replicas [](*Instance), belowKey *InstanceKey, postponedFunctionsContainer *PostponedFunctionsContainer) (matchedReplicas [](*Instance), belowInstance *Instance, err error, errs []error) {
replicas = RemoveInstance(replicas, belowKey)
if len(replicas) == 0 {
// Nothing to do
return matchedReplicas, belowInstance, err, errs
}

belowInstance, found, err := ReadInstance(belowKey)
if err != nil || !found {
return matchedReplicas, belowInstance, err, errs
}

log.Infof("Will match %+v replicas below %+v via Pseudo-GTID, independently", len(replicas), belowKey)

barrier := make(chan *InstanceKey)
replicaMutex := &sync.Mutex{}

for _, replica := range replicas {
replica := replica

// Parallelize repoints
go func() {
defer func() { barrier <- &replica.Key }()
ExecuteOnTopology(func() {
replica, _, replicaErr := MatchBelow(&replica.Key, belowKey, true)

replicaMutex.Lock()
defer replicaMutex.Unlock()

if replicaErr == nil {
matchedReplicas = append(matchedReplicas, replica)
} else {
errs = append(errs, replicaErr)
}
})
}()
}
for range replicas {
<-barrier
}
if len(errs) == len(replicas) {
// All returned with error
return matchedReplicas, belowInstance, fmt.Errorf("moveReplicasViaGTID: Error on all %+v operations", len(errs)), errs
}
AuditOperation("multi-match-below-independent", belowKey, fmt.Sprintf("matched %d/%d replicas below %+v via Pseudo-GTID", len(matchedReplicas), len(replicas), belowKey))

return matchedReplicas, belowInstance, err, errs

}

// MultiMatchBelow will efficiently match multiple replicas below a given instance.
// It is assumed that all given replicas are siblings
func MultiMatchBelow(replicas [](*Instance), belowKey *InstanceKey, replicasAlreadyStopped bool, postponedFunctionsContainer *PostponedFunctionsContainer) ([](*Instance), *Instance, error, []error) {
if config.Config.PseudoGTIDPreferIndependentMultiMatch {
return MultiMatchBelowIndependently(replicas, belowKey, postponedFunctionsContainer)
}
res := [](*Instance){}
errs := []error{}
replicaMutex := make(chan bool, 1)
Expand Down