github.com/thanos-io/thanos@v0.32.5/internal/cortex/chunk/cache/cache.go (about)

     1  // Copyright (c) The Cortex Authors.
     2  // Licensed under the Apache License 2.0.
     3  
     4  package cache
     5  
     6  import (
     7  	"context"
     8  	"flag"
     9  	"time"
    10  
    11  	"github.com/pkg/errors"
    12  
    13  	"github.com/go-kit/log"
    14  	"github.com/prometheus/client_golang/prometheus"
    15  )
    16  
    17  // Cache byte arrays by key.
    18  //
    19  // NB we intentionally do not return errors in this interface - caching is best
    20  // effort by definition.  We found that when these methods did return errors,
    21  // the caller would just log them - so its easier for implementation to do that.
    22  // Whatsmore, we found partially successful Fetchs were often treated as failed
    23  // when they returned an error.
    24  type Cache interface {
    25  	Store(ctx context.Context, key []string, buf [][]byte)
    26  	Fetch(ctx context.Context, keys []string) (found []string, bufs [][]byte, missing []string)
    27  	Stop()
    28  }
    29  
    30  // Config for building Caches.
    31  type Config struct {
    32  	EnableFifoCache bool `yaml:"enable_fifocache"`
    33  
    34  	DefaultValidity time.Duration `yaml:"default_validity"`
    35  
    36  	Background     BackgroundConfig      `yaml:"background"`
    37  	Memcache       MemcachedConfig       `yaml:"memcached"`
    38  	MemcacheClient MemcachedClientConfig `yaml:"memcached_client"`
    39  	Redis          RedisConfig           `yaml:"redis"`
    40  	Fifocache      FifoCacheConfig       `yaml:"fifocache"`
    41  
    42  	// This is to name the cache metrics properly.
    43  	Prefix string `yaml:"prefix" doc:"hidden"`
    44  
    45  	// For tests to inject specific implementations.
    46  	Cache Cache `yaml:"-"`
    47  }
    48  
    49  // RegisterFlagsWithPrefix adds the flags required to config this to the given FlagSet
    50  func (cfg *Config) RegisterFlagsWithPrefix(prefix, description string, f *flag.FlagSet) {
    51  	cfg.Background.RegisterFlagsWithPrefix(prefix, description, f)
    52  	cfg.Memcache.RegisterFlagsWithPrefix(prefix, description, f)
    53  	cfg.MemcacheClient.RegisterFlagsWithPrefix(prefix, description, f)
    54  	cfg.Redis.RegisterFlagsWithPrefix(prefix, description, f)
    55  	cfg.Fifocache.RegisterFlagsWithPrefix(prefix, description, f)
    56  
    57  	f.BoolVar(&cfg.EnableFifoCache, prefix+"cache.enable-fifocache", false, description+"Enable in-memory cache.")
    58  	f.DurationVar(&cfg.DefaultValidity, prefix+"default-validity", 0, description+"The default validity of entries for caches unless overridden.")
    59  
    60  	cfg.Prefix = prefix
    61  }
    62  
    63  func (cfg *Config) Validate() error {
    64  	return cfg.Fifocache.Validate()
    65  }
    66  
    67  // New creates a new Cache using Config.
    68  func New(cfg Config, reg prometheus.Registerer, logger log.Logger) (Cache, error) {
    69  	if cfg.Cache != nil {
    70  		return cfg.Cache, nil
    71  	}
    72  
    73  	caches := []Cache{}
    74  
    75  	if cfg.EnableFifoCache {
    76  		if cfg.Fifocache.Validity == 0 && cfg.DefaultValidity != 0 {
    77  			cfg.Fifocache.Validity = cfg.DefaultValidity
    78  		}
    79  
    80  		if cache := NewFifoCache(cfg.Prefix+"fifocache", cfg.Fifocache, reg, logger); cache != nil {
    81  			caches = append(caches, Instrument(cfg.Prefix+"fifocache", cache, reg))
    82  		}
    83  	}
    84  
    85  	if (cfg.MemcacheClient.Host != "" || cfg.MemcacheClient.Addresses != "") && cfg.Redis.Endpoint != "" {
    86  		return nil, errors.New("use of multiple cache storage systems is not supported")
    87  	}
    88  
    89  	if cfg.MemcacheClient.Host != "" || cfg.MemcacheClient.Addresses != "" {
    90  		if cfg.Memcache.Expiration == 0 && cfg.DefaultValidity != 0 {
    91  			cfg.Memcache.Expiration = cfg.DefaultValidity
    92  		}
    93  
    94  		client := NewMemcachedClient(cfg.MemcacheClient, cfg.Prefix, reg, logger)
    95  		cache := NewMemcached(cfg.Memcache, client, cfg.Prefix, reg, logger)
    96  
    97  		cacheName := cfg.Prefix + "memcache"
    98  		caches = append(caches, NewBackground(cacheName, cfg.Background, Instrument(cacheName, cache, reg), reg))
    99  	}
   100  
   101  	if cfg.Redis.Endpoint != "" {
   102  		if cfg.Redis.Expiration == 0 && cfg.DefaultValidity != 0 {
   103  			cfg.Redis.Expiration = cfg.DefaultValidity
   104  		}
   105  		cacheName := cfg.Prefix + "redis"
   106  		redisClient, err := NewRedisClient(&cfg.Redis)
   107  		if err != nil {
   108  			return nil, errors.Errorf("creating redis client: %v", err)
   109  		}
   110  		cache := NewRedisCache(cacheName, redisClient, reg, logger)
   111  		caches = append(caches, NewBackground(cacheName, cfg.Background, Instrument(cacheName, cache, reg), reg))
   112  	}
   113  
   114  	cache := NewTiered(caches)
   115  	if len(caches) > 1 {
   116  		cache = Instrument(cfg.Prefix+"tiered", cache, reg)
   117  	}
   118  	return cache, nil
   119  }