Skip to content

Commit bb346c0

Browse files
pracuccibwplotka
andcommitted
Add memcached support to index cache (#1881)
* Moved index cache key struct outside of the file containing the in-memory cache backend because generic Signed-off-by: Marco Pracucci <marco@pracucci.com> * Added cacheKey.string() to make it memcached friendly Signed-off-by: Marco Pracucci <marco@pracucci.com> * Added MemcachedIndexCache support Signed-off-by: Marco Pracucci <marco@pracucci.com> * Export Prometheus metrics from MemcachedIndexCache Signed-off-by: Marco Pracucci <marco@pracucci.com> * Fixed linter issues Signed-off-by: Marco Pracucci <marco@pracucci.com> * Simplified workers wait group in memcachedClient Signed-off-by: Marco Pracucci <marco@pracucci.com> * Fixed memcached client GetMulti() results batches channel buffer Signed-off-by: Marco Pracucci <marco@pracucci.com> * Wait for addrs resolution gorouting to complete on memcachedClient.Stop() Signed-off-by: Marco Pracucci <marco@pracucci.com> * Return struct from NewMemcachedClient() Signed-off-by: Marco Pracucci <marco@pracucci.com> * Update pkg/cacheutil/memcached_client.go Co-Authored-By: Bartlomiej Plotka <bwplotka@gmail.com> Signed-off-by: Marco Pracucci <marco@pracucci.com> * Simplified memcachedClient tests Signed-off-by: Marco Pracucci <marco@pracucci.com> * Cleaned up code based on feedback Signed-off-by: Marco Pracucci <marco@pracucci.com> * Removed error from GetMulti() return and introduced metrics and tracing in MemcachedClient Signed-off-by: Marco Pracucci <marco@pracucci.com> * Fixed compilation errors in store E2E tests Signed-off-by: Marco Pracucci <marco@pracucci.com> * Added leaktest check to all tests Signed-off-by: Marco Pracucci <marco@pracucci.com> * Introduced --index.cache-config support Signed-off-by: Marco Pracucci <marco@pracucci.com> * Fixed compilation errors in store E2E tests Signed-off-by: Marco Pracucci <marco@pracucci.com> * Updated store flags doc Signed-off-by: Marco Pracucci <marco@pracucci.com> * Updated index cache doc Signed-off-by: Marco Pracucci <marco@pracucci.com> * Updated changelog Signed-off-by: Marco Pracucci <marco@pracucci.com> * Increased default memcached client timeout from 100ms to 500ms Signed-off-by: Marco Pracucci <marco@pracucci.com> * Disabled memcached client max batch size by default Signed-off-by: Marco Pracucci <marco@pracucci.com> * Fixed index cache key max length Signed-off-by: Marco Pracucci <marco@pracucci.com> * Removed TODO from memcached client since looks the general consensus is to have a global limit on the max concurrent batches Signed-off-by: Marco Pracucci <marco@pracucci.com> * Allow to configure in-memory index cache using byte units Signed-off-by: Marco Pracucci <marco@pracucci.com> * Refactored index cache config file doc Signed-off-by: Marco Pracucci <marco@pracucci.com> * Fixed nits in comments Signed-off-by: Marco Pracucci <marco@pracucci.com> * Replaced hardcoded 16 with ULID calculated length based on review comment Signed-off-by: Marco Pracucci <marco@pracucci.com> * Do not expose jumpHash func Signed-off-by: Marco Pracucci <marco@pracucci.com> * Updated changelog Signed-off-by: Marco Pracucci <marco@pracucci.com> * Switched MemcachedClient GetMulti() concurrency limit to a gate Signed-off-by: Marco Pracucci <marco@pracucci.com> * Fixed flaky tests Signed-off-by: Marco Pracucci <marco@pracucci.com> * Fixed typos in comments Signed-off-by: Marco Pracucci <marco@pracucci.com> * Renamed memcached config option addrs to addresses Signed-off-by: Marco Pracucci <marco@pracucci.com> Co-authored-by: Bartlomiej Plotka <bwplotka@gmail.com>
1 parent a37ac09 commit bb346c0

23 files changed

+2104
-133
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ We use *breaking* word for marking changes that are not backward compatible (rel
2222
- [#1854](https://github.com/thanos-io/thanos/pull/1854) Update Rule UI to support alerts count displaying and filtering.
2323
- [#1838](https://github.com/thanos-io/thanos/pull/1838) Ruler: Add TLS and authentication support for Alertmanager with the `--alertmanagers.config` and `--alertmanagers.config-file` CLI flags. See [documentation](docs/components/rule.md/#configuration) for further information.
2424
- [#1838](https://github.com/thanos-io/thanos/pull/1838) Ruler: Add a new `--alertmanagers.sd-dns-interval` CLI option to specify the interval between DNS resolutions of Alertmanager hosts.
25+
- [#1881](https://github.com/thanos-io/thanos/pull/1881) Store Gateway: memcached support for index cache. See [documentation](docs/components/store.md/#index-cache) for further information.
2526

2627
## [v0.9.0](https://github.com/thanos-io/thanos/releases/tag/v0.9.0) - 2019.12.03
2728

cmd/thanos/store.go

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,13 @@ func registerStore(m map[string]setupFunc, app *kingpin.Application) {
3636
dataDir := cmd.Flag("data-dir", "Data directory in which to cache remote blocks.").
3737
Default("./data").String()
3838

39-
indexCacheSize := cmd.Flag("index-cache-size", "Maximum size of items held in the index cache.").
39+
indexCacheSize := cmd.Flag("index-cache-size", "Maximum size of items held in the in-memory index cache. Ignored if --index-cache.config or --index-cache.config-file option is specified.").
4040
Default("250MB").Bytes()
4141

42+
indexCacheConfig := extflag.RegisterPathOrContent(cmd, "index-cache.config",
43+
"YAML file that contains index cache configuration. See format details: https://thanos.io/components/store.md/#index-cache",
44+
false)
45+
4246
chunkPoolSize := cmd.Flag("chunk-pool-size", "Maximum size of concurrently allocatable bytes for chunks.").
4347
Default("2GB").Bytes()
4448

@@ -77,6 +81,7 @@ func registerStore(m map[string]setupFunc, app *kingpin.Application) {
7781
logger,
7882
reg,
7983
tracer,
84+
indexCacheConfig,
8085
objStoreConfig,
8186
*dataDir,
8287
*grpcBindAddr,
@@ -110,6 +115,7 @@ func runStore(
110115
logger log.Logger,
111116
reg *prometheus.Registry,
112117
tracer opentracing.Tracer,
118+
indexCacheConfig *extflag.PathOrContent,
113119
objStoreConfig *extflag.PathOrContent,
114120
dataDir string,
115121
grpcBindAddr string,
@@ -169,20 +175,29 @@ func runStore(
169175
return err
170176
}
171177

178+
indexCacheContentYaml, err := indexCacheConfig.Content()
179+
if err != nil {
180+
return errors.Wrap(err, "get content of index cache configuration")
181+
}
182+
172183
// Ensure we close up everything properly.
173184
defer func() {
174185
if err != nil {
175186
runutil.CloseWithLogOnErr(logger, bkt, "bucket client")
176187
}
177188
}()
178189

179-
// TODO(bwplotka): Add as a flag?
180-
maxItemSizeBytes := indexCacheSizeBytes / 2
181-
182-
indexCache, err := storecache.NewInMemoryIndexCache(logger, reg, storecache.Opts{
183-
MaxSizeBytes: indexCacheSizeBytes,
184-
MaxItemSizeBytes: maxItemSizeBytes,
185-
})
190+
// Create the index cache loading its config from config file, while keeping
191+
// backward compatibility with the pre-config file era.
192+
var indexCache storecache.IndexCache
193+
if len(indexCacheContentYaml) > 0 {
194+
indexCache, err = storecache.NewIndexCache(logger, indexCacheContentYaml, reg)
195+
} else {
196+
indexCache, err = storecache.NewInMemoryIndexCacheWithConfig(logger, reg, storecache.InMemoryIndexCacheConfig{
197+
MaxSize: storecache.Bytes(indexCacheSizeBytes),
198+
MaxItemSize: storecache.DefaultInMemoryIndexCacheConfig.MaxItemSize,
199+
})
200+
}
186201
if err != nil {
187202
return errors.Wrap(err, "create index cache")
188203
}

docs/components/store.md

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,19 @@ Flags:
6868
CA is specified, there is no client
6969
verification on server side. (tls.NoClientCert)
7070
--data-dir="./data" Data directory in which to cache remote blocks.
71-
--index-cache-size=250MB Maximum size of items held in the index cache.
71+
--index-cache-size=250MB Maximum size of items held in the in-memory
72+
index cache. Ignored if --index-cache.config or
73+
--index-cache.config-file option is specified.
74+
--index-cache.config-file=<file-path>
75+
Path to YAML file that contains index cache
76+
configuration. See format details:
77+
https://thanos.io/components/store.md/#index-cache
78+
--index-cache.config=<content>
79+
Alternative to 'index-cache.config-file' flag
80+
(lower priority). Content of YAML file that
81+
contains index cache configuration. See format
82+
details:
83+
https://thanos.io/components/store.md/#index-cache
7284
--chunk-pool-size=2GB Maximum size of concurrently allocatable bytes
7385
for chunks.
7486
--store.grpc.series-sample-limit=0
@@ -151,3 +163,61 @@ Filtering is done on a Chunk level, so Thanos Store might still return Samples w
151163
- `/-/ready` starts after all the bootstrapping completed (e.g initial index building) and ready to serve traffic.
152164

153165
> NOTE: Metric endpoint starts immediately so, make sure you set up readiness probe on designated HTTP `/-/ready` path.
166+
167+
## Index cache
168+
169+
Thanos Store Gateway supports an index cache to speed up postings and series lookups from TSDB blocks indexes. Two types of caches are supported:
170+
171+
- `in-memory` (_default_)
172+
- `memcached`
173+
174+
### In-memory index cache
175+
176+
The `in-memory` index cache is enabled by default and its max size can be configured through the flag `--index-cache-size`.
177+
178+
Alternatively, the `in-memory` index cache can also by configured using `--index-cache.config-file` to reference to the configuration file or `--index-cache.config` to put yaml config directly:
179+
180+
[embedmd]:# (../flags/config_index_cache_in_memory.txt yaml)
181+
```yaml
182+
type: IN-MEMORY
183+
config:
184+
max_size: 0
185+
max_item_size: 0
186+
```
187+
188+
All the settings are **optional**:
189+
190+
- `max_size`: overall maximum number of bytes cache can contain. The value should be specified with a bytes unit (ie. `250MB`).
191+
- `max_item_size`: maximum size of single item, in bytes. The value should be specified with a bytes unit (ie. `125MB`).
192+
193+
### Memcached index cache
194+
195+
The `memcached` index cache allows to use [Memcached](https://memcached.org) as cache backend. This cache type is configured using `--index-cache.config-file` to reference to the configuration file or `--index-cache.config` to put yaml config directly:
196+
197+
[embedmd]:# (../flags/config_index_cache_memcached.txt yaml)
198+
```yaml
199+
type: MEMCACHED
200+
config:
201+
addresses: []
202+
timeout: 0s
203+
max_idle_connections: 0
204+
max_async_concurrency: 0
205+
max_async_buffer_size: 0
206+
max_get_multi_concurrency: 0
207+
max_get_multi_batch_size: 0
208+
dns_provider_update_interval: 0s
209+
```
210+
211+
The **required** settings are:
212+
213+
- `addresses`: list of memcached addresses, that will get resolved with the [DNS service discovery](../service-discovery.md/#dns-service-discovery) provider.
214+
215+
While the remaining settings are **optional**:
216+
217+
- `timeout`: the socket read/write timeout.
218+
- `max_idle_connections`: maximum number of idle connections that will be maintained per address.
219+
- `max_async_concurrency`: maximum number of concurrent asynchronous operations can occur.
220+
- `max_async_buffer_size`: maximum number of enqueued asynchronous operations allowed.
221+
- `max_get_multi_concurrency`: maximum number of concurrent connections when fetching keys. If set to `0`, the concurrency is unlimited.
222+
- `max_get_multi_batch_size`: maximum number of keys a single underlying operation should fetch. If more keys are specified, internally keys are splitted into multiple batches and fetched concurrently, honoring `max_get_multi_concurrency`. If set to `0`, the batch size is unlimited.
223+
- `dns_provider_update_interval`: the DNS discovery update interval.

go.mod

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,19 @@ require (
1313
github.com/Azure/go-autorest/autorest/validation v0.2.1-0.20191028180845-3492b2aff503 // indirect
1414
github.com/NYTimes/gziphandler v1.1.1
1515
github.com/OneOfOne/xxhash v1.2.6 // indirect
16-
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d // indirect
16+
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d
1717
github.com/aliyun/aliyun-oss-go-sdk v2.0.4+incompatible
1818
github.com/armon/go-metrics v0.3.0
1919
github.com/aws/aws-sdk-go v1.25.35 // indirect
2020
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect
21+
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b
2122
github.com/cespare/xxhash v1.1.0
2223
github.com/cespare/xxhash/v2 v2.1.1 // indirect
2324
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd // indirect
2425
github.com/elastic/go-sysinfo v1.1.1 // indirect
2526
github.com/elastic/go-windows v1.0.1 // indirect
2627
github.com/evanphx/json-patch v4.5.0+incompatible // indirect
28+
github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb
2729
github.com/fatih/structtag v1.1.0
2830
github.com/fortytw2/leaktest v1.3.0
2931
github.com/fsnotify/fsnotify v1.4.7
@@ -83,7 +85,7 @@ require (
8385
go.opencensus.io v0.22.2 // indirect
8486
go.uber.org/atomic v1.5.0 // indirect
8587
go.uber.org/automaxprocs v1.2.0
86-
golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708 // indirect
88+
golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708
8789
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
8890
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
8991
golang.org/x/sys v0.0.0-20191113165036-4c7a9d0fe056 // indirect

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce
9393
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
9494
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
9595
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
96+
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b h1:L/QXpzIa3pOvUGt1D1lA5KjYhPBAN/3iWdP7xeFS9F0=
97+
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
9698
github.com/cenkalti/backoff v0.0.0-20181003080854-62661b46c409/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
9799
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
98100
github.com/cespare/xxhash v0.0.0-20181017004759-096ff4a8a059/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
@@ -134,6 +136,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
134136
github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
135137
github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M=
136138
github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
139+
github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb h1:IT4JYU7k4ikYg1SCxNI1/Tieq/NFvh6dzLdgi7eu0tM=
140+
github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb/go.mod h1:bH6Xx7IW64qjjJq8M2u4dxNaBiDfKK+z/3eGDpXEQhc=
137141
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
138142
github.com/fatih/structtag v1.1.0 h1:6j4mUV/ES2duvnAzKMFkN6/A5mCaNYPD3xfbAkLLOF8=
139143
github.com/fatih/structtag v1.1.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=

pkg/cacheutil/jump_hash.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package cacheutil
2+
3+
// jumpHash consistently chooses a hash bucket number in the range
4+
// [0, numBuckets) for the given key. numBuckets must be >= 1.
5+
//
6+
// Copied from github.com/dgryski/go-jump/blob/master/jump.go (MIT license).
7+
func jumpHash(key uint64, numBuckets int) int32 {
8+
var b int64 = -1
9+
var j int64
10+
11+
for j < int64(numBuckets) {
12+
b = j
13+
key = key*2862933555777941757 + 1
14+
j = int64(float64(b+1) * (float64(int64(1)<<31) / float64((key>>33)+1)))
15+
}
16+
17+
return int32(b)
18+
}

0 commit comments

Comments
 (0)