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

Commit

Permalink
Merge pull request #92 from github/independent-multi-match
Browse files Browse the repository at this point in the history
Independent multi-match
  • Loading branch information
Shlomi Noach authored Mar 7, 2017
2 parents 68e1e28 + a74e1c0 commit e6a8067
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 1 deletion.
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

0 comments on commit e6a8067

Please sign in to comment.