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 }