在继续之前,请考虑给我们一个 GitHub star️。谢谢你!
其他语言: 简体中文 日本语 한국어
网站 • 文档 • 快速入门 • 社区不和谐 • Dragonfly 论坛 • 加入 Dragonfly 社区
GitHub 讨论 • GitHub 问题 • 贡献 • Dragonfly Cloud
Dragonfly 是专为现代应用程序工作负载构建的内存数据存储。
Dragonfly 与 Redis 和 Memcached API 完全兼容,无需更改代码即可采用。与传统的内存数据存储相比,Dragonfly 的吞吐量提高了 25 倍,缓存命中率更高,尾部延迟更低,并且对于相同大小的工作负载,运行资源最多可减少 80%。
我们首先在m5.large
实例上将 Dragonfly 与 Redis 进行比较,m5.large 实例由于其单线程架构而通常用于运行 Redis。基准测试程序使用memtier_benchmark -c 20 --test-time 100 -t 4 -d 256 --distinct-client-seed
从同一可用区中的另一个负载测试实例 (c5n) 运行
Dragonfly 显示了类似的性能:
--ratio 1:0
):雷迪斯 | DF |
---|---|
QPS:159K,P99.9:1.16ms,P99:0.82ms | QPS:173K,P99.9:1.26ms,P99:0.9ms |
--ratio 0:1
):雷迪斯 | DF |
---|---|
QPS:194K,P99.9:0.8ms,P99:0.65ms | QPS:191K,P99.9:0.95ms,P99:0.8ms |
上面的基准测试表明,DF 内部允许垂直扩展的算法层在单线程运行时不会造成太大损失。
然而,如果我们采用更强一点的实例(m5.xlarge),DF 和 Redis 之间的差距就会开始扩大。 ( memtier_benchmark -c 20 --test-time 100 -t 6 -d 256 --distinct-client-seed
):
--ratio 1:0
):雷迪斯 | DF |
---|---|
QPS:190K,P99.9:2.45ms,P99:0.97ms | QPS:279K,P99.9:1.95ms,P99:1.48ms |
--ratio 0:1
):雷迪斯 | DF |
---|---|
QPS:220K,P99.9:0.98ms,P99:0.8ms | QPS:305K,P99.9:1.03ms,P99:0.87ms |
Dragonfly 吞吐能力随着实例规模不断增长,而单线程 Redis 在 CPU 上遇到瓶颈,在性能方面达到局部最大值。
如果我们在网络能力最强的实例 c6gn.16xlarge 上比较 Dragonfly 和 Redis,则与 Redis 单进程相比,Dragonfly 的吞吐量提高了 25 倍,超过 3.8M QPS。
Dragonfly 在峰值吞吐量下的第 99 个百分位数延迟指标:
操作 | 6g | 6gn | 7g |
---|---|---|---|
放 | 0.8毫秒 | 1毫秒 | 1毫秒 |
得到 | 0.9毫秒 | 0.9毫秒 | 0.8毫秒 |
塞泰克斯 | 0.9毫秒 | 1.1毫秒 | 1.3毫秒 |
所有基准测试均使用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 。
我们在 AWS 上的 c6gn.16xlarge 实例上将 Dragonfly 与 Memcached 进行了比较。
在延迟相当的情况下,Dragonfly 吞吐量在写入和读取工作负载方面均优于 Memcached 吞吐量。由于 Memcached 中写入路径上的争用,Dragonfly 在写入工作负载中表现出更好的延迟。
服务器 | QPS(千qps) | 延迟99% | 99.9% |
---|---|---|---|
蜻蜓 | ? 3844 | ? 0.9毫秒 | ? 2.4毫秒 |
内存缓存 | 806 | 1.6毫秒 | 3.2毫秒 |
服务器 | QPS(千qps) | 延迟99% | 99.9% |
---|---|---|---|
蜻蜓 | ? 3717 | 1毫秒 | 2.4毫秒 |
内存缓存 | 2100 | ? 0.34毫秒 | ? 0.6毫秒 |
Memcached 在读取基准测试中表现出较低的延迟,但吞吐量也较低。
为了测试内存效率,我们使用debug populate 5000000 key 1024
命令向 Dragonfly 和 Redis 填充了约 5GB 的数据,使用memtier
发送更新流量,并使用bgsave
命令启动快照。
该图展示了每台服务器在内存效率方面的表现。
Dragonfly 在空闲状态下的内存效率比 Redis 高 30%,并且在快照阶段没有出现任何明显的内存使用增加。在高峰期,Redis 内存使用量增加到 Dragonfly 的近 3 倍。
蜻蜓更快地完成了快照,几秒钟之内。
有关 Dragonfly 内存效率的更多信息,请参阅我们的 Dashtable 文档。
Dragonfly 在适用的情况下支持常见的 Redis 参数。例如,您可以运行: dragonfly --requirepass=foo --bind localhost
。
Dragonfly 目前支持以下 Redis 特定参数:
port
:Redis 连接端口( default: 6379
)。bind
:使用localhost
仅允许本地主机连接或公共 IP 地址以允许连接到该 IP地址(即也可以从外部)。使用0.0.0.0
允许所有 IPv4。requirepass
:AUTH 身份验证的密码( default: ""
)。maxmemory
:数据库使用的最大内存(以人类可读字节为单位)的限制( default: 0
)。 maxmemory
值为0
意味着程序将自动确定其最大内存使用量。dir
:Dragonfly Docker 默认使用/data
文件夹进行快照,CLI 使用""
。您可以使用-v
Docker 选项将其映射到主机文件夹。dbfilename
:保存和加载数据库的文件名( default: dump
)。还有一些特定于 Dragonfly 的参数:
memcached_port
:启用 Memcached 兼容 API 的端口( default: disabled
)。
keys_output_limit
: keys
命令中返回的键的最大数量( default: 8192
)。请注意, keys
是一个危险的命令。我们截断其结果以避免在获取太多键时内存使用激增。
dbnum
: select
支持的最大数据库数。
cache_mode
:请参阅下面新颖的缓存设计部分。
hz
:密钥过期评估频率( default: 100
)。较低的频率在空闲时使用较少的 CPU,但代价是驱逐速度较慢。
snapshot_cron
:自动备份快照的 Cron 计划表达式,使用标准 cron 语法,粒度为分钟( default: ""
)。下面是一些 cron 计划表达式示例,请随时在我们的文档中阅读有关此参数的更多信息。
Cron 计划表达式 | 描述 |
---|---|
* * * * * | 每分钟 |
*/5 * * * * | 每五分钟一次 |
5 */2 * * * | 每 2 小时 5 分 |
0 0 * * * | 每天 00:00(午夜) |
0 6 * * 1-5 | 周一至周五 06:00(黎明) |
primary_port_http_enabled
:如果为true
( default: true
),则允许访问主 TCP 端口上的 HTTP 控制台。
admin_port
:在分配的端口上启用对控制台的管理员访问( default: disabled
)。同时支持 HTTP 和 RESP 协议。
admin_bind
:将管理控制台 TCP 连接绑定到给定地址( default: any
)。同时支持 HTTP 和 RESP 协议。
admin_nopass
:启用对分配端口上控制台的开放管理访问,无需身份验证令牌( default: false
)。同时支持 HTTP 和 RESP 协议。
cluster_mode
:支持集群模式( default: ""
)。目前仅支持emulated
.
cluster_announce_ip
:集群命令向客户端宣布的 IP。
announce_port
:集群命令向客户端和复制主机宣布的端口。
./dragonfly-x86_64 --logtostderr --requirepass=youshallnotpass --cache_mode=true -dbnum 1 --bind localhost --port 6379 --maxmemory=12gb --keys_output_limit=12288 --dbfilename dump.rdb
还可以通过以下方式提供参数:
--flagfile <filename>
:文件应每行列出一个标志,并用等号代替键值标志的空格。标志值不需要引号。DFLY_x
,其中x
是标志的确切名称,区分大小写。如需日志管理或 TLS 支持等更多选项,请运行dragonfly --help
。
Dragonfly 目前支持约 185 个 Redis 命令以及除cas
之外的所有 Memcached 命令。几乎与 Redis 5 API 一样,Dragonfly 的下一个里程碑将是稳定基本功能并实现复制 API。如果您需要的命令尚未实现,请提出问题。
对于 Dragonfly 原生复制,我们正在设计一种分布式日志格式,它将支持更高数量级的速度。
在复制功能之后,我们将继续为 Redis 版本 3-6 API 添加缺失的命令。
请参阅我们的命令参考以了解 Dragonfly 当前支持的命令。
Dragonfly 具有单一、统一、自适应的缓存算法,该算法简单且内存高效。
您可以通过传递--cache_mode=true
标志来启用缓存模式。一旦启用此模式,蜻蜓将逐出将来最不可能偶然发现的项目,但仅限于接近maxmemory
限制时。
有效期范围限制为 ~8 年。
对于大于 2^28ms 的截止日期,具有毫秒精度的过期截止日期(PEXPIRE、PSETEX 等)四舍五入到最接近的秒,其误差小于 0.001%,对于大范围应该是可以接受的。如果这不适合您的用例,请联系或提出一个问题来解释您的案例。
有关 Dragonfly 到期期限和 Redis 实现之间的更多详细差异,请参阅此处。
默认情况下,Dragonfly 允许通过其主 TCP 端口 (6379) 进行 HTTP 访问。没错,您可以通过 Redis 协议和 HTTP 协议连接到 Dragonfly — 服务器在连接启动期间会自动识别该协议。继续使用您的浏览器尝试一下。 HTTP 访问目前没有太多信息,但将来会包含有用的调试和管理信息。
访问 URL :6379/metrics
查看 Prometheus 兼容的指标。
Prometheus 导出的指标与 Grafana 仪表板兼容,请参阅此处。
重要的! HTTP 控制台应在安全网络内访问。如果您将 Dragonfly 的 TCP 端口暴露在外部,我们建议您使用--http_admin_console=false
或--nohttp_admin_console
禁用控制台。
Dragonfly 最初是一个实验,旨在了解内存数据存储在 2022 年设计时会是什么样子。根据我们作为内存存储用户和云公司工程师的经验教训,我们知道我们需要保留两个Dragonfly 的关键属性:保证所有操作的原子性,以及在非常高的吞吐量下实现低亚毫秒级延迟。
我们的第一个挑战是如何使用当今公共云中可用的服务器充分利用 CPU、内存和 I/O 资源。为了解决这个问题,我们使用无共享架构,它允许我们在线程之间划分内存存储的键空间,以便每个线程都可以管理自己的字典数据片。我们将这些切片称为“碎片”。为无共享架构提供线程和 I/O 管理的库在这里是开源的。
为了为多键操作提供原子性保证,我们利用了最新学术研究的进展。我们选择了论文“VLL:主内存数据库系统的锁管理器重新设计”来开发 Dragonfly 的事务框架。无共享架构和 VLL 的选择使我们能够在不使用互斥锁或自旋锁的情况下组合原子多键操作。是我们的 PoC 的一个重要里程碑,其性能在其他商业和开源解决方案中脱颖而出。
我们的第二个挑战是为新商店设计更高效的数据结构。为了实现这一目标,我们的核心哈希表结构基于论文“Dash:持久内存上的可扩展哈希”。这篇论文本身以持久内存领域为中心,与主内存存储没有直接关系,但它仍然最适用于我们的问题。论文中提出的哈希表设计使我们能够维护 Redis 字典中存在的两个特殊属性:数据存储增长期间的增量哈希能力以及使用无状态扫描操作在更改时遍历字典的能力。除了这两个属性之外,Dash 在 CPU 和内存使用方面也更加高效。通过利用 Dash 的设计,我们能够通过以下功能进一步创新:
一旦我们为 Dragonfly 奠定了基础并且对其性能感到满意,我们就继续实现 Redis 和 Memcached 功能。迄今为止,我们已经实现了约 185 个 Redis 命令(大致相当于 Redis 5.0 API)和 13 个 Memcached 命令。
最后,
我们的使命是为云工作负载构建一个设计精良、超快速、经济高效的内存数据存储,利用最新的硬件进步。我们打算解决当前解决方案的痛点,同时保留其产品 API 和主张。