Top 5 High‑Performance Go In‑Memory Cache Libraries for Large Keys and High Concurrency
This article evaluates five Go in‑memory cache libraries—Ristretto, BigCache, FreeCache, FastCache, and groupcache—detailing their support for large keys, high‑throughput LRU‑like eviction, TPS/QPS benchmarks, core APIs, code examples, and practical selection guidance for backend developers.
Recommended List
Ristretto
Ristretto is an open‑source high‑performance cache from Dgraph that uses a Sampled LFU algorithm combined with TinyLFU admission, offering higher hit rates than classic LRU under real‑world loads. It leverages sync.Pool and lock‑free techniques to stay GC‑friendly in high‑concurrency scenarios.
TPS/QPS Data
Set (write) : can reach millions of TPS on multi‑core CPUs.
Get (read) : achieves tens of millions up to near a hundred million QPS, with minimal lock contention.
Supported Operations
Set(key, value, cost)
Get(key) → (interface{}, bool)
Del(key)
Wait() – waits for asynchronous Set processing
Clear()
Metrics – provides hit‑rate, eviction counts, etc.
Brief Usage Example
package main
import (
"fmt"
"github.com/dgraph-io/ristretto"
"time"
)
func main() {
cache, err := ristretto.NewCache(&ristretto.Config{
NumCounters: 1e7, // 10M counters
MaxCost: 1 << 30, // 1 GB
BufferItems: 64,
})
if err != nil { panic(err) }
ok := cache.Set("my-large-key", "my-large-value", 1)
if !ok { fmt.Println("Set failed, maybe due to contention") }
cache.Wait()
time.Sleep(10 * time.Millisecond)
if v, found := cache.Get("my-large-key"); found {
fmt.Printf("Found value: %s
", v.(string))
} else {
fmt.Println("Value not found.")
}
cache.Del("my-large-key")
if _, found := cache.Get("my-large-key"); !found {
fmt.Println("Value deleted successfully.")
}
}BigCache
BigCache is designed for storing massive numbers of entries and handling large keys while avoiding GC overhead by allocating a single large byte slice (or off‑heap memory) and sharding it across hash maps. Its eviction is time‑based (least‑recently‑updated).
TPS/QPS Data
Set : stable performance of hundreds of thousands to over a million TPS on multi‑core machines.
Get : typically millions to tens of millions QPS, with steady P99 latency even under heavy write loads.
Supported Operations
Set(key, value)
Get(key) → ([]byte, error)
Delete(key)
Len()
Reset()
Iterator()
Brief Usage Example
package main
import (
"fmt"
"github.com/allegro/bigcache/v3"
"time"
)
func main() {
config := bigcache.Config{
Shards: 1024,
LifeWindow: 10 * time.Minute,
CleanWindow: 5 * time.Minute,
MaxEntriesInWindow: 1000 * 10 * 60,
MaxEntrySize: 500,
Verbose: true,
HardMaxCacheSize: 8192, // MB
}
cache, err := bigcache.NewBigCache(config)
if err != nil { panic(err) }
key := "my-large-key"
value := []byte("my-large-value-as-bytes")
if err = cache.Set(key, value); err != nil {
fmt.Printf("Error setting value: %v
", err)
}
if v, err := cache.Get(key); err == nil {
fmt.Printf("Found value: %s
", string(v))
} else {
fmt.Printf("Value not found or error: %v
", err)
}
if err = cache.Delete(key); err == nil {
fmt.Println("Value deleted successfully.")
}
if _, err = cache.Get(key); err != nil {
fmt.Printf("Could not get deleted value: %v
", err)
}
}FreeCache
FreeCache targets zero GC overhead by storing all entries in a pre‑allocated ring buffer (a large byte slice), eliminating GC scans. It uses an approximate LRU eviction algorithm and excels when storing many small objects or large keys, provided total memory is bounded.
TPS/QPS Data
Set : comparable to BigCache, typically hundreds of thousands to a million TPS.
Get : excellent performance, reaching millions to tens of millions QPS, with near‑zero GC pause.
Supported Operations
Set(key, value, expireSeconds)
Get(key) → ([]byte, error)
Del(key) → bool
EntryCount()
Clear()
Iterator
Brief Usage Example
package main
import (
"fmt"
"github.com/coocood/freecache"
)
func main() {
cacheSize := 100 * 1024 * 1024 // 100 MB
cache := freecache.NewCache(cacheSize)
key := []byte("my-large-key")
value := []byte("my-large-value-for-freecache")
expire := 60 // seconds
if err := cache.Set(key, value, expire); err != nil { panic(err) }
if v, err := cache.Get(key); err == nil {
fmt.Printf("Found value: %s
", string(v))
} else {
fmt.Printf("Value not found or error: %v
", err)
}
if cache.Del(key) {
fmt.Println("Value deleted successfully.")
}
if _, err := cache.Get(key); err != nil {
fmt.Printf("Could not get deleted value: %v
", err)
}
}FastCache
FastCache, created by the VictoriaMetrics team, focuses on raw speed. It stores data in large byte slices divided into buckets, each bucket using a map for indexing, while values are appended to chunks, minimizing allocations and GC pressure.
TPS/QPS Data
Set : benchmarks show several million TPS.
Get : can reach tens of millions QPS, performing strongly in mixed read/write workloads.
Supported Operations
Set(key, value)
Get(dst, key) – appends the value to dst slice and returns the new slice
Has(key)
Del(key)
Reset()
UpdateStats(s *Stats)
Brief Usage Example
package main
import (
"fmt"
"github.com/VictoriaMetrics/fastcache"
)
func main() {
maxBytes := 100 * 1024 * 1024 // 100 MB
cache := fastcache.New(maxBytes)
key := []byte("my-large-key")
value := []byte("my-large-value-for-fastcache")
cache.Set(key, value)
var dst []byte
if v := cache.Get(dst, key); len(v) > 0 {
fmt.Printf("Found value: %s
", string(v))
} else {
fmt.Println("Value not found.")
}
cache.Del(key)
if !cache.Has(key) {
fmt.Println("Value deleted successfully.")
}
}groupcache
groupcache, authored by members of the Go team, provides a local LRU cache plus a peer‑to‑peer distributed caching framework. It prevents cache‑stampedes by ensuring only one node fetches a cold key while others wait for the result.
TPS/QPS Data
Focuses on distributed coordination rather than raw local speed; local LRU QPS is typically tens of thousands to a few hundred thousand.
Suitable when you need consistent cache across multiple services.
Supported Operations
NewGroup(name, cacheBytes, getter)
Get(ctx, key, dest)
Peer configuration for HTTP communication
Brief Usage Example (single‑node)
package main
import (
"context"
"fmt"
"github.com/golang/groupcache"
"log"
"sync"
"time"
)
var (
db = map[string][]byte{"key1": []byte("value1 from DB"), "key2": []byte("value2 from DB")}
dbMutex sync.RWMutex
)
func getter(ctx context.Context, key string, dest groupcache.Sink) error {
log.Printf("Cache miss! Fetching key '%s' from DB...", key)
dbMutex.RLock()
v, ok := db[key]
dbMutex.RUnlock()
if !ok { return fmt.Errorf("key not found in DB") }
return dest.SetBytes(v, time.Now().Add(time.Hour))
}
func main() {
myGroup := groupcache.NewGroup("my-cache-group", 64<<20, groupcache.GetterFunc(getter))
ctx := context.Background()
var data []byte
fmt.Println("
--- First Get for key1 ---")
if err := myGroup.Get(ctx, "key1", groupcache.AllocatingByteSliceSink(&data)); err != nil { log.Fatal(err) }
fmt.Printf("Got data: %s
", data)
fmt.Println("
--- Second Get for key1 ---")
if err := myGroup.Get(ctx, "key1", groupcache.AllocatingByteSliceSink(&data)); err != nil { log.Fatal(err) }
fmt.Printf("Got data (from cache): %s
", data)
fmt.Println("
--- Get for non-existent key3 ---")
if err := myGroup.Get(ctx, "key3", groupcache.AllocatingByteSliceSink(&data)); err != nil {
fmt.Printf("Correctly failed to get non-existent key: %v
", err)
}
}Summary and Selection Advice
If maximizing cache hit rate with the most modern eviction algorithm is the primary goal, Ristretto is the top choice.
When handling very large values or massive entry counts while requiring ultra‑stable latency, consider BigCache or FreeCache and benchmark both for your workload.
For raw speed and confidence in VictoriaMetrics engineering, FastCache offers a highly competitive option.
If you need a distributed cache solution rather than a local one, groupcache provides an officially backed, proven approach.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Nightwalker Tech
[Nightwalker Tech] is the tech sharing channel of "Nightwalker", focusing on AI and large model technologies, internet architecture design, high‑performance networking, and server‑side development (Golang, Python, Rust, PHP, C/C++).
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
