Documentation
¶
Overview ¶
Package etcd backs the L0 cluster ring with etcd: a node registers itself under a lease and watches the member set, so membership is live and self-healing — a crashed node's lease expires and it drops out of every other node's ring within the TTL, with no manual deregistration. The ring (cluster/ring) is rebuilt locally from the watched member set, so placement stays coordinator-free on the hot path; etcd only distributes membership.
Index ¶
- Constants
- type Member
- type Membership
- type Ownership
- func (o *Ownership) Acquire(ctx context.Context, shard string) (bool, error)
- func (o *Ownership) LastPlan() []rebalance.Reassignment
- func (o *Ownership) Owned() []string
- func (o *Ownership) Reconcile(ctx context.Context, r *ring.Ring, shards []string) ([]string, error)
- func (o *Ownership) Release(ctx context.Context, shard string) error
Constants ¶
const DefaultTTL = 10 * time.Second
DefaultTTL is the lease TTL: a node absent for this long (no keepalive) is evicted from the ring. It bounds failure-detection latency.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Member ¶
Member is a cluster node's advertised identity: its ring ID, failure-domain Zone, and the Addr its peers reach it on (used by the replication transport later).
type Membership ¶
type Membership struct {
// contains filtered or unexported fields
}
Membership is a live, etcd-backed view of the cluster. It keeps this node registered (under a keep-alive'd lease) and watches the member set, exposing the current ring.Ring. Safe for concurrent use; Membership.Ring and Membership.Members are lock-free / cheap.
func Join ¶
func Join(ctx context.Context, client *clientv3.Client, root string, self Member, ttl time.Duration) (*Membership, error)
Join registers self in the cluster rooted at root (an etcd key prefix) under a lease of ttl (≤ 0 ⇒ DefaultTTL), snapshots the current members, and starts watching for changes. The returned Membership must be closed to deregister.
func (*Membership) AddrOf ¶
func (m *Membership) AddrOf(id string) string
AddrOf returns the network address of the member with the given ring node ID, or "" if the member is unknown. It is the resolver the cluster write path uses to turn ring owners into transport targets.
func (*Membership) Close ¶
func (m *Membership) Close(ctx context.Context) error
Close stops watching, revokes this node's lease (so its peers drop it immediately rather than after the TTL), and waits for the background goroutines to exit. The revoke is bounded by a derived timeout.
func (*Membership) LeaseID ¶
func (m *Membership) LeaseID() clientv3.LeaseID
LeaseID is this node's membership lease. Ownership claims bind to it so they auto-release when the node dies (the basis for the rebalance handoff).
func (*Membership) Members ¶
func (m *Membership) Members() []Member
Members returns the current members, sorted by ID.
func (*Membership) Ring ¶
func (m *Membership) Ring() *ring.Ring
Ring returns the current ring (lock-free). It is replaced atomically as membership changes.
func (*Membership) SetLogger ¶ added in v0.5.0
func (m *Membership) SetLogger(l *zap.Logger)
SetLogger attaches a logger that records member joins and leaves (Info on each change). It must be called before Join starts the watch loop in practice it is set immediately after Join. nil disables logging. Safe only before the watch observes its first event.
type Ownership ¶
type Ownership struct {
// contains filtered or unexported fields
}
Ownership coordinates exclusive **compaction ownership** of shards across the cluster via etcd, so a shard (a tenant) is flushed/merged by exactly one node at a time — the rebalance executor. A node claims a shard with a CAS write keyed by the shard and bound to its membership lease; the claim auto-releases if the node dies, so a new primary can take over without manual handoff. Placement still comes from the ring; etcd only arbitrates the claim during the brief windows where nodes disagree on the ring (watch-propagation lag) or a node has failed.
Reconcile is **event-driven and minimal-move**: it tracks the claims this node currently holds and, on each pass, only issues etcd writes for the shards whose ring-primary actually changed since the last pass (plus retrying any wanted-but-uncontended claim). In steady state — an unchanged ring with no new tenants — it makes no etcd round-trips at all, instead of one acquire/release per shard every tick. When the ring does change it records the rebalance.Plan it enacted (see Ownership.LastPlan) for observability/preview.
func NewOwnership ¶
NewOwnership returns an ownership coordinator for node id, claiming under root with the node's membership lease (see Membership.LeaseID).
func (*Ownership) Acquire ¶
Acquire tries to claim shard for this node. It returns true if the claim is now held by this node (newly acquired or already ours), false if another live node holds it. The claim is a CAS: create the key only if absent; otherwise it belongs to whoever already created it.
func (*Ownership) LastPlan ¶ added in v0.10.0
func (o *Ownership) LastPlan() []rebalance.Reassignment
LastPlan returns the primary handoffs enacted at the most recent ring change (empty if the ring has not changed since open). It is informational — a preview of what the last rebalance moved — for an operator dashboard.
func (*Ownership) Owned ¶ added in v0.10.0
Owned returns a sorted snapshot of the shards this node currently holds a compaction claim on.
func (*Ownership) Reconcile ¶
Reconcile makes this node's claims match the ring: it acquires every shard this node is the ring-primary of and releases the rest. It returns the shards this node now owns — the set it should flush and compact. Idempotent, so it is safe to call on every membership change and on a timer.
The work is minimal: ring-primary lookups are pure in-memory HRW hashing (no etcd), and an etcd write is issued only when a claim must change — a wanted shard not yet held is acquired (retried every pass, which is what lets a stale claim's release converge even under an unchanged ring), and a held shard no longer wanted is released. Steady state issues no etcd writes. On a ring change the enacted primary handoffs are recorded in Ownership.LastPlan.