Skip to content

v1.5.0: Memcached auto discovery (breaking changes)

Latest

Choose a tag to compare

@yeqown yeqown released this 19 Oct 09:02
9984c7d

Memcached v1.5.0

This release adds opt-in Memcached cluster discovery, refreshable routing, and connection pools that follow topology changes. It also reduces allocation pressure in rendezvous selection and pool reuse, fixes standalone CLI/example builds, and moves the GUI to cmd/gui.

Breaking changes: v1.5.0 is not source-compatible with v1.4.0 for users of the resolver, picker, address, or public hash APIs. The module/import path remains github.com/yeqown/memcached; there is no /v2 migration. Read the migration notes before upgrading. The New constructor and client command signatures remain available.

go get github.com/yeqown/memcached@v1.5.0

New features and fixes

  • Add resolver.NewAutoDiscovery for the ASCII config get cluster extension used by AWS ElastiCache and Google Memorystore. Discovery is explicitly enabled; ordinary clients still use static resolution by default.
  • Add NewWithContext, WithResolveTimeout, resolver-controlled refresh scheduling, and discovery/topology telemetry.
  • Retain the last usable topology when background discovery fails. Reuse pools for unchanged node identities, drain removed nodes, and let borrowed connections finish their requests.
  • Reserve pool capacity before dialing, wake waiting borrowers on state changes, and close idle connections when pools shut down. Data connections are created on demand.
  • Restore standalone CLI and example builds and check them in CI. CLI release binaries now accept the version supplied by the release linker flags.
  • Fix the shared error variable race in the concurrent example.
  • Move the GUI from gui to cmd/gui and tighten GUI input types/accessibility semantics.
  • Refresh dependencies and migrate lint tooling to golangci-lint v2. Go 1.26.0 is required.
  • Expand self-contained tests, Memcached compatibility checks, and routing/lifecycle documentation.

Breaking changes and migration

Previous API v1.5.0 migration
Root Addr, NewAddr, Resolver, Picker, and Builder Use resolver.Addr, resolver.NewAddr(network, address), resolver.Resolver, and picker.Picker from the new subpackages. Construct pickers directly.
Address priority/metadata helpers Removed. resolver.Addr contains only Network and Address; node identity is the network/address pair.
WithPickBuilder and root *PickBuilder constructors Use WithPicker(picker.NewCRC32HashPicker()), WithPicker(picker.NewMurmur3HashPicker(seed)), or WithPicker(picker.NewRendezvousHashPicker(seed)).
Resolve(string) ([]*Addr, error) Implement Resolve(context.Context, string) (resolver.ResolveResult, *time.Time, error) and Close() error. Results include a Generation uint64; a nil next refresh time stops refreshes. Each resolver belongs to one client, which closes it.
Public hash package and Murmur3 digest Removed. Callers importing this package must migrate to another hash implementation or the new picker constructors.

Custom pickers must support concurrent calls and changing address snapshots.

Behavior changes to account for during rollout:

  • Rendezvous key placement changes, even with the same node addresses and seed, because scoring uses node identity rather than priority. Expect cache misses after upgrading; this release does not migrate cached values or replay requests.
  • Retrieval commands route by their first key. All keys supplied to multi-key Gets or GetAndTouches must belong to the same node; these commands do not scatter/gather across nodes.
  • Static resolution validates address syntax and rejects duplicate identities and invalid address forms. Parsing no longer performs DNS lookups.
  • CRC32/Murmur3 pickers retain modulo routing; changing cluster membership can remap many keys.
  • GUI build/run paths now start at cmd/gui.

To enable discovery while keeping the existing module path:

import (
    "time"

    "github.com/yeqown/memcached"
    "github.com/yeqown/memcached/picker"
    "github.com/yeqown/memcached/resolver"
)

client, err := memcached.New("configuration-endpoint:11211",
    memcached.WithResolver(resolver.NewAutoDiscovery(time.Minute)),
    memcached.WithResolveTimeout(5*time.Second),
    memcached.WithPicker(picker.NewRendezvousHashPicker(1)),
)

See usage and API migration and topology lifecycle.

Performance

  • Warm, uncontended pool reuse allocates no notification channels: 0 B and 0 allocations per operation in the pool microbenchmark. Waiting borrowers still allocate as needed.
  • A fresh release handle replaces the per-borrow closure and separate synchronization object. One handle allocation remains, preserving concurrent cleanup and panic semantics.
  • Default rendezvous selection uses stack scratch space for common inputs and makes zero heap allocations in the 10/50-node microbenchmarks. Larger inputs fall back to the heap; custom hashes continue to receive independent input buffers.
  • In local Apple M2 / Go 1.26 measurements, default rendezvous selection improved from approximately 658 to 252 ns/op at 10 nodes and 3.03 to 1.21 microseconds/op at 50 nodes compared with the previous main implementation.
  • The topology implementation still adds some request/pool overhead compared with v1.4.0: a warm Get measured 11 allocations rather than 9. End-to-end latency measurements were noisy; no production latency improvement is claimed.

Discovery I/O runs outside the request path. Each discovery client adds a refresh loop/timer and a discovery connection. Connection limits apply per node, so total capacity grows with cluster size.

Compatibility and validation

  • Root unit tests and real Memcached 1.6.37 integration tests passed with the race detector. CI checks lint, tests, standalone builds, and daemon compatibility.
  • All nine runnable examples were exercised against a local TCP/UDP Memcached daemon with the race detector. The concurrent example completed 10,000 Set/Get pairs. Standalone and workspace execution were checked.
  • The deprecated SASL example was compiled only; live SASL authentication was not tested.
  • AWS/GCP discovery was validated with protocol fixtures and topology integration tests; live cloud services were not tested. Ordinary upstream Memcached does not implement config get cluster.
  • This release does not add DNS/SRV/Kubernetes discovery, legacy AWS discovery-command fallback, or TLS/authentication settings for the discovery connection.

Changes: PR #43, plus documentation improvements in #39 and #42.

Full diff: v1.4.0...v1.5.0