github.com/thanos-io/thanos@v0.32.5/pkg/cache/memcached.go (about)

     1  // Copyright (c) The Thanos Authors.
     2  // Licensed under the Apache License 2.0.
     3  
     4  package cache
     5  
     6  import (
     7  	"context"
     8  	"time"
     9  
    10  	"github.com/go-kit/log"
    11  	"github.com/go-kit/log/level"
    12  	"github.com/prometheus/client_golang/prometheus"
    13  	"github.com/prometheus/client_golang/prometheus/promauto"
    14  
    15  	"github.com/thanos-io/thanos/pkg/cacheutil"
    16  )
    17  
    18  // MemcachedCache is a memcached-based cache.
    19  type MemcachedCache struct {
    20  	logger    log.Logger
    21  	memcached cacheutil.RemoteCacheClient
    22  	name      string
    23  
    24  	// Metrics.
    25  	requests prometheus.Counter
    26  	hits     prometheus.Counter
    27  }
    28  
    29  // NewMemcachedCache makes a new MemcachedCache.
    30  func NewMemcachedCache(name string, logger log.Logger, memcached cacheutil.RemoteCacheClient, reg prometheus.Registerer) *MemcachedCache {
    31  	c := &MemcachedCache{
    32  		logger:    logger,
    33  		memcached: memcached,
    34  		name:      name,
    35  	}
    36  
    37  	c.requests = promauto.With(reg).NewCounter(prometheus.CounterOpts{
    38  		Name:        "thanos_cache_memcached_requests_total",
    39  		Help:        "Total number of items requests to memcached.",
    40  		ConstLabels: prometheus.Labels{"name": name},
    41  	})
    42  
    43  	c.hits = promauto.With(reg).NewCounter(prometheus.CounterOpts{
    44  		Name:        "thanos_cache_memcached_hits_total",
    45  		Help:        "Total number of items requests to the cache that were a hit.",
    46  		ConstLabels: prometheus.Labels{"name": name},
    47  	})
    48  
    49  	level.Info(logger).Log("msg", "created memcached cache")
    50  
    51  	return c
    52  }
    53  
    54  // Store data identified by keys.
    55  // The function enqueues the request and returns immediately: the entry will be
    56  // asynchronously stored in the cache.
    57  func (c *MemcachedCache) Store(data map[string][]byte, ttl time.Duration) {
    58  	var (
    59  		firstErr error
    60  		failed   int
    61  	)
    62  
    63  	for key, val := range data {
    64  		if err := c.memcached.SetAsync(key, val, ttl); err != nil {
    65  			failed++
    66  			if firstErr == nil {
    67  				firstErr = err
    68  			}
    69  		}
    70  	}
    71  
    72  	if firstErr != nil {
    73  		level.Warn(c.logger).Log("msg", "failed to store one or more items into memcached", "failed", failed, "firstErr", firstErr)
    74  	}
    75  }
    76  
    77  // Fetch fetches multiple keys and returns a map containing cache hits, along with a list of missing keys.
    78  // In case of error, it logs and return an empty cache hits map.
    79  func (c *MemcachedCache) Fetch(ctx context.Context, keys []string) map[string][]byte {
    80  	// Fetch the keys from memcached in a single request.
    81  	c.requests.Add(float64(len(keys)))
    82  	results := c.memcached.GetMulti(ctx, keys)
    83  	c.hits.Add(float64(len(results)))
    84  	return results
    85  }
    86  
    87  func (c *MemcachedCache) Name() string {
    88  	return c.name
    89  }