Dragonfly v2.1
This release is important because starting from this version, it changes how teams can use our software in production.
Starting from v2.1.0 the project moves from BUSL-1.1 to the Dragonfly Source-Available License (DSAL).
For more details, please read https://www.dragonflydb.io/blog/introducing-dragonfly-enterprise
Besides this much of the work is hardening. ACL enforcement is stricter, credentials are redacted from logs, and many crashes and deadlocks are fixed across blocking commands, tiered storage, Lua and search. Search gains index aliases, multi-attribute fields and punctuation-aware queries. There is also an experimental append-only-file (AOF) persistence mode, and a number of throughput and memory improvements.
Highlights
- Dragonfly's licence changes from BSL 1.1 to DSAL, starting with v2.1 (#8739).
- The RESP IoLoopV2 is now enabled by default (#8576).
- Search gains FT.ALIAS* commands, alias-aware queries and multiple attributes per field (#8556, #8649, #8604).
Commands
- Without
--bind, Dragonfly now listens on::on dual-stack hosts, serving IPv4 and IPv6 from one listener (#8682). - Added
CLIENT TRACKINGINFO(#8497). - Added the
lua_max_stall_msflag, which kills Lua scripts that block their thread before writing (#8426). - Added the
--list_compress_policyflag.--list_compress_dict_thresholdis deprecated (#8008). DEBUG OBJHISTnow covers JSON, streams and sketches (#8656).- Added the
io_threadsandmax_connected_clients_per_threadPrometheus metrics (#8701). - INFO
expired_keysandevicted_keysare now cumulative across FLUSHDB/FLUSHALL and reset only by CONFIG RESETSTAT (#8562).
Performance
- During replica full sync, writes to buckets the snapshot has not yet reached skip forced early serialization. This now also works with a second replica and for EXPIRE-family commands (#8112).
DFLYCLUSTER GETSLOTINFOcollects stats per shard round, with bounded memory (#8715).- The background sweep that flushes unowned slots after a migration is now throttled (#8641).
- Inline single-shard transactions are faster, with [about 5% fewer cycles and about 8% fewer instructions] (#8609).
- Added the opt-in
--shard_sidekiq_queuesflag so Sidekiq queues and their private queues share a shard (#8642). - Single-shard BLMOVE/BRPOPLPUSH completes in one hop when data is available (#8638).
- Reduced the CPU overhead of cache-mode bumps (#8589).
- Added
edge_depthto--list_compress_policy(#8334). - Double formatting now uses dragonbox, [about 1.8–3.6x faster] (#8461).
- OAHTable now shrinks its bucket array automatically (#8454).
- V2 connections now flush replies right after a pipeline squash (#8431).
- V2 parse-loop lookups are cached per parsing segment (#8230).
- MGET and Memcache multi-get return large values zero-copy, and the borrow threshold is lowered to 8KB (#8420).
- CLUSTER SLOTS and CLUSTER SHARDS batch their replies, [from about 7000 socket writes to fewer than 100 for 1024 ranges] (#8390).
- Shard shutdown frees the whole heap in one operation (#8336).
- SCAN now packs returned keys into a single buffer (#8314).
- SCAN expiry checks and key extraction are faster (#8297).
- The journal is turned off automatically on shards where nothing uses it (#8259).
- Faster ASCII string decoding (#8295).
- Tiered storage's external allocator frees pages in O(1) and [halves descriptor RAM from about 128MB to 64MB per TB] (#8527).
Replication
- Added Prometheus metrics for snapshot and replica-disconnect state (#8740).
- S3 snapshot upload sockets are now paced to
snapshot_egress_limit_bytes. Added--s3_upload_traffic_mark(#8719).
Search
- FT.CREATE now stores the INDEXMISSING, INDEXEMPTY and UNF flags. FT.INFO output is aligned with the reference (#8720).
- FT.ALTER and FT.DROPINDEX accept index aliases (#8683).
- Search commands resolve aliases created with FT.ALIASADD (#8649).
- Added FT.ALIASADD, FT.ALIASUPDATE and FT.ALIASDEL (#8556).
- Aliases are persisted in snapshots and sent to replicas on full sync (#8624).
- The schema is keyed by alias, so a HASH field can have several attributes (#8604).
- JSON indexes accept the same path under several aliases (#8651).
- Queries accept punctuation inside words, such as
@email:*example.com*(#8419). - FT.INFO
percent_indexedreports real build progress (#8428).
Security
- CONFIG SET values and ACL SETUSER tokens are no longer exposed in logs, SLOWLOG or error replies (#8659).
- Fixed ACL category mismatches with Redis (#8308).
Metrics & Observability
- Prometheus
dragonfly_rdb_serialize_total,dragonfly_save_in_progressanddragonfly_replica_disconnects_total{reason}are exported (#8740). - Added V2 RESP IO loop and pipeline squash counters (#8557).
pipeline_latency_secondsis split by atypelabel (readorother) (#8535).
AOF Persistence (Experimental)
- Added manifest-driven startup for
--aof, with adoption of an existing snapshot as the base (#8502). - Added AOF replay at startup, run in parallel per shard (#8484).
- The AOF chain reader now reads in 128 KB buffered chunks (#8610).
- The chain reader detects a torn or damaged tail and replays the valid prefix (#8570).
- The segment writer fdatasyncs once per second, tracks a durable LSN and handles I/O errors (#8464).
Cloud & Storage
- Added an opt-in background repack scan for tiered storage to reduce disk fragmentation (#8007).
DEBUG OBJHISTreports the data size of tiered values (#8655).- Large disk allocations are now counted in tiered storage accounting (#8377).
Bug Fixes
- Cluster slot flush now covers every database (#8669).
- Fixed tiered small-bin leaks and stash-failure handling (#8636).
- Fixed ACL key-permission checks for read-write commands (#8721).
- Refactored ACL family code. ACL LOG is now newest first, and duplicate users are no longer double-counted (#8687).
- Saves are cancelled when the server enters LOADING, and blocked clients are unblocked (#8505).
- Hardened ACL file handling (#8681).
- Search index definitions with spaces or control bytes now persist correctly (#8696).
- TIME replies with bulk strings (#8712).
- Fixed a deadlock when XINFO or JSON.DEBUG ran in single-shard Lua scripts (#8648).
- A search index dropped during an HNSW query now returns an error (#8702).
- The per-index map for hash fields with a TTL now shrinks after removals (#8672).
- Replicas keep FT.SYNUPDATE groups during full sync (#8671).
- Fixed a crash in ACL SETUSER with an empty category (#8685).
- A cloud storage init failure at runtime no longer kills the server (#8689).
- WAIT honors its timeout (#8668).
- Fixed ACL gaps in RM and CLIENT/MEMORY admin subcommands (#8627).
- Expired TTL hash fields no longer leave stale postings in search indices (#8657).
- FT.SEARCH SORTBY ties are now ordered deterministically (#8664).
- Fixed a master crash when WAIT ran against a stalled replica (#8665).
- Fixed HELLO AUTH credential leaks (#8612).
- Rejected
*and<ms>-*stream IDs outside XADD (#8634). - Internal synonym tokens no longer leak into search results (#8603).
- Cache mode no longer lets MSET evict its own key (#8630).
- Empty consumer and group names are accepted (#8631).
- Fixed ACL category regressions (#8614).
- Blocking XREAD/XREADGROUP now serves every ready stream (#8595).
- Fixed transaction polls dropped while a transaction was running (#8538).
- Fixed a crash in blocking commands when watched keys expire (#8593).
- Fixed a crash in multi-shard MGET with tiered keys (#8539).
- Fixed PFMERGE writing the destination on every shard (#8602).
- The idle
timeoutnow also closes connections that never sent a byte (#8368). - FT.ALTER keeps synonym groups (#8580).
- FT.INFO lists fields in declaration order (#8569).
- An expired key is now treated as missing regardless of its type (#8581).
- BM25 scores no longer depend on the shard count (#8542).
- Fixed a DENYOOM abort after hours of uptime (#8575).
- Fixed ordering of control messages on V2 connections after a parser error (#8547).
- Client tracking now invalidates keys on expiry or eviction (#8563).
- Fixed replica epoll starvation in the stable-sync loop (#8559).
- Fixed keyspace notifications sent from atomic sections (#8558).
- Fixed tiered allocator segment queue corruption (#8528).
- Fixed hangs when replaying an AOF in which a shard's log ends early (#8543).
- V2 now handles protocol errors in order (#8541).
- Fixed vector queries combined with SORTBY (#8540).
- Fixed stale QList node indices (#8488).
- Fixed a stuck-queue hang with tiering and SAVE/BGSAVE (#8520).
- Fixed Lua result serialization with wrapper fields (#8517).
- Fixed QList ZSTD handling of
dont_compressnodes (#8487). - Fixed a stack overflow on deeply nested search queries (#8492).
- Fixed a crash after a failed load of a snapshot with search indices (#8500).
- Fixed a slot migration cancel race (#8473).
- Partial sends now refresh progress, so
--send_timeoutno longer closes healthy connections (#7536). - Fixed missing keys in snapshots with tiering (#8457).
- Fixed INFO
rdb_bgsave_in_progressstaying at 1 (#8459). - SORT BY/GET handles offloaded strings (#8436).
- Zero-padded MONITOR microseconds (#8437).
- The ACL file parser accepts 3-token rules (#8399).
- CONFIG SET requirepass now replaces existing passwords (#8403).
- Fixed possible use-after-free in SUNION, SDIFF, SINTER and ZRANDMEMBER (#8393).
- FT.PROFILE reports shard errors (#8391).
- SCAN and KEYS hide expired keys during CLIENT PAUSE (#8362).
- Fixed an SCRIPT FLUSH deadlock (#8110).
- Glob matching is now iterative and no longer overflows the stack (#8350).
- Expired keys are hidden during a write pause (#8323).
- Fixed QList recompression (#8333).
- The cluster config parser rejects invalid health values (#8306).
- Fixed RESPParser heap lifetime (#8307).
- TopK uses the data heap (#8312).
- Corrected ACL categories (#8311).
- Parked commands are released when the connection closes during CLIENT PAUSE (#8296).
- QList tiering metadata uses the data heap (#8313).
- Fixed connection close-path bugs (#8316).
- Fixed a mimalloc
mi_heap_destroycrash (#8285). - Fixed ACL checks for source/destination commands (#8249).
- Fixed SORT STORE replication (#8298).
- Replicas advertise the master's announced address in emulated cluster mode (#8241).
- DFLYMIGRATE no longer crashes without cluster mode (#8290).
What's Changed
- refactor: use ascii_unpack_fast to improve GetString performance by @BorysTheDev in #8295
- fix(cluster): reject DFLYMIGRATE without cluster mode by @foobar in #8290
- fix(tests): download the S3 fixture server from silo instead of dl.min.io by @vyavdoshenko in #8301
- fix(cluster): advertise the master's announced address on replicas in emulated mode by @vyavdoshenko in #8241
- fix(server): Fix sort .. store replication by @abhijat in #8298
- tools: Add scripts and UI for ci dashboard by @abhijat in #7930
- feat(server): Turn off journal after a bound by @abhijat in #8259
- refactor: use RESPParser for Redis replication by @BorysTheDev in #8211
- refactor: improve SCAN iterator/expiration performance by @BorysTheDev in #8297
- fix(acl): per key permission check for read-write commands by @kostasrim in #8249
- fix: crash in mimalloc mi_heap_destroy by @kostasrim in #8285
- chore: move watchdog after shard destruction by @kostasrim in #8286
- refactor: FuncSHA1 for interpreter by @BorysTheDev in #8310
- fix(facade): two connection close-path fixes by @romange in #8316
- fix: macos build missing header by @vyavdoshenko in #8320
- refactor: prepare the CLIENT PAUSE release path by @romange in #8317
- chore(deps): bump actions/checkout from 6 to 7 in the actions group by @dependabot[bot] in #8315
- fix: reduce script load contention by @BorysTheDev in #8321
- chore: qlist should use data heap only for all allocations by @kostasrim in #8313
- fix: missmatch in acl categories by @kostasrim in #8308
- fix(server): release commands parked by CLIENT PAUSE when the connection closes by @vyavdoshenko in #8296
- feat(ci): verify acl categories match valkey by @kostasrim in #8311
- fix(server): Fix blocking crash on wrongtype by @dranikpg in #8305
- feat: pack scan result to get better performance by @BorysTheDev in #8314
- fix: topk should use data heap for all allocations by @kostasrim in #8312
- fix: RESPParser should use backing heap by @kostasrim in #8307
- chore(helm-chart): update to v2.0.0 by @github-actions[bot] in #8332
- test: synchronize BLMPopBlocking lock assertion by @romange in #8330
- fix(cluster): reject invalid cluster node health values in config parser by @Tyagiquamar in #8306
- refactor(server): migrate StartMultiLockedAhead chain to ParsedArgs by @romange in #7803
- fix: seeder hash compare for CF by @kostasrim in #8339
- fix(tls): Allow JWT authentication with TLS by @tjovicic in #8322
- Remove compact object Huffman encoding by @romange in #8338
- refactor: inline lua reply stack by @BorysTheDev in #8341
- fix: macos and fedora build by @kostasrim in #8342
- fix(qlist): guard ZSTD dictionary recompression by @romange in #8333
- fix: jwt auth default without password should be rejected by @kostasrim in #8291
- fix(rdb): validate hash/zset listpacks deeply on load, surface load errors by @vyavdoshenko in #8328
- test(ci): enable more Valkey TCL suites in the external-mode gate by @vyavdoshenko in #8343
- server: Expired keys should hide even on write pause by @abhijat in #8323
- fix: hash field expiration accuracy by @BorysTheDev in #8340
- refactor: use ScanResult for SCAN cmd family by @BorysTheDev in #8352
- refactor: improve lua performance by @BorysTheDev in #8335
- docs(readme): refresh README by @szepeviktor in #8358
- perf: one-shot data heap destruct by @kostasrim in #8336
- chore: update mimalloc to v2.5.2 by @kostasrim in #8349
- refactor: reuse expiration code for set and hset by @BorysTheDev in #8363
- fix(core): match globs iteratively so a pattern cannot overflow the fiber stack by @vyavdoshenko in #8350
- fix(ci): demultiplex mangled output stream by @kostasrim in #8351
- fix: non-blocking interpreter pool so SCRIPT FLUSH can't deadlock by @vyavdoshenko in #8110
- server: hide expired keys during client pause by @abhijat in #8362
- ci: revert V2 regression test by @glevkovich in #8371
- feat(qlist): add --list_compress_policy for list compression by @romange in #8008
- CI: status dashboard workflow improvments by @abhijat in #8347
- fix(tests): add replication barrier to test by @abhijat in #8369
- feat(ci): upload core dumps on reg-test failures by @kostasrim in #8364
- chore: remove committed_golden validation metric by @romange in #8373
- fix(tiering): Account for large disk allocations by @romange in #8377
- CI: compress JSON files for dashboard in parallel by @abhijat in #8375
- Revert "ci: revert V2 regression test" by @glevkovich in #8376
- refactor: remove RedisParser from dflybench by @BorysTheDev in #8381
- refactor: remove RedisParser for resp-validator by @BorysTheDev in #8379
- fix: reject empty field names and consume SETID parse errors by @vyavdoshenko in #8385
- fix(search): make FT.PROFILE report shard errors like FT.SEARCH by @vyavdoshenko in #8391
- docs(replication): describe current backlog retention flags by @ZainnQureshii in #8383
- perf: batch reply for cluster slots/shards by @kostasrim in #8390
- fuzz: make crash replay find the input that actually crashed the server by @vyavdoshenko in #8396
- chore(server): Remove unused OpDel, minor cleanups by @abhijat in #8397
- fix(set): set OAHset implementation instead of StringSet by @vyavdoshenko in #8398
- fix: enforce launder iterators for preemptive commands by @kostasrim in #8393
- feat: use valkey hash expiry format by default by @BorysTheDev in #8370
- refactor(journal): split JournalStreamer into BufferedSocketWriter + consumers by @romange in #8395
- ci: add stale workflow for inactive issues and PRs by @romange in #8416
- CI: persist test summaries over time and reuse them by @abhijat in #8353
- refactor(server): share bucket traversal loop between snapshot and migration by @romange in #8417
- feat(server): make scoped-memory metric account for deletes by @abhijat in #8387
- perf(facade): cache V2 parse-loop lookups by @glevkovich in #8230
- fix: test_network_disconnect_during_migration by @BorysTheDev in #8423
- refactor: migrate outgoing migration to RESPParser by @BorysTheDev in #8389
- refactor(server): share SerializeBucketLocked between snapshot and migration by @romange in #8422
- chore: retire JSON flags and remove flat JSON storage by @romange in #8382
- feat(server): Track memory drop in async deletes by @abhijat in #8401
- chore: jwt authentication should be static by @kostasrim in #8415
- fix: match config set requirepass to valkey by @kostasrim in #8403
- chore(server): Use
ranges::findandset::containsby @abhijat in #8425 - feat(server): extend get_zero_copy to MGET and retire mget_dedup_keys by @romange in #8420
- docs: add sharded AOF design proposal by @romange in #8394
- fix(acl): accept 3-token user rules in aclfile parser (#8299) by @Tyagiquamar in #8399
- fix(facade): reply after V2 pipeline squash by @glevkovich in #8431
- fix(server): zero-pad the microseconds in MONITOR timestamps by @vyavdoshenko in #8437
- chore(build): link helio/build-dbg to the build dir for clangd by @romange in #8438
- feat(search): support punctuation inside query words (e.g. @email:example.com) by @vyavdoshenko in #8419
- fix(server): read offloaded strings in SORT BY/GET instead of aborting by @vyavdoshenko in #8436
- feat(search): report real index build progress in FT.INFO percent_indexed by @vyavdoshenko in #8428
- chore(tiering): Expose external alloc metrics/stats by @dranikpg in #8384
- fix(tiering): Disable cooling during load by @dranikpg in #8144
- feat: add error processing for unsupported rdb by @BorysTheDev in #8421
- fix(tests): pin redis-py below 8 by @kostasrim in #8453
- refactor: remove RedisParser from replica by @BorysTheDev in #8452
- fix(server): clear rdb_bgsave_in_progress when BGSAVE finishes by @vyavdoshenko in #8459
- feat: add auto shrink for OAHTable by @BorysTheDev in #8454
- Update compatible external dependencies by @romange in #8460
- Replace double-conversion with dragonbox for double formatting by @romange in #8461
- refactor: complete remove RedisParser by @BorysTheDev in #8465
- fuzz: pair a crash with its RECORD set by content, not by number by @vyavdoshenko in #8467
- core(lua): allow script which has not written to exit on time budget elapse by @abhijat in #8426
- fix(snapshot): wait for delayed entries taken over by writers before the final flush by @vyavdoshenko in #8457
- chore(deps-dev): bump urllib3 from 2.7.0 to 2.8.0 by @dependabot[bot] in #8455
- fix: HSNW index restoration crash by @BorysTheDev in #8466
- fix(facade): track partial-send progress in SinkReplyBuilder by @romange in #7536
- Report anonymous deployment info with the version check by @romange in #8469
- fix: SlotMigrationStreamer::Cancel() waits for Run finish by @BorysTheDev in #8473
- feat(aof): add aof on-disk format and block builder by @kostasrim in #8439
- feat(aof): add segment writer by @kostasrim in #8456
- fix: WaitUntilLocked should not poll IsLocked on success by @kostasrim in #8480
- refactor: test_replicate_old_master, detach the replica before shutti… by @BorysTheDev in #8481
- feat: Print fiber stacks before pytest timeout teardown by @BorysTheDev in #8482
- server: Add metric for type mem delta by @abhijat in #8434
- feat(aof): durability and basic error handling by @kostasrim in #8464
- server: remove shutdown watchdog by @abhijat in #8490
- chore(helm-chart): update to v2.0.2 by @github-actions[bot] in #8496
- feat(aof): aof streamer, flags, init and simple test by @kostasrim in #8470
- server: Log warning on cancelled snapshot, not error by @abhijat in #8499
- fix(search): drop search indices left unbuilt by a failed load by @vyavdoshenko in #8500
- fix(search): prevent stack overflow on deeply nested queries by @vyavdoshenko in #8492
- fix(test): DeleteExpiredStep should run in fiber context by @kostasrim in #8503
- tests: Make setex task run until after replica connection finishes by @abhijat in #8504
- refactor: improve stream performance by @BorysTheDev in #8507
- refactor: DflyShardReplica::ExecuteTx into JournalApplier by @kostasrim in #8471
- fix(facade): build against OpenSSL 4 by @vyavdoshenko in #8509
- refactor: store tag affixes as plain values by @BorysTheDev in #8511
- refactor: search, add ast access helpers by @BorysTheDev in #8514
- refactor: transfer AST ownership through expression by @BorysTheDev in #8515
- refactor: dispatch AST visits throught virtual nodes by @BorysTheDev in #8518
- Report deployment env, role and finer cloud in version check by @romange in #8498
- fix(qlist): skip dont_compress and rejected nodes in ZSTD dict compression by @romange in #8487
- refactor: move global cmd rendezvous from JournalApplier to MultiShardExecution by @kostasrim in #8526
- chore(ci): allow repeating selected large tests in Heavy Tests by @romange in #8524
- refactor: add lua bench and fix bug by @BorysTheDev in #8517
- perf(tiering): O(1) free page removal in ExternalAllocator by @romange in #8527
- fix(transaction): drain deferred poll after optimistic SingleHopAsync by @miledxz in #8520
- refactor(search): resolve projected fields once per query by @vyavdoshenko in #8519
- chore: remove deprecated ParsedCommand::ReplyWith by @romange in #8534
- feat(metrics): split pipeline_latency_seconds by read/other command type by @romange in #8535
- fix(qlist): keep node indices accurate across merges and erase by @romange in #8488
- fix(search): index a multi-group synonym term under every group token by @vyavdoshenko in #8516
- fix: test_replicate_old_master by @BorysTheDev in #8513
- refactor: simplify MultiShardExecution rendezvous by @kostasrim in #8529
- refactor: raw field access, bounded recursive lua reply conversion by @BorysTheDev in #8536
- fix(search): load the SORTBY value of vector queries apart from the reply fields by @vyavdoshenko in #8540
- refactor: search performance improvement by @BorysTheDev in #8544
- fix(resp): drain V2 parser errors by @glevkovich in #8541
- feat(aof): remove torned aof flows from MultiShardExecution by @kostasrim in #8543
- test(facade): replace the timing-dependent v1 protocol-error test by @vyavdoshenko in #8550
- refactor: added CRTP-generated callbacks for AST nodes by @BorysTheDev in #8546
- settings: Fix claude settings warnings by @abhijat in #8554
- fix(tiering): fix segment queue corruption and release empty segments by @romange in #8528
- refactor: remove IsResultSafe by @BorysTheDev in #8545
- chore(ci): limit loopback MTU to 9000 in regression test workflows by @romange in #8525
- refactor(db_slice): collapse expiry entry points into TryExpire by @romange in #8558
- fix(replica): yield in the stable-sync flow loop so a lagging flow cannot starve its thread by @vyavdoshenko in #8559
- fix(db_slice): queue the tracking invalidation before erasing the entry by @romange in #8563
- fix(resp): preserve V2 control ordering by @glevkovich in #8547
- search: Add alias support by @abhijat in #8556
- refactor(server): keep expired/evicted key counters only per db by @romange in #8562
- refactor(resp): simplify V2 parser drain code by @glevkovich in #8566
- refactor(journal): make DisableFlushGuard restore the flush mode it found by @romange in #8565
- feat(aof): chain reader skeleton by @kostasrim in #8568
- refactor(db_slice): make Del take a PrimeIterator by @romange in #8564
- tests: use v1.25.3 instead of v1.19.2 in the replication compatibility tests by @vyavdoshenko in #8574
- feat: reuse wrapper keys in interpeter by @BorysTheDev in #8561
- fix(server): drop the usec-keyed memory cache from ShouldDenyOnOOM by @vyavdoshenko in #8575
- fix(search): make BM25 scores independent of the shard count by @vyavdoshenko in #8542
- fix(db_slice): treat an expired key as missing regardless of its type by @romange in #8581
- chore(engine_shard): drop redundant continuation reset after a concluding hop by @romange in #8587
- refactor(db_slice): queue expired events in TryExpire instead of returning them by @romange in #8588
- refactor(qlist): rename compression policy setters by @romange in #8537
- chore(server): New error logs for loader by @dranikpg in #8501
- refactor: improve search queries performance by @BorysTheDev in #8592
- refactor(search): order schema fields by declaration, feed indices from one list by @vyavdoshenko in #8569
- fix(search): keep synonyms over FT.ALTER by @vyavdoshenko in #8580
- feat: avoid key slot recalculation by @BorysTheDev in #8597
- fix(server): apply idle timeout to connections that never sent a byte by @shahyash2609 in #8368
- fix(server): write PFMERGE destination only on its own shard by @vyavdoshenko in #8602
- refactor: improve search union op performance by @BorysTheDev in #8600
- feat(facade): enable RESP IoLoopV2 by default by @glevkovich in #8576
- feat(metrics): export V2 pipeline counters by @glevkovich in #8557
- feat(server): implement CLIENT TRACKINGINFO by @miledxz in #8497
- feat(qlist): make the uncompressed edge zone depth configurable by @romange in #8334
- test: Make test_pubsub_slow_subscriber_closed more reliable. by @glevkovich in #8605
- feat(aof): detect torn tail in chain reader by @kostasrim in #8570
- fix(server): Ensure storage for TS read lives long enough by @abhijat in #8539
- chore(server): add single-key transaction micro-benchmark by @romange in #8601
- refactor(transaction): keep blocking wake reservations only in BlockingController by @romange in #8596
- feat: use lua internals to get better performance by @BorysTheDev in #8599
- chore(server): fix compiler and clang-tidy warnings by @romange in #8611
- refactor: remove unused C++ code by @vyavdoshenko in #8613
- fix(blocking): do not suspend while NotifyPending iterates watch tables by @romange in #8593
- perf(db_slice): reduce the overhead of cache-mode bumps by @romange in #8589
- feat(aof): read once and buffer by @kostasrim in #8610
- fix(stream): serve every ready stream to a woken multi-stream read by @romange in #8595
- CI: add tests for CI dashboard generation by @abhijat in #8435
- feat(ci-test-dashboard): add GitHub issues, PRs, assignees by @glevkovich in #8608
- fix(acl): restore ACL categories regressed by #8308 and #8311 by @vyavdoshenko in #8614
- fix(stream): accept empty consumer and group names by @vyavdoshenko in #8631
- fix(server): register key locks of optimistic transactions in cache mode by @vyavdoshenko in #8630
- fix(search): keep synonym group tokens out of user queries by @vyavdoshenko in #8603
- fix(server): Fix omits cause inconsistencies during migrations by @dranikpg in #8619
- fix(stream): reject "" and "-" as explicit stream IDs outside XADD by @vyavdoshenko in #8634
- fix(server): hide HELLO AUTH credentials in logs, MONITOR and SLOWLOG by @vyavdoshenko in #8612
- feat(search): key the schema by alias, allow several attributes on one HASH field by @vyavdoshenko in #8604
- fix(server): Conclude single shard BLMOVE in one hop when data is ava… by @dranikpg in #8638
- fix(tests): make Proxy own accepted sockets so close() cannot leak one by @vyavdoshenko in #8637
- refactor: improve search negate operation by @BorysTheDev in #8639
- perf(sidekiq): map private and public queue to same shard by @kostasrim in #8642
- tests: Adjust time to wait for cooldown by @abhijat in #8590
- feat: add slot stats for several databases by @BorysTheDev in #8643
- chore(server): remove WITH_AWS build branches from snapshot storage by @miledxz in #8626
- feat(aof): error codes in replay chain reader by @kostasrim in #8616
- chore(search): persist and load alias definitions in snapshot by @abhijat in #8624
- feat(search): allow several attributes on one JSON path by @vyavdoshenko in #8651
- fix: SADD return value by @BorysTheDev in #8652
- fix: migration SYNC timeout by @BorysTheDev in #8491
- chore(server): split the transaction benchmark and add an async batched variant by @romange in #8615
- chore(deps-dev): bump aiohttp from 3.14.3 to 3.14.4 by @dependabot[bot] in #8620
- feat(aof): replay and e2e test by @kostasrim in #8484
- fix(transaction): replay dropped polls of blocked transactions by @vyavdoshenko in #8538
- perf(server): speed up inline single-shard transactions by @romange in #8609
- chore(server): hold running_tx_ in DEBUG POPULATE instead of RunSquashedMultiCb by @romange in #8658
- fix(server): hide CONFIG SET values and ACL SETUSER tokens in logs and errors by @vyavdoshenko in #8659
- fix: wait command preempts in atomic section by @kostasrim in #8665
- fix(search): order SORTBY ties by key and rank missing values last by @vyavdoshenko in #8664
- fix(search): remove expired hash field values from search indices by @vyavdoshenko in #8657
- fix(acl): give CLIENT/MEMORY admin subcommands their own ACL categories, check RM keys by @vyavdoshenko in #8627
- Report data size of tiered values in DEBUG OBJHIST by @romange in #8655
- fix(search): build sort_indices.cc against libc++. (macOS fix) by @vyavdoshenko in #8675
- chore(deps): bump certifi from 2026.7.22 to 2026.10.19 by @dependabot[bot] in #8650
- test: replace hard-coded shard keys with named constants by @avy252004 in #8618
- chore(deps): bump setuptools from 84.0.0 to 84.1.0 by @dependabot[bot] in #8676
- feat(search): Make search commands aware of aliases by @abhijat in #8649
- feat(aof): chain reader Repair by @kostasrim in #8666
- refactor(server): simplify WAIT acknowledgement tracking by @romange in #8668
- refactor(acl): expose a pure CheckCommand over an AclRulesView by @romange in #8684
- Cover JSON, streams and sketches in DEBUG OBJHIST by @romange in #8656
- fix(server): don't exit on cloud snapshot storage init failure at runtime by @dranikpg in #8689
- chore(search): Simplify tx concluding by @abhijat in #8691
- chore(server): Use lookup mode enum instead of one named after stats by @abhijat in #8688
- chore(search): Allow alter, drop via index alias by @abhijat in #8683
- refactor(acl): decouple User and UserRegistry from AclFamily's category tables by @romange in #8685
- fix(search): keep FT.SYNUPDATE replayed during a replica full sync by @vyavdoshenko in #8671
- fix(search): shrink the map of kept field values after removals by @vyavdoshenko in #8672
- chore(search): Propagate error if index dropped during search by @abhijat in #8702
- fix(server): make XINFO and JSON.DEBUG keyed so scripts read them through the transaction by @vyavdoshenko in #8648
- fix(server): reply to TIME with bulk strings by @vyavdoshenko in #8712
- feat(aof): manifest file by @kostasrim in #8493
- chore(server): Refactor duplicate code by @abhijat in #8690
- fix(search): keep index definitions with spaces or wide schemas across reloads by @vyavdoshenko in #8696
- fix(acl): fail closed on a broken aclfile, validate hashes, save atomically by @vyavdoshenko in #8681
- feat: add throttling to slot flushes after migration by @BorysTheDev in #8641
- Expose io thread count and max connections per io thread by @romange in #8701
- refactor(acl): simplify ACL rule parsing and serialization by @romange in #8686
- feat(aof): manifest bootstrap, startup and gc by @kostasrim in #8502
- test: disable tiered_storage_test by @BorysTheDev in #8716
- refactor: improve GetSlotInfo performance by @BorysTheDev in #8715
- feat: cancel save op if loading starts by @BorysTheDev in #8505
- refactor(acl): simplify AclFamily connection, ACL file and log handling by @romange in #8687
- feat(ci-dashboard): publish private GCS copy by @glevkovich in #8725
- chore(ci): remove public ci-tests-dashboard publishing by @glevkovich in #8726
- refactor(test): share JSON legacy and modern conformance scenarios by @kostasrim in #8692
- feat(server): listen on :: by default on dual-stack hosts by @oleg-milanov in #8682
- feat: getslotinfo don't print unowned slots by @BorysTheDev in #8722
- fix(tiering): Avoid double counting list node memory in AutoUpdater by @dranikpg in #8732
- fix(s3): Socket pacing + socket marks by @dranikpg in #8719
- fix(acl): rw commands permission check by @kostasrim in #8721
- chore(server): Better name,description for typed memory metric by @abhijat in #8730
- fix(tiering): fix small-bins leak and stash-cancellation on failure by @dranikpg in #8636
- fix(server): Skip forced snapshot serialization for redundant writes with second replica, add support for expire by @dranikpg in #8112
- feat(tiering): Tiered bin-bucket defragmentation by @dranikpg in #8007
- fix(ci-dashboard): add private repo links by @glevkovich in #8640
- feat(aof): segment rotation and spare by @kostasrim in #8508
- chore(tests): Apply more checks in test multi pubsub by @abhijat in #8728
- feat: allow listpack usage during borrow mode for HNSW by @BorysTheDev in #8733
- chore(search): Only collect vector range nodes once by @abhijat in #8736
- feat: flush slots for all databases by @BorysTheDev in #8669
- refactor: MRMW mutex for HNSW index by @BorysTheDev in #8737
- chore: Switch license to Dragonfly Source Available License (DSAL) by @romange in #8739
- fix(tiering): Better tracking of device usage by @dranikpg in #8122
- feat(search): store INDEXMISSING, INDEXEMPTY and UNF, align FT.INFO by @vyavdoshenko in #8720
- feat(metrics): export snapshot and replica disconnect counters by @romange in #8740
Huge thanks to all the contributors! ❤️
New Contributors
- @Tyagiquamar made their first contribution in #8306
- @szepeviktor made their first contribution in #8358
- @ZainnQureshii made their first contribution in #8383
- @miledxz made their first contribution in #8520
- @oleg-milanov made their first contribution in #8682
Full Changelog: v2.0.0...v2.1