From 56db047a2dd9b84e263f70aa974821322aae7bdf Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Mon, 26 Aug 2019 21:30:45 +0000 Subject: [PATCH 01/11] Set up ring for benchmark with valid config and descriptors Signed-off-by: Bryan Boreham --- pkg/ring/ring_test.go | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/pkg/ring/ring_test.go b/pkg/ring/ring_test.go index 26377d70560..dcb1e4b61b8 100644 --- a/pkg/ring/ring_test.go +++ b/pkg/ring/ring_test.go @@ -1,14 +1,10 @@ package ring import ( - "context" "fmt" "testing" - "github.com/stretchr/testify/require" - - "github.com/cortexproject/cortex/pkg/ring/kv" - "github.com/cortexproject/cortex/pkg/ring/kv/consul" + "github.com/cortexproject/cortex/pkg/util/flagext" ) const ( @@ -26,20 +22,12 @@ func BenchmarkRing(b *testing.B) { desc.AddIngester(fmt.Sprintf("%d", i), fmt.Sprintf("ingester%d", i), tokens, ACTIVE, false) } - consul := consul.NewInMemoryClient(GetCodec()) - err := consul.CAS(context.Background(), ConsulKey, func(interface{}) (interface{}, bool, error) { - return desc, false, nil - }) - require.NoError(b, err) - - r, err := New(Config{ - KVStore: kv.Config{ - Mock: consul, - }, - ReplicationFactor: 3, - }, "ingester") - if err != nil { - b.Fatal(err) + cfg := Config{} + flagext.DefaultValues(&cfg) + r := Ring{ + name: "ingester", + cfg: cfg, + ringDesc: desc, } // Generate a batch of N random keys, and look them up From 467f1ba16e59f4d012240c9323cce8256a59f642 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Mon, 26 Aug 2019 17:09:55 +0000 Subject: [PATCH 02/11] Move heavyweight random operations out of loop in BenchmarkRing() Signed-off-by: Bryan Boreham --- pkg/ring/ring_test.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/pkg/ring/ring_test.go b/pkg/ring/ring_test.go index dcb1e4b61b8..d0baf7efc0b 100644 --- a/pkg/ring/ring_test.go +++ b/pkg/ring/ring_test.go @@ -2,7 +2,9 @@ package ring import ( "fmt" + "math/rand" "testing" + "time" "github.com/cortexproject/cortex/pkg/util/flagext" ) @@ -10,6 +12,7 @@ import ( const ( numIngester = 100 numTokens = 512 + numKeys = 100 ) func BenchmarkRing(b *testing.B) { @@ -30,10 +33,18 @@ func BenchmarkRing(b *testing.B) { ringDesc: desc, } + rnd := rand.New(rand.NewSource(time.Now().UnixNano())) + keys := make([]uint32, numKeys) // Generate a batch of N random keys, and look them up b.ResetTimer() for i := 0; i < b.N; i++ { - keys := GenerateTokens(100, nil) + generateKeys(rnd, numKeys, keys) r.BatchGet(keys, Write) } } + +func generateKeys(r *rand.Rand, numTokens int, dest []uint32) { + for i := 0; i < numTokens; i++ { + dest[i] = r.Uint32() + } +} From 96a0edbbcab705274cf5ac5bef0bff7c24a2557b Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Wed, 28 Aug 2019 08:02:46 +0000 Subject: [PATCH 03/11] Modify ring benchmark to call higher-level fn DoBatch() Signed-off-by: Bryan Boreham --- pkg/ring/ring_test.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/pkg/ring/ring_test.go b/pkg/ring/ring_test.go index d0baf7efc0b..cf80ccb20c6 100644 --- a/pkg/ring/ring_test.go +++ b/pkg/ring/ring_test.go @@ -1,11 +1,14 @@ package ring import ( + "context" "fmt" "math/rand" "testing" "time" + "github.com/stretchr/testify/require" + "github.com/cortexproject/cortex/pkg/util/flagext" ) @@ -15,7 +18,7 @@ const ( numKeys = 100 ) -func BenchmarkRing(b *testing.B) { +func BenchmarkBatch(b *testing.B) { // Make a random ring with N ingesters, and M tokens per ingests desc := NewDesc() takenTokens := []uint32{} @@ -33,13 +36,20 @@ func BenchmarkRing(b *testing.B) { ringDesc: desc, } + ctx := context.Background() + callback := func(IngesterDesc, []int) error { + return nil + } + cleanup := func() { + } rnd := rand.New(rand.NewSource(time.Now().UnixNano())) keys := make([]uint32, numKeys) // Generate a batch of N random keys, and look them up b.ResetTimer() for i := 0; i < b.N; i++ { generateKeys(rnd, numKeys, keys) - r.BatchGet(keys, Write) + err := DoBatch(ctx, &r, keys, callback, cleanup) + require.NoError(b, err) } } From 6d1a283b20a3ea48fbe60b8ce48c148ce0274226 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Wed, 28 Aug 2019 08:37:28 +0000 Subject: [PATCH 04/11] Add two more sizes of batch benchmark Signed-off-by: Bryan Boreham --- pkg/ring/ring_test.go | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/pkg/ring/ring_test.go b/pkg/ring/ring_test.go index cf80ccb20c6..2178c41023e 100644 --- a/pkg/ring/ring_test.go +++ b/pkg/ring/ring_test.go @@ -13,12 +13,22 @@ import ( ) const ( - numIngester = 100 - numTokens = 512 - numKeys = 100 + numTokens = 512 ) -func BenchmarkBatch(b *testing.B) { +func BenchmarkBatch10x100(b *testing.B) { + benchmarkBatch(b, 10, 100) +} + +func BenchmarkBatch100x100(b *testing.B) { + benchmarkBatch(b, 100, 100) +} + +func BenchmarkBatch100x1000(b *testing.B) { + benchmarkBatch(b, 100, 1000) +} + +func benchmarkBatch(b *testing.B, numIngester, numKeys int) { // Make a random ring with N ingesters, and M tokens per ingests desc := NewDesc() takenTokens := []uint32{} From 46309e4386c1811a492bebe078058dd0639159ab Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Wed, 28 Aug 2019 08:10:19 +0000 Subject: [PATCH 05/11] Refactor Ring.DoBatch() to avoid memory allocation in BatchGet() Trade-off is we do more lock/unlock operations. Signed-off-by: Bryan Boreham --- pkg/distributor/distributor_test.go | 12 ------------ pkg/ring/batch.go | 12 ++++++------ pkg/ring/ring.go | 18 ------------------ 3 files changed, 6 insertions(+), 36 deletions(-) diff --git a/pkg/distributor/distributor_test.go b/pkg/distributor/distributor_test.go index 63314ed4d4c..4128c41105c 100644 --- a/pkg/distributor/distributor_test.go +++ b/pkg/distributor/distributor_test.go @@ -475,18 +475,6 @@ func (r mockRing) Get(key uint32, op ring.Operation) (ring.ReplicationSet, error return result, nil } -func (r mockRing) BatchGet(keys []uint32, op ring.Operation) ([]ring.ReplicationSet, error) { - result := []ring.ReplicationSet{} - for i := 0; i < len(keys); i++ { - rs, err := r.Get(keys[i], op) - if err != nil { - return nil, err - } - result = append(result, rs) - } - return result, nil -} - func (r mockRing) GetAll() (ring.ReplicationSet, error) { return ring.ReplicationSet{ Ingesters: r.ingesters, diff --git a/pkg/ring/batch.go b/pkg/ring/batch.go index 2decdea48ce..f8ddd6a9acc 100644 --- a/pkg/ring/batch.go +++ b/pkg/ring/batch.go @@ -37,14 +37,14 @@ type itemTracker struct { // // Not implemented as a method on Ring so we can test separately. func DoBatch(ctx context.Context, r ReadRing, keys []uint32, callback func(IngesterDesc, []int) error, cleanup func()) error { - replicationSets, err := r.BatchGet(keys, Write) - if err != nil { - return err - } - itemTrackers := make([]itemTracker, len(keys)) ingesters := map[string]ingester{} - for i, replicationSet := range replicationSets { + + for i, key := range keys { + replicationSet, err := r.Get(key, Write) + if err != nil { + return err + } itemTrackers[i].minSuccess = len(replicationSet.Ingesters) - replicationSet.MaxErrors itemTrackers[i].maxFailures = replicationSet.MaxErrors diff --git a/pkg/ring/ring.go b/pkg/ring/ring.go index a74b22ecfdc..7bf18d9fe97 100644 --- a/pkg/ring/ring.go +++ b/pkg/ring/ring.go @@ -32,7 +32,6 @@ type ReadRing interface { prometheus.Collector Get(key uint32, op Operation) (ReplicationSet, error) - BatchGet(keys []uint32, op Operation) ([]ReplicationSet, error) GetAll() (ReplicationSet, error) ReplicationFactor() int } @@ -187,23 +186,6 @@ func (r *Ring) Get(key uint32, op Operation) (ReplicationSet, error) { return r.getInternal(key, op) } -// BatchGet returns ReplicationFactor (or more) ingesters which form the replicas -// for the given keys. The order of the result matches the order of the input. -func (r *Ring) BatchGet(keys []uint32, op Operation) ([]ReplicationSet, error) { - r.mtx.RLock() - defer r.mtx.RUnlock() - - result := make([]ReplicationSet, len(keys), len(keys)) - for i, key := range keys { - rs, err := r.getInternal(key, op) - if err != nil { - return nil, err - } - result[i] = rs - } - return result, nil -} - func (r *Ring) getInternal(key uint32, op Operation) (ReplicationSet, error) { if r.ringDesc == nil || len(r.ringDesc.Tokens) == 0 { return ReplicationSet{}, ErrEmptyRing From 1df2f3197218649760d5036c22ae309a518a6714 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Tue, 27 Aug 2019 07:07:40 +0000 Subject: [PATCH 06/11] Reduce garbage in replicationStrategy() by modifying ingester list in-place Signed-off-by: Bryan Boreham --- pkg/ring/replication_strategy.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pkg/ring/replication_strategy.go b/pkg/ring/replication_strategy.go index a62b1683545..4f5808f5d9b 100644 --- a/pkg/ring/replication_strategy.go +++ b/pkg/ring/replication_strategy.go @@ -10,6 +10,7 @@ import ( // tolerate. // - Filters out dead ingesters so the one doesn't even try to write to them. // - Checks there is enough ingesters for an operation to succeed. +// The ingesters argument may be overwritten. func (r *Ring) replicationStrategy(ingesters []IngesterDesc, op Operation) ( liveIngesters []IngesterDesc, maxFailure int, err error, ) { @@ -26,14 +27,15 @@ func (r *Ring) replicationStrategy(ingesters []IngesterDesc, op Operation) ( // Skip those that have not heartbeated in a while. NB these are still // included in the calculation of minSuccess, so if too many failed ingesters // will cause the whole write to fail. - liveIngesters = make([]IngesterDesc, 0, len(ingesters)) - for _, ingester := range ingesters { - if r.IsHealthy(&ingester, op) { - liveIngesters = append(liveIngesters, ingester) + for i := 0; i < len(ingesters); { + if r.IsHealthy(&ingesters[i], op) { + i++ } else { + ingesters = append(ingesters[:i], ingesters[i+1:]...) maxFailure-- } } + liveIngesters = ingesters // This is just a shortcut - if there are not minSuccess available ingesters, // after filtering out dead ones, don't even bother trying. From 96a59dd80a9262437cef61a5769317ea478bb9bd Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Wed, 28 Aug 2019 08:13:00 +0000 Subject: [PATCH 07/11] Pre-size ingesters map to save garbage Signed-off-by: Bryan Boreham --- pkg/distributor/distributor_test.go | 4 ++++ pkg/ring/batch.go | 2 +- pkg/ring/replication_strategy.go | 8 ++++++++ pkg/ring/ring.go | 1 + 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/pkg/distributor/distributor_test.go b/pkg/distributor/distributor_test.go index 4128c41105c..e431b674cda 100644 --- a/pkg/distributor/distributor_test.go +++ b/pkg/distributor/distributor_test.go @@ -486,6 +486,10 @@ func (r mockRing) ReplicationFactor() int { return int(r.replicationFactor) } +func (r mockRing) IngesterCount() int { + return len(r.ingesters) +} + type mockIngester struct { sync.Mutex client.IngesterClient diff --git a/pkg/ring/batch.go b/pkg/ring/batch.go index f8ddd6a9acc..e4543d7b802 100644 --- a/pkg/ring/batch.go +++ b/pkg/ring/batch.go @@ -38,7 +38,7 @@ type itemTracker struct { // Not implemented as a method on Ring so we can test separately. func DoBatch(ctx context.Context, r ReadRing, keys []uint32, callback func(IngesterDesc, []int) error, cleanup func()) error { itemTrackers := make([]itemTracker, len(keys)) - ingesters := map[string]ingester{} + ingesters := make(map[string]ingester, r.IngesterCount()) for i, key := range keys { replicationSet, err := r.Get(key, Write) diff --git a/pkg/ring/replication_strategy.go b/pkg/ring/replication_strategy.go index 4f5808f5d9b..225fa627189 100644 --- a/pkg/ring/replication_strategy.go +++ b/pkg/ring/replication_strategy.go @@ -62,3 +62,11 @@ func (r *Ring) IsHealthy(ingester *IngesterDesc, op Operation) bool { func (r *Ring) ReplicationFactor() int { return r.cfg.ReplicationFactor } + +// IngesterCount is number of ingesters in the ring +func (r *Ring) IngesterCount() int { + r.mtx.Lock() + c := len(r.ringDesc.Ingesters) + r.mtx.Unlock() + return c +} diff --git a/pkg/ring/ring.go b/pkg/ring/ring.go index 7bf18d9fe97..a6599514485 100644 --- a/pkg/ring/ring.go +++ b/pkg/ring/ring.go @@ -34,6 +34,7 @@ type ReadRing interface { Get(key uint32, op Operation) (ReplicationSet, error) GetAll() (ReplicationSet, error) ReplicationFactor() int + IngesterCount() int } // Operation can be Read or Write From d6d1ebdb415c4cccae38512981f18e52e1b30e92 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Wed, 28 Aug 2019 08:28:02 +0000 Subject: [PATCH 08/11] Allocate memory for replication set in the caller to ring.Get() Signed-off-by: Bryan Boreham --- pkg/distributor/distributor_test.go | 3 ++- pkg/distributor/query.go | 2 +- pkg/ring/batch.go | 4 +++- pkg/ring/ring.go | 13 ++++++------- pkg/ruler/ruler.go | 2 +- 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/pkg/distributor/distributor_test.go b/pkg/distributor/distributor_test.go index e431b674cda..c79e6dcc8ce 100644 --- a/pkg/distributor/distributor_test.go +++ b/pkg/distributor/distributor_test.go @@ -464,9 +464,10 @@ type mockRing struct { replicationFactor uint32 } -func (r mockRing) Get(key uint32, op ring.Operation) (ring.ReplicationSet, error) { +func (r mockRing) Get(key uint32, op ring.Operation, buf []ring.IngesterDesc) (ring.ReplicationSet, error) { result := ring.ReplicationSet{ MaxErrors: 1, + Ingesters: buf[:0], } for i := uint32(0); i < r.replicationFactor; i++ { n := (key + i) % uint32(len(r.ingesters)) diff --git a/pkg/distributor/query.go b/pkg/distributor/query.go index 9c1e2b5422e..546aa4779de 100644 --- a/pkg/distributor/query.go +++ b/pkg/distributor/query.go @@ -68,7 +68,7 @@ func (d *Distributor) queryPrep(ctx context.Context, from, to model.Time, matche // Get ingesters by metricName if one exists, otherwise get all ingesters metricNameMatcher, _, ok := extract.MetricNameMatcherFromMatchers(matchers) if !d.cfg.ShardByAllLabels && ok && metricNameMatcher.Type == labels.MatchEqual { - replicationSet, err = d.ring.Get(shardByMetricName(userID, metricNameMatcher.Value), ring.Read) + replicationSet, err = d.ring.Get(shardByMetricName(userID, metricNameMatcher.Value), ring.Read, nil) } else { replicationSet, err = d.ring.GetAll() } diff --git a/pkg/ring/batch.go b/pkg/ring/batch.go index e4543d7b802..091c24d1280 100644 --- a/pkg/ring/batch.go +++ b/pkg/ring/batch.go @@ -40,8 +40,10 @@ func DoBatch(ctx context.Context, r ReadRing, keys []uint32, callback func(Inges itemTrackers := make([]itemTracker, len(keys)) ingesters := make(map[string]ingester, r.IngesterCount()) + const maxExpectedReplicationSet = 5 // typical replication factor 3 plus one for inactive plus one for luck + var descs [maxExpectedReplicationSet]IngesterDesc for i, key := range keys { - replicationSet, err := r.Get(key, Write) + replicationSet, err := r.Get(key, Write, descs[:0]) if err != nil { return err } diff --git a/pkg/ring/ring.go b/pkg/ring/ring.go index a6599514485..681f66203fd 100644 --- a/pkg/ring/ring.go +++ b/pkg/ring/ring.go @@ -31,7 +31,10 @@ const ( type ReadRing interface { prometheus.Collector - Get(key uint32, op Operation) (ReplicationSet, error) + // Get returns n (or more) ingesters which form the replicas for the given key. + // buf is a slice to be overwritten for the return value + // to avoid memory allocation; can be nil. + Get(key uint32, op Operation, buf []IngesterDesc) (ReplicationSet, error) GetAll() (ReplicationSet, error) ReplicationFactor() int IngesterCount() int @@ -181,20 +184,16 @@ func migrateRing(desc *Desc) []TokenDesc { } // Get returns n (or more) ingesters which form the replicas for the given key. -func (r *Ring) Get(key uint32, op Operation) (ReplicationSet, error) { +func (r *Ring) Get(key uint32, op Operation, buf []IngesterDesc) (ReplicationSet, error) { r.mtx.RLock() defer r.mtx.RUnlock() - return r.getInternal(key, op) -} - -func (r *Ring) getInternal(key uint32, op Operation) (ReplicationSet, error) { if r.ringDesc == nil || len(r.ringDesc.Tokens) == 0 { return ReplicationSet{}, ErrEmptyRing } var ( n = r.cfg.ReplicationFactor - ingesters = make([]IngesterDesc, 0, n) + ingesters = buf[:0] distinctHosts = map[string]struct{}{} start = r.search(key) iterations = 0 diff --git a/pkg/ruler/ruler.go b/pkg/ruler/ruler.go index 738250e5aa9..526a6545a57 100644 --- a/pkg/ruler/ruler.go +++ b/pkg/ruler/ruler.go @@ -330,7 +330,7 @@ func (r *Ruler) Evaluate(userID string, item *workItem) { } func (r *Ruler) ownsRule(hash uint32) bool { - rlrs, err := r.ring.Get(hash, ring.Read) + rlrs, err := r.ring.Get(hash, ring.Read, nil) // If an error occurs evaluate a rule as if it is owned // better to have extra datapoints for a rule than none at all // TODO: add a temporary cache of owned rule values or something to fall back on From f22916b1c282959bd66956aea7146cf066e451ce Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Wed, 28 Aug 2019 08:31:29 +0000 Subject: [PATCH 09/11] Bulk allocate slices for trackers, to save garbage from append() Signed-off-by: Bryan Boreham --- pkg/ring/batch.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pkg/ring/batch.go b/pkg/ring/batch.go index 091c24d1280..7b152322759 100644 --- a/pkg/ring/batch.go +++ b/pkg/ring/batch.go @@ -37,6 +37,7 @@ type itemTracker struct { // // Not implemented as a method on Ring so we can test separately. func DoBatch(ctx context.Context, r ReadRing, keys []uint32, callback func(IngesterDesc, []int) error, cleanup func()) error { + expectedTrackers := len(keys) * (r.ReplicationFactor() + 1) / r.IngesterCount() itemTrackers := make([]itemTracker, len(keys)) ingesters := make(map[string]ingester, r.IngesterCount()) @@ -51,7 +52,11 @@ func DoBatch(ctx context.Context, r ReadRing, keys []uint32, callback func(Inges itemTrackers[i].maxFailures = replicationSet.MaxErrors for _, desc := range replicationSet.Ingesters { - curr := ingesters[desc.Addr] + curr, found := ingesters[desc.Addr] + if !found { + curr.itemTrackers = make([]*itemTracker, 0, expectedTrackers) + curr.indexes = make([]int, 0, expectedTrackers) + } ingesters[desc.Addr] = ingester{ desc: desc, itemTrackers: append(curr.itemTrackers, &itemTrackers[i]), From 454b37a8ab8aab05488f3d01c007fa90f248a96c Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Thu, 5 Sep 2019 10:03:02 +0000 Subject: [PATCH 10/11] refactor: remove named return values in replicationStrategy() Signed-off-by: Bryan Boreham --- pkg/ring/replication_strategy.go | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/pkg/ring/replication_strategy.go b/pkg/ring/replication_strategy.go index 225fa627189..4b5383a7674 100644 --- a/pkg/ring/replication_strategy.go +++ b/pkg/ring/replication_strategy.go @@ -12,8 +12,7 @@ import ( // - Checks there is enough ingesters for an operation to succeed. // The ingesters argument may be overwritten. func (r *Ring) replicationStrategy(ingesters []IngesterDesc, op Operation) ( - liveIngesters []IngesterDesc, maxFailure int, err error, -) { + []IngesterDesc, int, error) { // We need a response from a quorum of ingesters, which is n/2 + 1. In the // case of a node joining/leaving, the actual replica set might be bigger // than the replication factor, so use the bigger or the two. @@ -22,7 +21,7 @@ func (r *Ring) replicationStrategy(ingesters []IngesterDesc, op Operation) ( replicationFactor = len(ingesters) } minSuccess := (replicationFactor / 2) + 1 - maxFailure = replicationFactor - minSuccess + maxFailure := replicationFactor - minSuccess // Skip those that have not heartbeated in a while. NB these are still // included in the calculation of minSuccess, so if too many failed ingesters @@ -35,17 +34,16 @@ func (r *Ring) replicationStrategy(ingesters []IngesterDesc, op Operation) ( maxFailure-- } } - liveIngesters = ingesters // This is just a shortcut - if there are not minSuccess available ingesters, // after filtering out dead ones, don't even bother trying. - if maxFailure < 0 || len(liveIngesters) < minSuccess { - err = fmt.Errorf("at least %d live ingesters required, could only find %d", - minSuccess, len(liveIngesters)) - return + if maxFailure < 0 || len(ingesters) < minSuccess { + err := fmt.Errorf("at least %d live ingesters required, could only find %d", + minSuccess, len(ingesters)) + return nil, 0, err } - return + return ingesters, maxFailure, nil } // IsHealthy checks whether an ingester appears to be alive and heartbeating From 14f9b1608fd3a8200bf55195502308a7af2da698 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Thu, 5 Sep 2019 13:21:44 +0000 Subject: [PATCH 11/11] Review feedback - cosmetic Signed-off-by: Bryan Boreham --- pkg/ring/batch.go | 2 +- pkg/ring/replication_strategy.go | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pkg/ring/batch.go b/pkg/ring/batch.go index 7b152322759..9ef1b9705d9 100644 --- a/pkg/ring/batch.go +++ b/pkg/ring/batch.go @@ -41,7 +41,7 @@ func DoBatch(ctx context.Context, r ReadRing, keys []uint32, callback func(Inges itemTrackers := make([]itemTracker, len(keys)) ingesters := make(map[string]ingester, r.IngesterCount()) - const maxExpectedReplicationSet = 5 // typical replication factor 3 plus one for inactive plus one for luck + const maxExpectedReplicationSet = 5 // Typical replication factor 3, plus one for inactive plus one for luck. var descs [maxExpectedReplicationSet]IngesterDesc for i, key := range keys { replicationSet, err := r.Get(key, Write, descs[:0]) diff --git a/pkg/ring/replication_strategy.go b/pkg/ring/replication_strategy.go index 4b5383a7674..5d0728659fe 100644 --- a/pkg/ring/replication_strategy.go +++ b/pkg/ring/replication_strategy.go @@ -11,8 +11,7 @@ import ( // - Filters out dead ingesters so the one doesn't even try to write to them. // - Checks there is enough ingesters for an operation to succeed. // The ingesters argument may be overwritten. -func (r *Ring) replicationStrategy(ingesters []IngesterDesc, op Operation) ( - []IngesterDesc, int, error) { +func (r *Ring) replicationStrategy(ingesters []IngesterDesc, op Operation) ([]IngesterDesc, int, error) { // We need a response from a quorum of ingesters, which is n/2 + 1. In the // case of a node joining/leaving, the actual replica set might be bigger // than the replication factor, so use the bigger or the two.