cache-cluster
Peer-aware distributed cache with a consistent-hash ring and HTTP peer fill, on any cache backend.
go get github.com/ubgo/cache-cluster
- Language
- Go
- Go version
- 1.24
- Core deps
- 1 direct
- Latest tag
- v0.1.0
- License
- Apache-2.0
- Go modules
- 1
Highlights from the README
- One fill per hot key, cluster-wide. Ownership routing plus single-flight at the owner collapses a thundering herd into a single backend load.
- Minimal reshuffle on membership change. Consistent hashing means adding or removing a node only moves that node’s share of keys, not the whole keyspace.
- Bring your own storage. Any
cache.Cache(in-memory, Redis, …) is the local backend; clustering is a thin layer on top. - No third-party dependencies. Standard library HTTP plus the ubgo/cache contract. The core and this module are dependency-free.
- Explicit, predictable membership. Peers are configured, not gossiped — no surprise topology changes.
Code from the README
package main
import (
"context"
"net/http"
clustercache "github.com/ubgo/cache-cluster"
memcache "github.com/ubgo/cache-mem"
)
func main() {
local := memcache.New()
node := clustercache.New("n1", local,
clustercache.WithPeers(map[string]string{
"n1": "http://10.0.0.1:8080",
"n2": "http://10.0.0.2:8080",
"n3": "http://10.0.0.3:8080",
}),
clustercache.WithLoader(func(ctx context.Context, key string) ([]byte, error) {
return db.Load(ctx, key)
}),
)
defer node.Close()
http.Handle("/_cache", node.Handler()) // peers reach each other here
go http.ListenAndServe(":8080", nil)
v, err := node.Get(context.Background(), "user:42") // owner-routed, filled once
_ = v
_ = err
}clustercache.WithPeers(map[string]string{
"n1": "http://10.0.0.1:8080",
"n2": "http://10.0.0.2:8080",
})ctx := context.Background()
_ = node.Set(ctx, "k", []byte("v"))
v, err := node.Get(ctx, "k")
ok, _ := node.Has(ctx, "k")
_ = node.Del(ctx, "k")
_ = v; _ = err; _ = okFrom the cache-cluster README.