-
Notifications
You must be signed in to change notification settings - Fork 816
Store chunks in DynamoDB #418
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
b37a9e7
fdf2b80
8e94e94
07574a8
5c3713c
756462d
cb2a5d7
8880ee0
7f9611a
65fcac1
348e2a1
79ec2f0
a3a54ba
0ccd9c3
04b0828
bb3e011
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,8 +19,8 @@ type StorageClient interface { | |
QueryPages(ctx context.Context, query IndexQuery, callback func(result ReadBatch, lastPage bool) (shouldContinue bool)) error | ||
|
||
// For storing and retrieving chunks. | ||
PutChunk(ctx context.Context, key string, data []byte) error | ||
GetChunk(ctx context.Context, key string) ([]byte, error) | ||
PutChunks(ctx context.Context, chunks []Chunk, keys []string, data [][]byte) error | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What are the constraints on how There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The list must be the same length, and the ordering within them must be consistent. You could probably consider this a micro optimization, as the chunk can generate the key and the buffer. I'll see if I can factor it out. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Have managed to tidy this up. |
||
GetChunks(ctx context.Context, chunks []Chunk) ([]Chunk, error) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand this interface. You already have chunks ( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The chunks you're passing in are "empty", in that they just describe what to fetch. I could separate out the parsed chunk ID ( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. SGTM |
||
} | ||
|
||
// WriteBatch represents a batch of writes. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ import ( | |
"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbiface" | ||
"github.com/prometheus/client_golang/prometheus" | ||
"github.com/prometheus/common/log" | ||
"github.com/prometheus/common/model" | ||
"golang.org/x/net/context" | ||
|
||
"github.com/weaveworks/common/instrument" | ||
|
@@ -47,6 +48,7 @@ type TableManagerConfig struct { | |
DynamoDBPollInterval time.Duration | ||
|
||
PeriodicTableConfig | ||
PeriodicChunkTableConfig | ||
|
||
// duration a table will be created before it is needed. | ||
CreationGracePeriod time.Duration | ||
|
@@ -55,6 +57,11 @@ type TableManagerConfig struct { | |
ProvisionedReadThroughput int64 | ||
InactiveWriteThroughput int64 | ||
InactiveReadThroughput int64 | ||
|
||
ChunkTableProvisionedWriteThroughput int64 | ||
ChunkTableProvisionedReadThroughput int64 | ||
ChunkTableInactiveWriteThroughput int64 | ||
ChunkTableInactiveReadThroughput int64 | ||
} | ||
|
||
// RegisterFlags adds the flags required to config this to the given FlagSet | ||
|
@@ -66,8 +73,13 @@ func (cfg *TableManagerConfig) RegisterFlags(f *flag.FlagSet) { | |
f.Int64Var(&cfg.ProvisionedReadThroughput, "dynamodb.periodic-table.read-throughput", 300, "DynamoDB periodic tables read throughput") | ||
f.Int64Var(&cfg.InactiveWriteThroughput, "dynamodb.periodic-table.inactive-write-throughput", 1, "DynamoDB periodic tables write throughput for inactive tables.") | ||
f.Int64Var(&cfg.InactiveReadThroughput, "dynamodb.periodic-table.inactive-read-throughput", 300, "DynamoDB periodic tables read throughput for inactive tables") | ||
f.Int64Var(&cfg.ChunkTableProvisionedWriteThroughput, "dynamodb.chunk-table.write-throughput", 3000, "DynamoDB chunk tables write throughput") | ||
f.Int64Var(&cfg.ChunkTableProvisionedReadThroughput, "dynamodb.chunk-table.read-throughput", 300, "DynamoDB chunk tables read throughput") | ||
f.Int64Var(&cfg.ChunkTableInactiveWriteThroughput, "dynamodb.chunk-table.inactive-write-throughput", 1, "DynamoDB chunk tables write throughput for inactive tables.") | ||
f.Int64Var(&cfg.ChunkTableInactiveReadThroughput, "dynamodb.chunk-table.inactive-read-throughput", 300, "DynamoDB chunk tables read throughput for inactive tables") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't these flags be on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I followed the pattern we used for PeriodicTableConfig, where only the flags that need to be shared are actually put in the shared struct.
Eventually I want Cortex to self-tune its provisioned throughput, but for now the chunk table will need different levels as other tables. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fair enough. |
||
|
||
cfg.PeriodicTableConfig.RegisterFlags(f) | ||
cfg.PeriodicChunkTableConfig.RegisterFlags(f) | ||
} | ||
|
||
// PeriodicTableConfig for the use of periodic tables (ie, weekly tables). Can | ||
|
@@ -90,6 +102,20 @@ func (cfg *PeriodicTableConfig) RegisterFlags(f *flag.FlagSet) { | |
f.Var(&cfg.PeriodicTableStartAt, "dynamodb.periodic-table.start", "DynamoDB periodic tables start time.") | ||
} | ||
|
||
// PeriodicChunkTableConfig contains the various parameters for the chunk table. | ||
type PeriodicChunkTableConfig struct { | ||
ChunkTableFrom util.DayValue | ||
ChunkTablePrefix string | ||
ChunkTablePeriod time.Duration | ||
} | ||
|
||
// RegisterFlags adds the flags required to config this to the given FlagSet | ||
func (cfg *PeriodicChunkTableConfig) RegisterFlags(f *flag.FlagSet) { | ||
f.Var(&cfg.ChunkTableFrom, "dynamodb.chunk-table.from", "Date after which to write chunks to DynamoDB.") | ||
f.StringVar(&cfg.ChunkTablePrefix, "dynamodb.chunk-table.prefix", "cortex_chunks_", "DynamoDB table prefix for period chunk tables.") | ||
f.DurationVar(&cfg.ChunkTablePeriod, "dynamodb.chunk-table.period", 7*24*time.Hour, "DynamoDB chunk tables period.") | ||
} | ||
|
||
// TableManager creates and manages the provisioned throughput on DynamoDB tables | ||
type TableManager struct { | ||
client TableClient | ||
|
@@ -191,7 +217,6 @@ func (m *TableManager) calculateExpectedTables() []tableDescription { | |
gracePeriodSecs = int64(m.cfg.CreationGracePeriod / time.Second) | ||
maxChunkAgeSecs = int64(m.cfg.MaxChunkAge / time.Second) | ||
firstTable = m.cfg.PeriodicTableStartAt.Unix() / tablePeriodSecs | ||
lastTable = (mtime.Now().Unix() + gracePeriodSecs) / tablePeriodSecs | ||
now = mtime.Now().Unix() | ||
) | ||
|
||
|
@@ -211,23 +236,54 @@ func (m *TableManager) calculateExpectedTables() []tableDescription { | |
result = append(result, legacyTable) | ||
} | ||
|
||
result = append(result, periodicTables( | ||
m.cfg.TablePrefix, m.cfg.PeriodicTableStartAt.Time, m.cfg.TablePeriod, | ||
m.cfg.CreationGracePeriod, m.cfg.MaxChunkAge, | ||
m.cfg.ProvisionedReadThroughput, m.cfg.ProvisionedWriteThroughput, | ||
m.cfg.InactiveReadThroughput, m.cfg.InactiveWriteThroughput, | ||
)...) | ||
|
||
if m.cfg.ChunkTableFrom.IsSet() { | ||
result = append(result, periodicTables( | ||
m.cfg.ChunkTablePrefix, m.cfg.ChunkTableFrom.Time, m.cfg.ChunkTablePeriod, | ||
m.cfg.CreationGracePeriod, m.cfg.MaxChunkAge, | ||
m.cfg.ChunkTableProvisionedReadThroughput, m.cfg.ChunkTableProvisionedWriteThroughput, | ||
m.cfg.ChunkTableInactiveReadThroughput, m.cfg.ChunkTableInactiveWriteThroughput, | ||
)...) | ||
} | ||
|
||
sort.Sort(byName(result)) | ||
return result | ||
} | ||
|
||
func periodicTables( | ||
prefix string, start model.Time, period, beginGrace, endGrace time.Duration, | ||
activeRead, activeWrite, inactiveRead, inactiveWrite int64, | ||
) []tableDescription { | ||
var ( | ||
periodSecs = int64(period / time.Second) | ||
beginGraceSecs = int64(beginGrace / time.Second) | ||
endGraceSecs = int64(endGrace / time.Second) | ||
firstTable = start.Unix() / periodSecs | ||
lastTable = (mtime.Now().Unix() + beginGraceSecs) / periodSecs | ||
now = mtime.Now().Unix() | ||
result = []tableDescription{} | ||
) | ||
for i := firstTable; i <= lastTable; i++ { | ||
table := tableDescription{ | ||
// Name construction needs to be consistent with chunk_store.bigBuckets | ||
name: m.cfg.TablePrefix + strconv.Itoa(int(i)), | ||
provisionedRead: m.cfg.InactiveReadThroughput, | ||
provisionedWrite: m.cfg.InactiveWriteThroughput, | ||
name: prefix + strconv.Itoa(int(i)), | ||
provisionedRead: inactiveRead, | ||
provisionedWrite: inactiveWrite, | ||
} | ||
|
||
// if now is within table [start - grace, end + grace), then we need some write throughput | ||
if (i*tablePeriodSecs)-gracePeriodSecs <= now && now < (i*tablePeriodSecs)+tablePeriodSecs+gracePeriodSecs+maxChunkAgeSecs { | ||
table.provisionedRead = m.cfg.ProvisionedReadThroughput | ||
table.provisionedWrite = m.cfg.ProvisionedWriteThroughput | ||
if (i*periodSecs)-beginGraceSecs <= now && now < (i*periodSecs)+periodSecs+endGraceSecs { | ||
table.provisionedRead = activeRead | ||
table.provisionedWrite = activeWrite | ||
} | ||
result = append(result, table) | ||
} | ||
|
||
sort.Sort(byName(result)) | ||
return result | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to say why we need it when fetching chunks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Old code I should have removed, sorry!