@@ -19,9 +19,7 @@ import (
19
19
)
20
20
21
21
const (
22
- ingesterSubsystem = "ingester"
23
- maxConcurrentFlushSeries = 100
24
-
22
+ ingesterSubsystem = "ingester"
25
23
discardReasonLabel = "reason"
26
24
27
25
// Reasons to discard samples.
40
38
"The current number of users in memory." ,
41
39
nil , nil ,
42
40
)
41
+ flushQueueLengthDesc = prometheus .NewDesc (
42
+ "cortex_ingester_flush_queue_length" ,
43
+ "The total number of series pending in the flush queue." ,
44
+ nil , nil ,
45
+ )
43
46
44
47
// ErrOutOfOrderSample is returned if a sample has a timestamp before the latest
45
48
// timestamp in the series it is appended to.
@@ -64,7 +67,9 @@ type Ingester struct {
64
67
userStateLock sync.Mutex
65
68
userState map [string ]* userState
66
69
67
- flushQueue * priorityQueue
70
+ // One queue per flush thread. Fingerprint is used to
71
+ // pick a queue.
72
+ flushQueues []* priorityQueue
68
73
69
74
ingestedSamples prometheus.Counter
70
75
discardedSamples * prometheus.CounterVec
@@ -136,9 +141,8 @@ func New(cfg Config, chunkStore cortex.Store) (*Ingester, error) {
136
141
chunkStore : chunkStore ,
137
142
quit : make (chan struct {}),
138
143
139
- userState : map [string ]* userState {},
140
-
141
- flushQueue : newPriorityQueue (),
144
+ userState : map [string ]* userState {},
145
+ flushQueues : make ([]* priorityQueue , cfg .ConcurrentFlushes , cfg .ConcurrentFlushes ),
142
146
143
147
ingestedSamples : prometheus .NewCounter (prometheus.CounterOpts {
144
148
Name : "cortex_ingester_ingested_samples_total" ,
@@ -186,7 +190,8 @@ func New(cfg Config, chunkStore cortex.Store) (*Ingester, error) {
186
190
187
191
i .done .Add (cfg .ConcurrentFlushes )
188
192
for j := 0 ; j < cfg .ConcurrentFlushes ; j ++ {
189
- go i .flushLoop ()
193
+ i .flushQueues [j ] = newPriorityQueue ()
194
+ go i .flushLoop (j )
190
195
}
191
196
192
197
i .done .Add (1 )
@@ -439,7 +444,9 @@ func (i *Ingester) loop() {
439
444
440
445
// We close flush queue here to ensure the flushLoops pick
441
446
// up all the flushes triggered by the last run
442
- i .flushQueue .Close ()
447
+ for _ , flushQueue := range i .flushQueues {
448
+ flushQueue .Close ()
449
+ }
443
450
444
451
log .Infof ("Ingester.loop() exited gracefully" )
445
452
i .done .Done ()
@@ -503,7 +510,7 @@ func (i *Ingester) flushSeries(u *userState, fp model.Fingerprint, series *memor
503
510
504
511
// Decide what chunks to flush
505
512
firstTime := series .head ().FirstTime ()
506
- if immediate || model .Now ().Sub (series . head (). FirstTime () ) > i .cfg .MaxChunkAge {
513
+ if immediate || model .Now ().Sub (firstTime ) > i .cfg .MaxChunkAge {
507
514
series .headChunkClosed = true
508
515
series .head ().MaybePopulateLastTime ()
509
516
}
@@ -517,17 +524,18 @@ func (i *Ingester) flushSeries(u *userState, fp model.Fingerprint, series *memor
517
524
return
518
525
}
519
526
520
- i .flushQueue .Enqueue (& flushOp {firstTime , u .userID , fp , immediate })
527
+ flushQueueIndex := int (uint64 (fp ) % uint64 (i .cfg .ConcurrentFlushes ))
528
+ i .flushQueues [flushQueueIndex ].Enqueue (& flushOp {firstTime , u .userID , fp , immediate })
521
529
}
522
530
523
- func (i * Ingester ) flushLoop () {
531
+ func (i * Ingester ) flushLoop (j int ) {
524
532
defer func () {
525
533
log .Info ("Ingester.flushLoop() exited" )
526
534
i .done .Done ()
527
535
}()
528
536
529
537
for {
530
- o := i .flushQueue .Dequeue ()
538
+ o := i .flushQueues [ j ] .Dequeue ()
531
539
if o == nil {
532
540
return
533
541
}
@@ -551,10 +559,14 @@ func (i *Ingester) flushLoop() {
551
559
userState .fpLocker .Lock (op .fp )
552
560
chunks := series .chunkDescs
553
561
if ! series .headChunkClosed {
554
- chunks = chunks [1 : ]
562
+ chunks = chunks [: len ( chunks ) - 1 ]
555
563
}
556
564
userState .fpLocker .Unlock (op .fp )
557
565
566
+ if len (chunks ) == 0 {
567
+ continue
568
+ }
569
+
558
570
// flush the chunks without locking the series
559
571
if err := i .flushChunks (ctx , op .fp , series .metric , chunks ); err != nil {
560
572
log .Errorf ("Failed to flush chunks: %v" , err )
@@ -610,6 +622,7 @@ func (i *Ingester) updateRates() {
610
622
func (i * Ingester ) Describe (ch chan <- * prometheus.Desc ) {
611
623
ch <- memorySeriesDesc
612
624
ch <- memoryUsersDesc
625
+ ch <- flushQueueLengthDesc
613
626
ch <- i .ingestedSamples .Desc ()
614
627
i .discardedSamples .Describe (ch )
615
628
ch <- i .chunkUtilization .Desc ()
@@ -641,6 +654,16 @@ func (i *Ingester) Collect(ch chan<- prometheus.Metric) {
641
654
prometheus .GaugeValue ,
642
655
float64 (numUsers ),
643
656
)
657
+
658
+ flushQueueLength := 0
659
+ for _ , flushQueue := range i .flushQueues {
660
+ flushQueueLength += flushQueue .Length ()
661
+ }
662
+ ch <- prometheus .MustNewConstMetric (
663
+ flushQueueLengthDesc ,
664
+ prometheus .GaugeValue ,
665
+ float64 (flushQueueLength ),
666
+ )
644
667
ch <- i .ingestedSamples
645
668
i .discardedSamples .Collect (ch )
646
669
ch <- i .chunkUtilization
0 commit comments