Skip to content

v0.17.0

Choose a tag to compare

@github-actions github-actions released this 15 Jul 00:30
ec03187

This feature release completes online shard splitting with coordinator-driven automatic splits, introduces dynamic cluster administration (data-server and namespace CRUD through the admin API and CLI), and adds coordinator high availability with leader election and admin-request redirection. It also brings major performance, durability, and stability improvements across the WAL, replication, session, and read paths.

Compatibility

  • Upgrade coordinators before data servers. v0.17.0 introduces a coordinator-to-data-server instance-ID handshake that gates all internal RPCs: an upgraded coordinator manages v0.16.x data servers through a deprecated GetInfo fallback, but a v0.16.x coordinator cannot initialize v0.17.0 data servers (#1048, #1199).
  • Complete the data-server roll promptly. Once an upgraded data server is bound to the coordinator, it rejects internal RPCs that do not carry the instance ID, so v0.16.x leaders cannot replicate to already-upgraded followers; leadership converges onto upgraded nodes through the normal restart-driven elections. Avoid pausing the roll with a minority of data servers still on v0.16.x.
  • Public RPC authority validation is enabled by default. Data servers reject client RPCs whose gRPC :authority does not match an advertised or configured address with PERMISSION_DENIED: oxia: unexpected authority, as v0.16.3 briefly did before v0.16.5 made the check opt-in. Clients connecting through proxies, load balancers, or alternate DNS names need those addresses listed in the cluster-config allowExtraAuthorities, or the check disabled with featureFlags.authorityValidation: false in the data server config (#1038, #1134).
  • Client-facing errors now use standard gRPC status codes with Oxia error reasons attached as ErrorInfo details, and the unused LeaderHint message was removed. Mixed-version clients and servers interoperate, but non-Go client implementations matching the old custom status codes must adapt (#1118, #1119).
  • The admin ListNamespaces response changed from a list of names to a list of NamespaceView objects carrying spec and live status, and the deprecated ListNodes RPC was removed together with the oxia admin list-nodes and oxia admin list-namespaces commands; use oxia admin dataserver get and oxia admin namespace get (#1087, #1203).
  • Coordinator metadata written by v0.17.0 stays readable by v0.16.3+ readers for the Kubernetes ConfigMap and Raft providers, keeping rollback possible. Status-document compatibility for the file metadata provider is not preserved (#1099, #1105, #1207).

Requirements

  • No data migration is required on data servers.
  • Coordinator config: rename server.admin to server.public; the CLI bind flag changed from --admin-addr/-a to --public-addr/-p, keeping the default port 6651 (#1154).
  • Coordinator cluster config is now sourced through the metadata provider: set metadata.kubernetes.configName or metadata.file.configName (with metadata.file.dir). The --conf/-f and --cconfig flags, including the configmap:<namespace>/<name> form, are deprecated but still accepted and mapped onto the new settings (#1059).
  • Cluster config: namespace anti-affinity rules moved from policy.antiAffinities to antiAffinities directly on the namespace; the old key is not read (#1101).

Public API Changes

  • Admin protocol: added CreateDataServer, PatchDataServer, and DeleteDataServer (completing the data-server registry introduced in v0.16.3) and namespace CRUD RPCs (CreateNamespace, GetNamespace, PatchNamespace, DeleteNamespace); ListDataServers and ListNamespaces responses now carry views with live status; removed the deprecated ListNodes RPC (#1087, #1091, #1092, #1093, #1094, #1095, #1096, #1097, #1129, #1203).
  • Coordination protocol: added the Handshake RPC binding data servers to their coordinator and reporting supported features (GetInfo is deprecated, kept as a rolling-upgrade fallback), and the FreezeShard RPC used to quiesce a parent shard at split cutover; GetStatus now returns per-shard ShardStats with db size and operation counters (#1048, #1197, #1202).
  • Replication protocol: leaders advertise cumulative_acks_supported on Append, letting followers acknowledge a whole sync round with one cumulative ack; older followers keep acking per entry (#1164).
  • Client protocol: NotificationBatch entries changed from a map to a wire-compatible repeated field emitted in sorted key order, making the serialized batch deterministic across replicas; existing client implementations keep working unchanged (#1190).
  • Cluster configuration schema: new coordinators (name and public address per coordinator) and autoSplit sections (#1201, #1202).

Go Client Library

Relative to the last published client module version, oxia/v0.16.1:

  • SyncClient and AsyncClient are unchanged.
  • Breaking: AdminClient was reworked. Every method takes a context.Context, data-server and namespace CRUD methods were added, ListNamespaces returns []*proto.NamespaceView, and ListNodes with its result types was removed (#1087, #1091, #1092, #1093, #1094, #1095, #1096, #1097, #1203).
  • Added ErrUnauthorized, ErrUnauthenticated, and ErrUnknown sentinel errors, matchable with errors.Is (#1036).

Metrics Changes

  • Added oxia_coordinator_autosplit_evaluations_total and oxia_coordinator_autosplit_splits_initiated_total counters on the coordinator (#1205).
  • Shard-split observer metrics on the parent leader, introduced with the split groundwork in v0.16.2 but not documented then: oxia_server_observer_snapshots_started/_completed/_failed/_sent, oxia_server_observer_snapshots_transfer_time, and the per-observer oxia_server_observer_ack_offset gauge for monitoring split catch-up (#945).
  • oxia_server_session_active changed from an asynchronous gauge to an up-down counter: the value and Prometheus exposition are unchanged, but OTLP pipelines filtering by instrument type now see a non-monotonic sum (#1182).

Operational Changes

  • Automatic shard splitting is available and disabled by default: when autoSplit is enabled in the cluster config, the coordinator initiates splits from sustained per-shard size/throughput stats, with stabilization and cooldown windows and a max-shards-per-namespace guard (#1202, #1205).
  • Multiple coordinators can run against shared metadata: each coordinator has a stable identity (metadata.name, defaulting to the hostname), the elected leader publishes its address in the metadata lease, and admin requests reaching a non-leader are redirected to the leader; coordinator public addresses are listed in the cluster config (#1155, #1156, #1192, #1201).
  • The admin CLI was restructured into resource command groups: oxia admin namespace create|get|patch|delete, oxia admin dataserver create|get|patch|delete, and oxia admin shard split (replacing split-shard), with a new -o/--output json|yaml|table selector; admin and client CLIs accept --auth-token/--auth-token-file independently of TLS (#1057, #1104, #1109, #1114).
  • Empty cluster configs are accepted, so a cluster can be bootstrapped and then populated entirely through the admin API (#1079).
  • Node saturation no longer triggers leader elections: a server that misses health probes only because it is overloaded no longer causes re-election storms that amplify the overload (#1233).
  • Sessions scale much further: per-session expiry goroutines were replaced by a shared scheduler, cutting per-session overhead from kilobytes plus a goroutine to about a hundred bytes (#1236).
  • The coordinator exits on metadata leadership loss instead of risking a split brain (#1175).
  • Log noise reduced during startup, elections, and client disconnects; session lifecycle logging moved to debug level (#1208, #1212, #1213, #1226, #1229).
  • --profile now also enables mutex and block profiling (#1238).

Changes Since v0.16.3

Fixes that were backported to the v0.16.4-v0.16.7 patch releases are also included below, since v0.17.0 supersedes the release-0.16 branch (#1115, #1116, #1123, #1124, #1133, #1134, #1137, #1139, #1143, #1144, #1147, #1175).

  • shard split: correct split cutover end to end — children fenced at the parent's term, parent frozen and drained before fencing, namespace term options carried to children, and commit offsets propagated to observers parked at the WAL head (#1173, #1197, #1224, #1232)
  • coordinator: automatic shard splitting driven by per-shard stats (#1202, #1205)
  • coordinator: admin CRUD APIs and CLI for data servers and namespaces, with status views and output formats; deprecated ListNodes removed (#1057, #1087, #1091, #1092, #1093, #1094, #1095, #1096, #1097, #1129, #1203)
  • coordinator: leader election with stable identities, lease-published public addresses, and admin-request redirection to the leader (#1155, #1156, #1192, #1201)
  • coordinator: instance-ID handshake binding data servers to the coordinator, with initial elections gated on the handshake (#1048, #1199)
  • coordinator: config model cleanup — server.public rename, cluster config sourced through the metadata provider, empty cluster configs accepted, namespace anti-affinities directly on the namespace (#1154, #1059, #1079, #1101)
  • coordinator: metadata schema normalized to protobuf while keeping YAML/JSON documents compatible with v0.16.3+ readers (#1099, #1105, #1207)
  • coordinator: prevent node saturation from triggering leader elections (#1233)
  • coordinator: raft metadata provider hardening — snapshot retention, resource lifecycle, FSM synchronization, and exit on leadership loss (#1170, #1172, #1175)
  • coordinator: require synced status before balancing, avoid blocking best-effort election enqueue, synchronize runtime close with shard deletion (#1106, #1222, #1241)
  • wal: recover segments with empty or stale index files instead of panicking, reject empty index files, close read-only files on mmap errors (#1228, #1230, #1231)
  • wal: make rolled-over segments durable before acknowledging them, and fix a self-deadlock when truncating below all retained segments (#1176, #1178)
  • wal: stop blocking appends and reads during fsync, defer segment fsync out of the rollover path, marshal entries into reusable buffers (#1160, #1161, #1162)
  • replication: reject gapped appends instead of acking entries the follower does not have (#1239)
  • replication: coalesce follower acks into one cumulative ack per sync round, run commit callbacks off the quorum-ack tracker lock, send duplicate-entry acks from the syncer goroutine (#1164, #1159, #1177)
  • replication: keep snapshot-bootstrapped followers eligible for leader election, drain follower cursors on close (#1163, #1139)
  • dataserver: prevent a slow WriteStream client from stalling the whole shard (#1158)
  • dataserver: persist control-request commit offsets and enabled features across restarts (#1133, #1137)
  • dataserver: drain leader operations before closing the Pebble DB, avoid killing the process when Close() races gRPC Serve() (#1143, #1169)
  • dataserver: use the Pebble default memtable size instead of a fixed 32 MiB per shard (#1123)
  • dataserver: skip unchanged periodic shard-status persists, allocation-free condition broadcasts, skip debug-log attribute boxing when the level is off (#1183, #1185, #1186)
  • database: run reads, lists and range scans inline on the handler goroutine, decode each scanned key once, marshal new entries directly into the Pebble batch arena, skip copying old values when only metadata is needed (#1191, #1184, #1189, #1188)
  • database: seek past the internal-key region instead of stepping through it, drop a duplicated seek in getHigher, avoid decoding internal keys in place (#1243, #1242, #1181)
  • sessions: replace per-session goroutines with a shared session-expiry scheduler (#1236); close sessions outside the session-manager lock and avoid re-acquiring it on failed session starts (#1171, #1179)
  • notifications: retry stream initialization on retryable errors, stop dispatcher failures from becoming permanent, initialize dispatch from the notification offset, enforce the read batch limit, make batch serialization deterministic (#1165, #1144, #1147, #1187, #1190)
  • client: standardize on gRPC error codes with Oxia error details (#1118, #1119)
  • client: fix stuck shard-assignment streams by draining server-side termination signals (#1215, #1216); discard multi-shard get responses after the first error (#1180)
  • client/dataserver: refresh stale pooled gRPC connections and align eviction with keepalive (#1115, #1116)
  • security: enable public RPC authority validation by default, strip schemes from configured authorities (#1134, #1124)
  • cli: auth token flags decoupled from TLS (#1109, #1114); mutex and block profiling with --profile (#1238)
  • logging: quieter startup, elections, and disconnects; session lifecycle logs at debug level; deduplicated JSON time field and human-readable durations (#1075, #1076, #1208, #1212, #1213, #1226, #1229)
  • deps: grpc-go 1.81.1 with CodecV2 registration (#1167, #1168); golang.org/x/net v0.55.0 fixing multiple HIGH CVEs (#1200); golang.org/x/crypto 0.52.0 (#1220)

Full Changelog: v0.16.3...v0.17.0