cache-redis
Redis 6+ backend for cache with prefix isolation and Pub/Sub invalidation across processes.
go get github.com/ubgo/cache-redis
- Language
- Go
- Go version
- 1.24
- Core deps
- 3 direct
- Latest tag
- v0.1.0
- License
- Apache-2.0
- Go modules
- 1
Highlights from the README
- Native Redis, no reinvention. Every operation maps to the right Redis command:
SET EX/PX,SET NX,INCRBY/DECRBY,MGET, pipelined multi-set. No client-side TTL bookkeeping. - Safe on huge keyspaces.
DeleteByPrefixandIterateuse cursor-basedSCANwith batchedDEL— never the blockingKEYScommand — so they are safe to run against a multi-million-key production database. - Multi-tenant safe.
WithPrefixnamespaces every key, andFlushis scoped to that prefix so two services can share one Redis database without stepping on each other. - Tiered-cache ready.
NewInvalidationships a Redis Pub/Sub invalidation bus so an L1/L2cache-tiereddeployment can run a long L1 TTL and still stay coherent across pods. - Conformance-tested, Docker-free. Passes the shared
cachetest.Runsuite fully in-process viaminiredis. No Redis service required in CI.
Code from the README
package main
import (
"context"
"log"
"time"
"github.com/redis/go-redis/v9"
rediscache "github.com/ubgo/cache-redis"
)
func main() {
rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379"})
c := rediscache.New(rdb, rediscache.WithPrefix("svc:billing"))
defer c.Close()
ctx := context.Background()
if err := c.Set(ctx, "invoice:42", []byte(`{"total":1999}`), time.Minute); err != nil {
log.Fatal(err)
}
b, err := c.Get(ctx, "invoice:42") // (nil, cache.ErrNotFound) on miss
if err != nil {
log.Fatal(err)
}
log.Printf("%s", b)
}billing := rediscache.New(rdb, rediscache.WithPrefix("svc:billing"))
search := rediscache.New(rdb, rediscache.WithPrefix("svc:search"))
_ = billing.Set(ctx, "k", []byte("a"), time.Minute)
_ = search.Set(ctx, "k", []byte("b"), time.Minute)
_ = billing.Flush(ctx) // wipes only svc:billing:*
ok, _ := search.Has(ctx, "k") // still true — search is isolatedinv := rediscache.NewInvalidation(rdb, "cache:invalidate")
tc := tieredcache.New(
tieredcache.WithL1(memCache), // nanosecond local hits
tieredcache.WithL2(rediscache.New(rdb)), // shared across pods
tieredcache.WithInvalidation(inv), // Pub/Sub coherence
)
defer tc.Close()From the cache-redis README.
At a glance (from the README)
| Adapter | Backing store | TTL introspection | Prefix ops | Cross-process invalidation | Best for |
|---|---|---|---|---|---|
| cache-redis (this) | Redis 6+ | Yes (TTL) | Yes (SCAN) | Yes (Pub/Sub) | Shared distributed cache, L2 tier |
| cache-pg | Postgres / SQLite | Yes | Yes (LIKE) | No | Durable cache where you already run Postgres |
| cache-tiered | composes others | via tiers | via tiers | Yes (pluggable bus) | L1/L2 hot-path latency |
| cache-memcached | Memcached | No (unsupported) | No (unsupported) | No | Drop-in interop with an existing Memcached fleet |