Fix selection of compactable blocks
This commit is contained in:
		
							parent
							
								
									fa04455cd7
								
							
						
					
					
						commit
						3951d8cc29
					
				| 
						 | 
					@ -113,7 +113,7 @@ func (b *writeBenchmark) run(cmd *cobra.Command, args []string) {
 | 
				
			||||||
	st, err := tsdb.Open(dir, nil, nil, &tsdb.Options{
 | 
						st, err := tsdb.Open(dir, nil, nil, &tsdb.Options{
 | 
				
			||||||
		WALFlushInterval:  200 * time.Millisecond,
 | 
							WALFlushInterval:  200 * time.Millisecond,
 | 
				
			||||||
		RetentionDuration: 15 * 24 * 60 * 60 * 1000, // 15 days in milliseconds
 | 
							RetentionDuration: 15 * 24 * 60 * 60 * 1000, // 15 days in milliseconds
 | 
				
			||||||
		BlockRanges:       tsdb.ExponentialBlockRanges(3*60*60*1000, 3, 5),
 | 
							BlockRanges:       tsdb.ExponentialBlockRanges(2*60*60*1000, 5, 3),
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		exitWithError(err)
 | 
							exitWithError(err)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										65
									
								
								compact.go
								
								
								
								
							
							
						
						
									
										65
									
								
								compact.go
								
								
								
								
							| 
						 | 
					@ -180,57 +180,50 @@ func (c *compactor) Plan() ([][]string, error) {
 | 
				
			||||||
	return nil, nil
 | 
						return nil, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// selectDirs returns the dir metas that should be compacted into a single new block.
 | 
				
			||||||
 | 
					// If only a single block range is configured, the result is always nil.
 | 
				
			||||||
func (c *compactor) selectDirs(ds []dirMeta) []dirMeta {
 | 
					func (c *compactor) selectDirs(ds []dirMeta) []dirMeta {
 | 
				
			||||||
	// The way to skip compaction is to not have blockRanges.
 | 
						if len(c.opts.blockRanges) < 2 || len(ds) < 1 {
 | 
				
			||||||
	if len(c.opts.blockRanges) == 1 {
 | 
					 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return selectRecurse(ds, c.opts.blockRanges)
 | 
						highTime := ds[len(ds)-1].meta.MinTime
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
func selectRecurse(dms []dirMeta, intervals []int64) []dirMeta {
 | 
						for _, iv := range c.opts.blockRanges[1:] {
 | 
				
			||||||
	if len(intervals) == 0 {
 | 
							parts := splitByRange(ds, iv)
 | 
				
			||||||
		return dms
 | 
							if len(parts) == 0 {
 | 
				
			||||||
	}
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Get the blocks by the max interval
 | 
							for _, p := range parts {
 | 
				
			||||||
	blocks := splitByRange(dms, intervals[len(intervals)-1])
 | 
								mint := p[0].meta.MinTime
 | 
				
			||||||
	dirs := []dirMeta{}
 | 
								maxt := p[len(p)-1].meta.MaxTime
 | 
				
			||||||
	for i := len(blocks) - 1; i >= 0; i-- {
 | 
								// Pick the range of blocks if it spans the full range (potentially with gaps)
 | 
				
			||||||
		// We need to choose the oldest blocks to compact. If there are a couple of blocks in
 | 
								// or is before the most recent block.
 | 
				
			||||||
		// the largest interval, we should compact those first.
 | 
								// This ensures we don't compact blocks prematurely when another one of the same
 | 
				
			||||||
		if len(blocks[i]) > 1 {
 | 
								// size still fits in the range.
 | 
				
			||||||
			dirs = blocks[i]
 | 
								if (maxt-mint == iv || maxt <= highTime) && len(p) > 1 {
 | 
				
			||||||
			break
 | 
									return p
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// If there are too many blocks, see if a smaller interval will catch them.
 | 
						return nil
 | 
				
			||||||
	// i.e, if we have 0-20, 60-80, 80-100; all fall under 0-240, but we'd rather compact 60-100
 | 
					 | 
				
			||||||
	// than all at once.
 | 
					 | 
				
			||||||
	// Again if have 0-1d, 1d-2d, 3-6d we compact 0-1d, 1d-2d to compact it into the 0-3d block instead of compacting all three
 | 
					 | 
				
			||||||
	// This is to honor the boundaries as much as possible.
 | 
					 | 
				
			||||||
	if len(dirs) > 2 {
 | 
					 | 
				
			||||||
		smallerDirs := selectRecurse(dirs, intervals[:len(intervals)-1])
 | 
					 | 
				
			||||||
		if len(smallerDirs) > 1 {
 | 
					 | 
				
			||||||
			return smallerDirs
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return dirs
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// splitByRange splits the directories by the time range.
 | 
					// splitByRange splits the directories by the time range. The range sequence starts at 0.
 | 
				
			||||||
// for example if we have blocks 0-10, 10-20, 50-60, 90-100 and want to split them into 30 interval ranges
 | 
					//
 | 
				
			||||||
// splitByRange returns [0-10, 10-20], [50-60], [90-100].
 | 
					// For example, if we have blocks [0-10, 10-20, 50-60, 90-100] and the split range tr is 30
 | 
				
			||||||
 | 
					// it returns [0-10, 10-20], [50-60], [90-100].
 | 
				
			||||||
func splitByRange(ds []dirMeta, tr int64) [][]dirMeta {
 | 
					func splitByRange(ds []dirMeta, tr int64) [][]dirMeta {
 | 
				
			||||||
	var splitDirs [][]dirMeta
 | 
						var splitDirs [][]dirMeta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for i := 0; i < len(ds); {
 | 
						for i := 0; i < len(ds); {
 | 
				
			||||||
		var group []dirMeta
 | 
							var (
 | 
				
			||||||
		var t0 int64
 | 
								group []dirMeta
 | 
				
			||||||
		m := ds[i].meta
 | 
								t0    int64
 | 
				
			||||||
 | 
								m     = ds[i].meta
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
		// Compute start of aligned time range of size tr closest to the current block's start.
 | 
							// Compute start of aligned time range of size tr closest to the current block's start.
 | 
				
			||||||
		if m.MinTime >= 0 {
 | 
							if m.MinTime >= 0 {
 | 
				
			||||||
			t0 = tr * (m.MinTime / tr)
 | 
								t0 = tr * (m.MinTime / tr)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,6 +49,22 @@ func TestCompactionSelect(t *testing.T) {
 | 
				
			||||||
			planned: nil,
 | 
								planned: nil,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								// We should wait for a third block of size 20 to appear before compacting
 | 
				
			||||||
 | 
								// the existing ones.
 | 
				
			||||||
 | 
								blocks: []dirMetaSimple{
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										dir: "1",
 | 
				
			||||||
 | 
										tr:  []int64{0, 20},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										dir: "2",
 | 
				
			||||||
 | 
										tr:  []int64{20, 40},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								planned: nil,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								// Block to fill the entire parent range appeared – should be compacted.
 | 
				
			||||||
			blocks: []dirMetaSimple{
 | 
								blocks: []dirMetaSimple{
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					dir: "1",
 | 
										dir: "1",
 | 
				
			||||||
| 
						 | 
					@ -65,6 +81,25 @@ func TestCompactionSelect(t *testing.T) {
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			planned: [][]string{{"1", "2", "3"}},
 | 
								planned: [][]string{{"1", "2", "3"}},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								// Block for the next parent range appeared. Nothing will happen in the first one
 | 
				
			||||||
 | 
								// anymore and we should compact it.
 | 
				
			||||||
 | 
								blocks: []dirMetaSimple{
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										dir: "1",
 | 
				
			||||||
 | 
										tr:  []int64{0, 20},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										dir: "2",
 | 
				
			||||||
 | 
										tr:  []int64{20, 40},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										dir: "3",
 | 
				
			||||||
 | 
										tr:  []int64{60, 80},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								planned: [][]string{{"1", "2"}},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			blocks: []dirMetaSimple{
 | 
								blocks: []dirMetaSimple{
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
| 
						 | 
					@ -92,18 +127,10 @@ func TestCompactionSelect(t *testing.T) {
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			blocks: []dirMetaSimple{
 | 
								blocks: []dirMetaSimple{
 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					dir: "1",
 | 
					 | 
				
			||||||
					tr:  []int64{0, 20},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					dir: "2",
 | 
										dir: "2",
 | 
				
			||||||
					tr:  []int64{20, 40},
 | 
										tr:  []int64{20, 40},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					dir: "3",
 | 
					 | 
				
			||||||
					tr:  []int64{40, 60},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					dir: "4",
 | 
										dir: "4",
 | 
				
			||||||
					tr:  []int64{60, 120},
 | 
										tr:  []int64{60, 120},
 | 
				
			||||||
| 
						 | 
					@ -121,24 +148,28 @@ func TestCompactionSelect(t *testing.T) {
 | 
				
			||||||
					tr:  []int64{1200, 1440},
 | 
										tr:  []int64{1200, 1440},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			planned: [][]string{{"6", "7"}},
 | 
								planned: [][]string{{"2", "4", "5"}},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			blocks: []dirMetaSimple{
 | 
								blocks: []dirMetaSimple{
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					dir: "1",
 | 
										dir: "1",
 | 
				
			||||||
					tr:  []int64{0, 20},
 | 
										tr:  []int64{0, 60},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					dir: "2",
 | 
										dir: "4",
 | 
				
			||||||
					tr:  []int64{60, 80},
 | 
										tr:  []int64{60, 80},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					dir: "3",
 | 
										dir: "5",
 | 
				
			||||||
					tr:  []int64{80, 100},
 | 
										tr:  []int64{80, 100},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										dir: "6",
 | 
				
			||||||
 | 
										tr:  []int64{100, 120},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			planned: [][]string{{"2", "3"}},
 | 
								planned: [][]string{{"4", "5", "6"}},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue