96

1

Dragonfly

Dragonfly 是一种现代内存数据存储,与 Redis 和 Memcached API 完全兼容。Dragonfly 在多线程、无共享架构之上实现了新颖的算法和数据结构。因此,与 Redis 相比,Dragonfly 的性能达到了 x25,并且在单个实例上支持数百万 QPS。

蜻蜓

ci-tests 推特网址

快速入门| discord| GitHub 讨论| GitHub 问题| 贡献

可能是宇宙中最快的内存存储!

Dragonfly 是一种现代内存数据存储,与 Redis 和 Memcached API 完全兼容。Dragonfly 在多线程、无共享架构之上实现了新颖的算法和数据结构。因此,与 Redis 相比,Dragonfly 的性能达到了 x25,并且在单个实例上支持数百万 QPS。

Dragonfly 的核心特性使其成为经济高效、高性能且易于使用的 Redis 替代品。

基准

与 Redis 相比,Dragonfly 在 c6gn.16xlarge 上的 QPS 超过了 380 万倍,吞吐量增加了 25 倍。

Dragonfly 在其峰值吞吐量时的第 99 个延迟百分位:

操作 r6g c6gn c7g
set 0.8ms 1ms 1ms
get 0.9ms 0.9ms 0.8ms
setex 0.9ms 1.1ms 1.3ms

所有基准测试都是使用 memtier_benchmark (见下文)根据服务器类型和实例类型调整的线程数执行的。memtier在单独的 c6gn.16xlarge 机器上运行。对于 setex 基准,我们使用了 500 的到期范围,因此它可以在测试结束时存活下来。

memtier_benchmark --ratio ... -t <threads> -c 30 -n 200000 --distinct-client-seed -d 256 \
     --expiry-range=...

在流水线模式下运行时 --pipeline=30,Dragonfly的 SET操作达到10M qps ,GET 操作达到 15M qps

Memcached / Dragonfly

c6gn.16xlarge我们在 AWS 上的实例上比较了 memcached 和 Dragonfly 。正如您在下面看到的那样,就吞吐量而言,Dragonfly 在写入和读取工作负载方面都在 memcached 中占主导地位,并且延迟相当。对于写入工作负载,由于memcached 中写入路径的争用,Dragonfly 也有更好的延迟。

设置基准

服务器 QPS(千qps) 延迟 99% 99.9%
Dragonfly 🟩3844 🟩0.9ms 🟩2.4ms
Memcached 806 1.6ms 3.2ms

获取基准

服务器 QPS(千qps) 延迟 99% 99.9%
Dragonfly 🟩3717 1ms 2.4ms
Memcached 2100 🟩0.34ms 🟩0.6ms

Memcached 在读取基准测试中表现出较低的延迟,但吞吐量也较低。

内存效率

debug populate 5000000 key 1024在下面的测试中,我们使用命令向 Dragonfly 和 Redis 填充了大约 5GB 的数据。然后我们开始发送更新流量 memtier并使用“bgsave”命令启动快照。下图清楚地展示了两台服务器在内存效率方面的表现。

在空闲状态下,Dragonfly 的内存效率比 Redis 高 30%。它在快照阶段也没有显示任何可见的内存增加。同时,与 Dragonfly 相比,Redis 在峰值时达到了几乎 3 倍的内存增长。Dragonfly 完成快照的速度也快得多,就在它开始几秒钟后。有关 Dragonfly 内存效率的更多信息,请参阅dashtable doc

运行服务器

Dragonfly 在 linux 上运行。我们建议在 linux 5.11 或更高版本上运行它,但您也可以在旧内核上运行 Dragonfly。

使用Docker:

docker run --network=host --ulimit memlock=-1 docker.dragonflydb.io/dragonflydb/dragonfly

redis-cli PING  # redis-cli can be installed with "apt install -y redis-tools"

您需要 --ulimit memlock=-1,因为一些 Linux 发行版将容器的默认 memlock 限制配置为 64m,而 Dragonfly 需要更多。

发布

我们维护x86 和 arm64 架构的二进制版本。您需要安装 libunwind8lib 才能运行二进制文件。

从源头构建

您需要安装依赖项才能在 Ubuntu 20.04 或更高版本上构建:

git clone --recursive https://github.com/dragonflydb/dragonfly && cd dragonfly

# to install dependencies
sudo apt install ninja-build libunwind-dev libboost-fiber-dev libssl-dev \
     autoconf-archive libtool cmake g++

# Configure the build
./helio/blaze.sh -release

# Build
cd build-opt && ninja dragonfly

# Run
./dragonfly --alsologtostderr

配置

在适用的情况下,Dragonfly 支持常见的 redis 参数。例如,您可以运行:dragonfly --requirepass=foo --bind localhost.

Dragonfly 目前支持以下 Redis 特定参数:

  • portredis连接端口,默认:6379
  • bindlocalhost 仅允许 locahost 连接 Public IP ADDRESS 以允许连接到该 IP地址(也来自外部)
  • requirepassAUTH认证密码,默认:""
  • maxmemory限制数据库使用的最大内存(以字节为单位)。0 - 意味着程序将自动确定其最大内存使用量。默认值:0
  • dir- 默认情况下,dragonfly docker 使用 /data文件夹进行快照。CLI 使用:"" 您可以使用 -vdocker 选项将其映射到您的主机文件夹。
  • dbfilename保存/加载数据库的文件名。默认值:“转储”;

此外,它还有 Dragonfly 特定的参数选项:

  • memcache_port - 在此端口上启用 memcached 兼容 API。默认禁用。
  • keys_output_limit``keys-命令中返回的最大键数。默认为 8192。 keys是一个危险的命令。我们截断它的结果以避免在获取太多键时导致内存爆炸。
  • dbnum- 支持的数据库的最大数量 select
  • cache_mode- 请参阅下面的缓存部分。
  • hz- 密钥到期评估频率。默认值为 1000。较低频率在空闲时使用较少的 cpu,但会降低键逐出的精度。
  • save_schedule- UTC 时间的全局规范以保存与 HH:MM(24 小时时间)匹配的快照。默认: ””
  • keys_output_limit- keys 命令输出的最大键数。默认值:8192

有关日志管理或 tls 支持等更多选项,请运行 dragonfly --help.

路线图和状态

目前 Dragonfly 支持约 130 个 Redis 命令和除 cas. 我们几乎与 Redis 2.8 API 相提并论。我们的第一个里程碑将是稳定基本功能并与 Redis 2.8 和 Memcached API 实现 API 对等。如果您看到您需要的命令尚未实现,请打开一个问题。

下一个里程碑将是实现 H/A redis -> dragonflydragonfly<->dragonfly复制。

对于Dragonfly 原生复制,我们计划设计一种分布式日志格式,在复制时支持更高数量级的速度。

在复制和故障转移功能之后,我们将继续使用 API 3、4 和 5 中的其他 Redis 命令。

有关 Dragonfly 的当前状态,请参阅API 就绪文档

里程碑 - H/A

实施领导者/跟随者复制(PSYNC/REPLICAOF/...)。

里程碑 - “成熟度”

API 3、4、5 没有集群支持,没有模块,也没有内存自省命令。也没有地理命令,不支持键空间通知,没有流。可能是设计配置支持。总体而言 - 几十个命令...可能实现集群 API 装饰器以允许集群配置的客户端连接到单个实例。

下一个里程碑将在此过程中确定。

设计决策

新颖的缓存设计

Dragonfly 有一个统一的自适应缓存算法,非常简单且内存高效。--cache_mode=true您可以通过传递标志来启用缓存模式。一旦启用此模式,Dragonfly 将逐出将来最不可能偶然发现的项目,但仅在接近最大内存限制时。

具有相对准确性的到期期限

有效期限制为约 4 年。此外,对于超过 134217727 毫秒(大约 37 小时)的截止日期,毫秒精度的到期期限(PEXPIRE/PSETEX 等)将四舍五入到最接近 的秒数。这种舍入的误差小于 0.001%,我希望这对于大范围是可以接受的。如果它破坏了您的用例 - 与我交谈或打开一个问题并解释您的案例。

有关此实现与 Redis 实现之间的更详细区别,请参见此处

原生 Http 控制台和 Prometheus 兼容指标

默认情况下,Dragonfly 允许通过其主 TCP 端口 (6379) 进行 http 访问。没错,你可以通过 Redis 协议和 HTTP 协议连接到 Dragonfly——服务器在连接发起时会自动识别协议。继续尝试使用您的浏览器。目前它没有太多信息,但未来我们计划添加有用的调试和管理信息。如果你去 :6379/metricsurl 你会看到一些 prometheus 兼容的指标。

Prometheus 导出的指标与 Grafana 仪表板兼容,请参见此处

重要的!Http 控制台旨在在安全网络中访问。如果将 Dragonfly 的 TCP 端口暴露在外部,建议使用 --http_admin_console=false或禁用控制台 --nohttp_admin_console

背景

Dragonfly 最初是一个实验,看看如果在 2022 年设计的内存数据存储会是什么样子。根据我们作为内存存储用户和为云公司工作的工程师的经验教训,我们知道我们需要保留 Dragonfly 的两个关键属性:a)为其所有操作提供原子性保证,以及 b)在非常高的吞吐量下保证低的亚毫秒延迟。

我们的第一个挑战是如何使用当今公共云中可用的服务器充分利用 CPU、内存和 i/o 资源。为了解决这个问题,我们使用了无共享架构,它允许我们在线程之间划分内存存储的键空间,以便每个线程管理自己的字典数据切片。我们称这些切片 - 碎片。为无共享架构提供线程和 I/O 管理的库在此处开源。

为了为多键操作提供原子性保证,我们使用了最近学术研究的进展。我们选择了论文“VLL: a lock manager redesign for main memory database systems”来开发 Dragonfly 的事务框架。选择 shared-nothing 架构和 VLL 使我们能够在不使用互斥锁或自旋锁的情况下组合原子多键操作。这是我们 PoC 的一个重要里程碑,其性能在其他商业和开源解决方案中脱颖而出。

我们的第二个挑战是为新商店设计更高效的数据结构。为了实现这个目标,我们的核心哈希表结构基于论文“Dash: Scalable Hashing on Persistent Memory”。论文本身以持久内存域为中心,与主内存存储没有直接关系。尽管如此,它非常适用于我们的问题。它提出了一种哈希表设计,使我们能够维护 Redis 字典中存在的两个特殊属性:a)它在数据存储增长期间的增量哈希能力 b)它使用无状态扫描操作在更改下遍历字典的能力。除了这两个属性之外,Dash 在 CPU 和内存方面的效率要高得多。通过利用 Dash 的设计,我们能够通过以下功能进一步创新:

  • TTL 记录的有效记录到期。
  • 一种新颖的缓存驱逐算法,它实现了比其他缓存策略(如 LRU 和 LFU)更高的命中率,且 内存开销为零
  • 一种新颖的无分叉快照算法。

在我们为 Dragonfly 打好基础并对其性能感到满意之后,我们继续实现 Redis 和 Memcached 功能。到目前为止,我们已经实现了大约 130 个 Redis 命令(相当于 v2.8)和 13 个 Memcached 命令。

最后, 我们的使命是为利用最新硬件进步的云工作负载构建一个设计精良、超快、经济高效的内存数据存储。我们打算解决当前解决方案的痛点,同时保留其产品 API 和主张。