Redis 6多线程I/O vs Elasticache vs KeyDB

本文对比了KeyDB、Elasticache和Redis6的单节点性能,重点在于多线程I/O的影响。KeyDB在多线程处理上优于Redis6和Elasticache,提供更高的吞吐量和更低的时延。测试使用了Memtier和YCSB工具,结果显示KeyDB在各种负载下表现出最佳性能。此外,文章还讨论了三者之间的关键差异,包括开源特性、服务管理和设计哲学。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

翻译自:https://docs.keydb.dev/blog/2020/04/15/blog-post/

随着Redis 6多线程I/O的出现,该博客比较了Elasticache,KeyDB和Redis 6.0的单节点性能。我们将研究不同负载和不同工具下的吞吐量和时延。

背景介绍

KeyDB大约是在一年前作为Redis的分支引入的,通过多线程实现显著的性能提升。不久之后,亚马逊宣布了含有增强io处理Redis内核的Elasticache。Redis最近也发布了支持多线程io的6.0版。与Redis6和Elasticache不同,KeyDB在多个方面进行多线程处理,包括将event loop放在多个线程上,network IO和query parsing能并发执行。

因此,有3家公司提供了3种产品,它们彼此兼容,并且基于开源Redis:Elasticache是优化的​​Redis服务;RedisLabs和Redis提供了核心代码和商用软件,而KeyDB是更快速、拥有更多新技术的开源Redis的超集。该博客聚焦性能对比,但末尾有一节也概述了其他一些关键差异。

性能测试

我们使用Memtier和YCSB进行测试。Memtier是RedisLabs开发的一个性能测试工具,YCSB是雅虎用来比较众多热数据库的性能测试工具。我们没有使用KeyDB自己开发的性能测试工具,从而避免出现主观偏差,同时也是因为本次测试的吞吐量限制。本次测试的结果都可以通过AWS重现。该博客末尾有一节详细介绍了如何重现测试以及需要考虑的因素,从而避免出现瓶颈和测试差异。

Memtier的吞吐量测试

Memtier是RedisLabs设计的用于对Redis进行负载测试的性能测试工具。它擅长产生高吞吐量,并且还与KeyDB和Elasticache兼容。以下测试在几种不同大小的AWS r5实例上运行。

我们测试8个线程的KeyDB和8个IO线程的Redis,发现4个IO线程以上的Redis在性能上看不到进一步的提高。但是我们尝试了不同的组合,并使用线程数显示最佳吞吐量。

Elasticache是​​由AWS管理的一项服务,因此我们留给AWS来优化其配置。

所有测试均在同一AZ内的private IP上进行,并取数次测试的平均值。此博客的末尾可以看到有关重现这些性能测试的详细信息。

下图显示了QPS测试数据:

 

如图所见,随着更多cpu的使用,KeyDB显示出与Redis和Elasticache相比显著的QPS提高。即使Redis6使用多线程IO,它仍然落后于KeyDB和Elasticache,垂直扩展能力较低。

在r5.large实例上,Elasticache的性能略高,但是我们注意到Elasticache在r5.xlarge上的性能反而下降了(在不同时间进行了多次测试)。我们不确定背后的原因。

用memtier测出的时延都在几毫秒,因为它是计算机/节点在最大吞吐量时测得,不能代表平均负载甚至是高负载时的时延。为了在测试时延方面进行良好的相对比较,我们使用YCSB在给定的负载和吞吐量下测试时延。

使用YCSB进行吞吐量测试

YCSB是Yahoo的性能测试工具,与当今许多流行的数据库兼容。该工具有很大的灵活性,可以使用不同的“工作负载”来表示更多实际的加载场景。

以下测试着眼于运行几种不同工作负载时的最大吞吐量:

负载A:大量更新(读/写50:50)

负载B:大量读取(95:5读/写)

负载C:只读

负载D:读取最新记录-新增记录最热

负载E:短程,比如对话

负载F:读-修改-写

下表显示了预加载以上负载数据集的最大QPS。“加载操作/秒”来自加载负载“ a”数据集。根据YCSB建议,此数据集用于所有负载测试

 

通过YCSB的测试数据,KeyDB在每个测试的负载下都有最高的吞吐量。Elasticache位居第二,其次是Redis6。可以注意到,Redis6仍然比没有多线程IO的Redis5要快。

YCSB的时延测试

YCSB是衡量时延的出色工具。它可以指定目标吞吐量,并测量与该流量相关的延迟。在不同的负载下,它可以很好地了解数据库在不同流量和不同负载下的性能。在选择要与实例一起使用的计算机大小时,它也有很大帮助。

下面的测试针对的是读/写为50/5的“负载a”和大部分为写的“负载b”。UPDATE和READ的有相似的时延曲线。在运行内存数据库时,通常会使用这些负载。时延测量单位为微秒,数值越低越好

 

上面显示的曲线表明,随着实例接近其最大吞吐量,时延会显著增加。与Redis6相比,KeyDB可以处理的吞吐量要大得多。与Elasticache相比,KeyDB可以处理的吞吐量也更多,因此能够在较高负载下保持较低的时延。

当处于中等流量时,KeyDB,Elasticache和Redis 6的时延都相似。达到更高的负载时才出现差异。当运行负载a / c / d / e / f时,上述曲线看起来非常相似,但是幅度略有不同。

“负载e”的响应最不同,因此我们还将在下面显示其时延曲线。YCSB所描述的负载e对于“线程对话,每次扫描都是针对指定线程中的消息”而言可能很常见。

如图所见,曲线的趋势类似,但是由于负载的性质,数据集与其他数据集不同。KeyDB仍然保持较低的时延。

火焰图

对于那些喜欢火焰图并寻找某种视觉表示的人,我们在Redis5,Redis6和KeyDB之间运行了一些FlameGraphs。我们无权访问Elasticache服务器,因此无法为其运行它们。这些FlameGraphs在性能测试期间运行。

memtier-redis5memtier-redis6memtier-keydbycsb-redis5ycsb-redis6ycsb-keydb

KeyDBElasticacheRedis有哪些不同?

每种产品都是从开源Redis开始构建的,并保持与Redis的完全兼容性。但是每种产品的发展方向都略有不同。因此,除了性能之外,这些产品之间还有哪些其他主要区别?

KeyDB是开源的,专注于内存效率,高吞吐量和性能,并在不久的将来还要进行一些重大改进。这使KeyDB能够提供不被开源Redis接受的一部分功能。KeyDB专注于简化用户体验,比如active replication和multi-master。KeyDB还有其他命令,比如subkey EXPIRES和CRON

KeyDB Pro版本还包括MVCC和FLASH的支持等

Elasticache提供自己的Redis分支作为优化的Redis服,但只能通过AWS提供的付费服务获得,因此无法on Prem使用。由于Redis的实例管理完全由AWS托管,因此Redis副本和集群只能由AWS管理,用户的高级决策有限,配置参数也不受自己的控制。

Redis是开源的,并且使用时间最长。与KeyDB不同,它采用了一切从简的设计和实现理念。

RedisLabs是Redis的付费版本,它提供完全托管的解决方案以及专有模块。RedisLabs提供付费版本的FLASH支持,并且可以on Prem的形式托管,但是价格可能会很高。

多线程差异

尽管Redis6现在具有多线程IO,Elasticache使用其增强的网络IO线程,但KeyDB的工作原理是在多个线程上运行正常的Redis event loop。Network IO和query parsing是同时进行的。每个连接在accept()上分配一个线程。多线程对核心哈希表的访问通过spinlock来保护。因为哈希表的访问非常快,所以spinlock的争用概率比较低。事务在EXEC命令执行的时间内保持锁定。Redis module与GIL协同工作,仅在所有线程都暂停时才获取。这保持了Redis module所期望的原子性保证。

重现性能测试

我们无权通过客户端config get <>来查看Elasticache的配置。但是从设置的角度来看,elasticache依靠副本进行数据备份,并提供诸如“daily backup”之类的功能作为s3的rdb选项。通过查看info persistence, 在性能测试期间没有进行后台保存。为了公平起见,在Redis和KeyDB的性能测试中也禁用了后台保存。

为了优化Redis并遵循其建议,测试中还更新了以下linux参数:

/ proc / sys / net / core / somaxconn更改为65536

echo never > / sys / kernel / mm / transparent_hugepage / enabled

sysctl vm.overcommit_memory = 1

避免瓶颈

  1. 由于KeyDB的多线程和性能提升,需要比运行一个KeyDB实例大得多的性能测试计算机。需要32核m5.8xlarge才能通过memtier产生足够的吞吐量。这支持多达16个线程KeyDB实例的吞吐量(medium到4xlarge)
  2. 使用Memtier时,请运行32个线程。
  3. 在同一网络上运行测试,确保实例位于同一AZ,比如us-east-2a中的两个实例
  4. 使用private IP运行。如果使用AWS的公共IP,则与网络相关的变化可能更多
  5. 当心通过代理或VPC运行。使用此类方法,防火墙和其他附加层时,可能很难确定到底是什么瓶颈。最好在简单的环境(在同一vpc内)进行性能测试,然后再添加各层以确保在最优环境下测试。
  6. 在比较不同的机器实例性能时,确保它们位于相同的AZ中,并尽可能在相近时段进行测试。一天中的网络吞吐量确实会发生变化,所以彼此之间时段接近的测试可以提供最具代表性的相对比较。
  7. KeyDB是多线程的,确保在运行时指定多个线程

KeyDB

所有的测试都是通过以下参数执行的:

$ keydb-server --protected-mode no --server-threads 7 --server-thread-affinity true --save “”

请记住,安全组不会公开端口6379,而只会向测试实例公开。可以使用--requirepass mypassword参数添加访问密码。

Redis

使用Redis6需要用新的io-threads参数。可以根据需要设置IO线程数。4-8之间的最佳结果,但是在设置时请记住计算机上可用的CPU数量

$ redis-server --protected-mode no --io-threads [#threads] --save “”

Elasticache

可以从这开始:https : //aws.amazon.com/elasticache/。转到“create cluster”并记住以下参数:

  1. 选择“ Redis”,并确保取消选择“cluster mode enabled”
  2. 设置实例名称和版本5.0.6(最新)的兼容性
  3. 选择计算机大小/类型并将副本设置为0
  4. 选择与性能测试机器相同的AZ
  5. 一旦创建了机器,就可以使用“primary endpoint”作为主机地址进行连接

Memtier

确保至少在m5.8xlarge上运行。安装memtier并从加载数据集开始

$ memtier_benchmark -s [ip address] –hide-histogram –threads=32 –ratio=1:0

然后使用以下命令运行正常测试:

$ memtier_benchmark -s [ip address] –hide-histogram –threads=32

可以使用其他参数和选项。有关详细信息,请参见--help选项。

YCSB

有关安装YCSB,负载,加载,运行等详细信息,请参阅github存储库Wiki,以下是用于性能测试的基本命令。

首先加载数据,然后执行测试。默认设置很小,因此需要为测试指定记录数1000万和操作数1000万。

如果性能测试客户端太少的话,可能会对网络延迟比较敏感。为了获得相当一致的结果和最大吞吐量,建议使用350个客户端线程。结果将输出到指定的文件中。

本博客中执行的所有YCSB测试均在r5.4xlarge实例(测试机)上完成,性能测试计算机为m5.8xlarge。

<think>好的,我现在需要回答用户关于Redis的I/O多路复用技术的问题。首先,我得回忆一下Redis的基础知识,特别是它的网络模型部分。 用户的问题是关于Redis的I/O多路复用,所以我应该先解释这个概念。I/O多路复用是指使用一个机制来同时监控多个文件描述符(比如套接字),当其中任何一个描述符就绪(可读或可写)时,程序就能得到通知。这样可以避免阻塞在单个I/O操作上,提高并发处理能力。 接下来,我需要说明Redis为什么选择使用I/O多路复用。可能的原因包括高性能、单线程模型的优势,以及如何通过多路复用实现高并发。需要提到Redis主要采用单线程模型,避免了多线程的上下文切换开销,而I/O多路复用允许这个单线程高效处理多个客户端连接。 然后,应该介绍Redis在不同操作系统上使用的多路复用技术。比如,Linux下使用epoll,BSD/MacOS使用kqueue,而较旧系统可能使用select或poll。需要解释这些技术之间的区别,为什么epoll比select更高效,比如epoll的事件驱动方式不需要每次遍历所有文件描述符。 可能需要给出一个简单的示例代码,说明如何使用Python中的select模块实现多路复用,但用户要求只能用Python代码,所以需要调整示例。比如,展示一个使用select处理多个客户端连接的服务器端代码片段,虽然这可能不是Redis内部的实现,但可以帮助用户理解概念。 另外,要强调I/O多路复用如何与Redis的事件循环结合,事件处理器处理就绪的事件,如读或写操作。Redis的事件驱动架构使得它能够高效处理大量并发连接,而不会因为阻塞在某个连接上。 还要注意用户可能的疑问,比如为什么Redis选择单线程而不是多线程,这里需要解释单线程避免了锁的开销和竞争条件,简化了设计,同时I/O多路复用足够处理高并发的场景,特别是当应用受限于网络I/O而非CPU时。 最后,按照用户的要求,提出几个相关问题。这些问题应该围绕Redis的多路复用实现、不同多路复用技术的对比、单线程模型的优缺点,以及事件处理机制展开。 现在需要组织这些内容,确保回答结构清晰,先回答再解释,然后给出相关问题。检查是否有遗漏点,比如不同的多路复用技术之间的比较,或者具体的工作流程。</think><< Redis的I/O多路复用技术是其高性能的核心机制之一,主要通过事件驱动模型实现高并发连接处理。以下是详细说明: 一、核心原理 1. 多路复用器选择: - Linux系统使用epoll - BSD/MacOS使用kqueue - 旧系统使用select/poll 2. 工作流程: a. 创建事件循环(event loop) b. 注册socket文件描述符和事件(读/写) c. 通过多路复用API等待事件 d. 处理就绪事件 二、关键技术对比 | 技术 | 时间复杂度 | 最大连接数限制 | 触发模式 | |---------|------------|----------------|----------------| | select | O(n) | 1024 | 水平触发 | | poll | O(n) | 无限制 | 水平触发 | | epoll | O(1) | 无限制 | 边沿/水平触发 | | kqueue | O(1) | 无限制 | 边沿触发 | 三、Python示例(使用selectors模块): ```python import selectors import socket sel = selectors.DefaultSelector() def accept(sock): conn, addr = sock.accept() print('Accepted', addr) conn.setblocking(False) sel.register(conn, selectors.EVENT_READ, read) def read(conn): data = conn.recv(1024) if data: print('Echoing', repr(data)) conn.send(data) else: print('Closing', conn) sel.unregister(conn) conn.close() sock = socket.socket() sock.bind(('localhost', 1234)) sock.listen() sock.setblocking(False) sel.register(sock, selectors.EVENT_READ, accept) while True: events = sel.select() for key, mask in events: callback = key.data callback(key.fileobj) ``` 四、Redis实现特点: 1. 单线程事件循环 2. 非阻塞I/O操作 3. 时间事件与文件事件统一处理 4. 自适应多路复用选择(自动选择最佳实现)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值