In-Network Leaderless Replication for Distributed Data Stores论文阅读

In-Network Leaderless Replication for Distributed Data Stores论文阅读



原文链接

In-Network Leaderless Replication for Distributed Data Stores

概要

无领导复制(leaderless replication)允许任何副本处理任何类型的请求,以实现分布式数据存储的读取可扩展性(read scalability)和高可用性(high avaliablity)。然而,这需要繁重的复制协议协调开销,降低写入吞吐量。此外,数据存储仍需要协调成员更改,因此很难快速解决服务器故障。为此,我们提出了 NetLR,这是一种复制数据存储体系结构,可同时支持高性能、容错性和线性化。 NetLR 的关键思想是将整个复制功能移动到网络中,方法是将交换机用作在途的网络内复制协调器。具体来说,NetLR 在网络交换机中执行一致性感知读取调度(consistency-aware read scheduling)、高性能写入协调(, high-performance write coordination)和主动故障适应(active fault adaptation)。我们的网络内复制消除了写入和成员更改的副本间协调,提供了高写入性能和快速故障处理。 NetLR 可以使用可编程交换机以线路速率实现,而额外的内存使用量仅为 5.68%。我们在英特尔 Tofino 交换机上实现了 NetLR 原型,并进行了广泛的测试台实验。我们的评估结果表明,NetLR 是唯一实现高吞吐量和低延迟并且对服务器故障具有鲁棒性的解决方案。


1 简介

推荐系统和网络搜索等数据密集型应用程序依赖于分布式数据存储,它们由 Redis、Memcached和 RocksDB等非关系型键值数据库支持。这些应用程序通常需要数十万次数据存储访问来依次处理用户请求。它们的工作负载通常是读取繁重的,但写入繁重或混合负载也很常见。为了获得良好的用户体验,数据存储应提供高性能的读写、容错性和强一致性(即线性化,linearizability)。
复制是分布式数据存储中用于掩盖故障和改进可用性的常用技术。数据存储通常采用基于领导者(leader-based protocol)的协议,该协议由一个负责处理请求的领导者(leader)和多个用于可用性的追随者(follower)组成。通过领导者处理请求可以很容易地确保线性化,但领导者容易成为数据存储的性能瓶颈。由于领导者选举和组成员更改等共识问题,它还会导致停机,直到服务器故障得到解决为止。
无领导者复制(leaderless replication)是一种方法,它允许任何副本处理读取和写入,以实现可扩展的读取性能和高可用性。不幸的是,这会增加复制协议的协调开销,从而降低写入性能。例如,链复制(chain replica, CR)[32],一种典型的基于领导者的协议,只需要两条消息来写入瓶颈副本。然而,在最先进的无领导者协议 Hermes中,写入协调器副本处理 3𝑛 - 1 条消息进行写入,其中 𝑛 是副本的数量。此外,尽管无领导复制不需要领导达成共识,但仍需要协调成员变更。因此,当服务器发生故障时,请求处理会停止,直到组成员身份重新配置和相应的协调完成。上述无领导复制的局限性促使我们提出以下问题:我们能否构建一个同时支持高性能、容错性和线性化的复制数据存储?
为了解决上述问题,本文提出了in-Network Leaderless Replication (NetLR),一种复制数据存储架构,将交换机(switch)用作网络内复制协调器。 Harmonia是最近利用交换机进行复制的一个方向,但它仅限于基于领导者的复制的读写冲突检测。 NetLR 比 Harmonia 更进一步,将整个复制功能移动到网络中以实现无领导复制。 NetLR 背后的关键点是交换机执行复制功能,包括一致性感知读取调度(consistency-aware read scheduling)、写入协调(write coordination)和主动故障适应(active
fault adaptation)。这是因为 1. 网络交换机是一个为复制消息提供全局视图的集中点; 2. 像 Intel Tofino这样的可编程交换机,ASIC 具有足够的灵活性和计算能力来处理带有自定义元数据的复制消息。与复制协议相比,我们的网络级方法使数据存储能够享受可扩展的读取、高可用性和线性化,而不会因副本间协调而导致写入性能下降。此外,由于交换机直接协调写入而无需写入协调器副本,因此延迟也得到了改善。最后,数据存储不必协调成员更改,从而实现无缝故障适应。
在 NetLR 中,交换数据平面由一致性感知读调度模块和写协调模块组成。即使发生读写冲突,一致性感知读取调度模块也可以以无领导方式保持线性化。具体来说,该模块在写入操作期间跟踪临时不一致对象的最新已知一致副本。基于此,即使正在进行写入,交换机也可以将读取请求转发到一致的副本。写协调模块发起并提交写操作。为了提供严格的写入顺序,模块通过为每次写入分配一个全局序列号来序列化写入。为了获得高性能,该模块在交换机内部复制写请求,而不是从客户端接收。交换机将写入广播到每个副本,并且仅当每个回复都聚合到交换机时才提交写入。
我们的交换机控制平面使用主动故障适应模块快速处理服务器故障。具体来说,交换机控制平面以集中的方式主动管理服务器的活跃度。当发生故障时,模块立即将故障副本从副本列表中排除,并更新交换数据平面。由于成员资格重新配置是在没有服务器协调的情况下执行的,因此可以将请求无缝地转发到活动副本。这也意味着客户端和存储服务器不必维护彼此的活动状态。
NetLR 是一种实用的解决方案,可以与商品交换机一起部署。我们在 P4 中使用英特尔 Tofino 交换机 ASIC实现了 NetLR 原型。 NetLR 仅使用 5.68% 的交换机内存,因为我们的数据平面仅存储对象元数据。我们的解决方案不会损害数据包转发功能并保持线路速率,因为这些模块可以使用一些匹配动作表和状态寄存器来实现。
为了评估 NetLR,我们构建了一个由 7 个连接到 Edgecore 的服务器组成的测试平台Wedge100BF-32X开关并进行一系列实验。主要结果如下。首先,NetLR 提供比现有复制协议更高的吞吐量和更低的延迟。此外,NetLR 支持近线性可扩展性。即使在服务器出现故障的情况下,NetLR 也能保持高吞吐量。最后,NetLR 对写入比率和对象访问模式等工作负载动态具有鲁棒性。
总而言之,我们做出了以下贡献:
• 我们提出了 NetLR,一种通过在网络交换机中执行整个复制功能来提供高性能、容错和线性化能力的复制数据存储架构,消除了复制协议的协调开销。
• 我们设计了交换机数据平面和控制平面模块,它们执行网络中的路径内复制,同时仅消耗一小部分交换机硬件资源,包括内存和状态寄存器。
• 我们实现了 NetLR 的原型并进行实验表明 NetLR 提供了比现有工作更好的性能,并且对工作负载动态具有鲁棒性。
本文的其余部分组织如下。在第 2 节中,我们描述了这项工作的动机。第 3 节、第 4 节和第 5 节分别提供了 NetLR 的设计原理、体系结构和设计。我们分别在第 6 节和第 7 节中介绍了实施和评估结果。我们在第 8 节讨论相关工作。最后,我们在第 9 节总结我们的工作。
图1 Hermes处理请求, the state-of-the-art leaderless replication protocol.虽然读取在本地处理,但写入需要副本间协调。
图1 Hermes处理请求, the state-of-the-art leaderless replication protocol.虽然读取在本地处理,但写入需要副本间协调。

2 背景与动机

2.1 线性复制协议

具有非关系键值数据库(如 Redis和 RocksDB)的分布式数据存储是现代数据密集型应用程序的关键构建块。对象数据通常在多个存储服务器(即副本)上复制以提高可用性。由于副本数量和部署成本成正比,通常使用 3 到 7 个副本 。为了处理请求,复制的数据存储使用复制协议,如下所示。

2.1.1 基于领导者的复制

复制协议通常是基于领导者的,它由一个领导者副本和多个跟随者副本组成。在 Primary-Backup (PB) 中,领导者副本同时处理读取和写入请求。跟随者副本仅用于备份。 PB 中的领导者通过向追随者广播写入更新消息来启动写入,并且只有在收到所有确认后才提交写入。当领导者失败时,其中一个跟随者副本通过共识协议(如 Paxos )被选为新的领导者。
链复制(CR)是一种流行的基于领导者的复制协议。 CR 通过在副本链中使用不同的专用(领导者)副本进行读取和写入来提高 PB 的整体性能。读取由尾部副本处理,写入由头部副本发起并通过链转发到尾部副本。尾副本向客户端发送写回复消息以提交操作。 PB 中的领导者应该为单次写入处理 2𝑛 消息,其中 𝑛 是副本的数量。然而,由于序列化的写入传播,CR 只需要在尾部副本处理两条消息。

2.1.2 无领导复制

最近,无领导复制已经流行起来。在无领导者复制中,没有领导者,每个副本都可以提供读写服务。它通过运用多种副本提供了可扩展的读吞吐量。数据存储也变得高度可用,因为系统不依赖特定副本来处理请求。自然,它不需要领导达成共识。
图 1 显示了使用 Hermes 处理请求的示例,这是最先进的无领导复制协议 。客户端请求可以转发到任何副本。副本收到读取请求后,在本地返回请求对象的数据。我们可以看到,Read 1 和 Read 2 是在本地处理的,没有与其他副本协调。与读取不同,处理写入需要副本之间的协调,因为每个副本都应该维护最新的数据。因此,当一个副本收到写请求时,该副本成为写协调者(图中的副本 1),并向其他副本广播消息以进行写更新和对象失效。在收到所有更新确认后,写协调器发回写完成消息以提交操作。最后,协调器传播对象验证消息以再次启用对对象的读取。

2.2 副本间协调开销

作为读取可扩展性和高可用性的权衡,无领导复制增加了复制协议的协调开销。此外,还需要对成员变更进行协调。这使得很难快速适应服务器故障。

2.2.1 写入协调

无领导复制的一个缺陷是难以保证线性化。为了线性化,读取应该总是得到最新的数据。这也强制要求按顺序进行写入。然而,由于请求是以分布式方式处理的,并发请求可能会同时发生冲突。这会导致违反线性化,如下所示。当读取访问尚未应用对同一对象的持续写入的副本时,会发生读写冲突。在这种情况下,尽管数据存储中至少存在一个具有最新数据的副本,但读取的数据却是陈旧的数据。这是因为 1. 客户端不知道哪个副本有最新的数据; 2. 写协调器通过传播写更新消息来更新所有副本需要时间(即复制滞后)。当多个副本协调同一对象的不同写入时,会发生写入间冲突。副本按照它们接收消息的顺序更新对象数据。因此,当较旧写入的更新消息比较新写入的更新消息更晚到达副本时,副本最终会存储较旧的对象数据。现有的无领导复制协议通过执行额外的协调来牺牲线性化性能。在 Hermes 中,每个副本都维护对象状态,可以是有效的,也可以是无效的。如图 1 所示,写协调器不仅更新对象数据,而且使其他副本中的对象无效。它还在提交写入后发回附加消息以验证对象。对象失效阻止读取获取陈旧数据,但读取停止直到对象状态再次变为有效。此外,Hermes 中的写协调器应该处理 3𝑛 - 1 条消息来进行写协调,而 CR 只在尾部副本处处理两条消息来进行写。此处n是复本数。具体来说,Hermes 中的写协调器应该分别处理 2 个𝑛 消息来启动和提交一个写操作和 𝑛 - 1 个消息来验证对象。这意味着 Hermes 中的写入吞吐量随着副本数量的增加而降低,而 CR 提供恒定的吞吐量。

2.2.2 协调成员更改

在无领导复制中,副本不必就领导达成共识。这对于复制数据存储来说是一个巨大的好处,因为达成共识是一个复杂的问题。但是,副本仍然需要协调成员资格的变化。数据存储中的客户端和副本应维护其他副本的正确活动状态。如果状态不正确,可以将读取传递到故障副本。由于永久等待确认,写入也无法提交。此外,理想情况下,数据存储应该能够尽可能快地适应故障。但是,当服务器发生故障时,吞吐量可能会下降,直到更新的成员状态被传播。

3 设计原理

网络内复制的案例 我们的目标是构建一个可复制的数据存储,同时提供高性能、容错性和线性化。具体来说,解决方案应该为读取和写入提供高吞吐量和低延迟。为了实现容错,数据存储应该无缝地适应服务器故障。对于线性化,读取必须始终获取请求对象的最新数据,并且必须按顺序应用写入。为了实现这一目标,我们没有设计复制协议,而是通过使用交换机将整个复制功能移动到网络中作为输入。ToR(架顶式)交换机是协调复制的一个好地方,因为存储机架中的每条复制消息都会通过这里。这表明交换机可以使用全局视图执行路径复制,以查看副本之间正在交换的消息。副本间协调开销的根本原因是对象和服务器状态以分布式方式维护。因此,我们可以通过维护交换机上的状态来消除协调开销。可编程交换机的灵活性和能力是实现网内无领导复制的关键使能器。传统交换机只提供固定的功能,如 L2/L3 包转发,我们无法对交换机硬件进行编程。然而,英特尔 Tofino和 Cavium Xpliant等新兴的可编程交换机 ASIC 允许我们自定义数据包处理管道,同时提供 Tbps 规模的吞吐量。具体来说,1. 我们可以对数据包解析器进行编程,以识别自定义数据包格式; 2. 我们可以利用有状态内存来读取/写入自定义数据,3. 我们可以定义自定义匹配表和相应的动作。在复制的上下文中,我们可以使交换机识别复制消息,维护对象和服务器状态,并执行复制功能。网络交换机的资源容量有限。从概念上讲,将交换机转换为复制协调器并不简单,因为交换机硬件基本上是为数据包转发而设计的。可编程交换机具有有限的计算和存储的能力,因此,在设计 NetLR 时,我们仔细考虑了这些资源限制。 NetLR 是一种轻量级的解决方案,只占用很少的交换机硬件资源。此外,NetLR 可以在交换机架构支持的可用计算预算内完成请求处理。
与 Harmonia 比较 Harmonia是最近利用交换机复制数据存储的一个进展。具体来说,Harmonia 检测交换机中的读写冲突。我们将 NetLR 的显着特点突出如下。
• Harmonia 仅支持基于领导者的复制协议(例如 PB 和 CR)。如果请求的对象不一致,交换机会将读取转发到领导副本。 NetLR 在交换机中执行无领导复制,因此不需要复杂的复制协议。如果对象存在挂起的写入,则交换机将读取转发到最新的已知一致副本,该副本可以是任何副本,而不是像领导者这样的特定副本。
• 在Harmonia 中,领导者副本负责写协调。这表明 Harmonia 无法同时实现写入的高吞吐量和低延迟。例如,当 Harmonia 使用 CR 时,延迟会随着链长的增加而增加。与 Harmonia 不同,NetLR 中的延迟不受副本数量的影响,因为我们使用交换机以广播方式协调写入。
• Harmonia 基于复制协议被动处理成员资格更改。 NetLR 积极处理组成员资格的变化。交换机控制平面监控副本的活跃度,快速适应服务器故障,无需副本的干预。
与现有作品的比较 我们在表 1 中总结了 NetLR 与现有工作的区别。CR 和 Hermes 是协议级方法,而 Harmonia 和 NetLR 是网络级解决方案。 Hermes 和 NetLR 提供读取可扩展性并且不需要领导选举,因为它们是无领导的。 Harmonia 还提供了读取可扩展性以及网络内读写冲突检测。 NetLR 是唯一不需要副本间协调来进行写入和成员资格更改的解决方案。副本之间不存在写协调器。因此,我们的解决方案只需要在瓶颈副本处处理两条消息(即写入更新和确认)以进行写入操作。同样,两跳足以处理一次写入(即 1 次往返时间 (RTT))。
表1 现有工作对比 (coordi. = coordination; mem. = Membership changes; n = number of replicas).
表1 现有工作对比 (coordi. = coordination; mem. = Membership changes; n = number of replicas).

4 NETLR 架构

图 2 说明了由以下组件组成的 NetLR 体系结构。
在这里插入图片描述

4.1 交换数据平面

交换数据平面是 NetLR 的核心组件,它协调复制过程。交换数据平面中的包处理流水线基本上作为通用交换机进行L2/L3包转发。 NetLR 将复制功能添加到处理管道中,这不会损害数据包转发功能。 NetLR 的功能通过以下两个模块实现。

4.1.1 一致性感知读取调度

一致性感知读取调度模块通过以无领导方式解决读写冲突来调度读取请求。为此,该模块维护由于持续写入而变得不一致的对象列表。该列表通常很小,因为当开关提交写入时,该对象已从列表中删除。该模块还跟踪具有最新不一致对象数据的最新已知一致副本的 ID。当请求的对象在不一致对象列表中时,交换机将读取转发到最新的已知一致副本。这意味着读取总是获取对象的最新数据,即使对象的写入尚未应用于所有副本。当新的写回复到达交换机时,副本 ID 会更新为源副本的 ID。即使对象不一致,这也使开关能够平衡读取请求,这与仅将读取转发到领导副本的 Harmonia 不同。

4.1.2 高性能写入协调

交换机中的写协调模块直接协调写操作。因此,副本不会相互通信以协调写入。在接收到来自客户端的写入后,交换模块克隆写入消息并将它们广播到副本。当每个写回复都聚合到交换机时,模块通过向客户端发送写回复来提交写操作。该模块大大减少了写协调所需的消息数量。具体来说,由于不需要副本间协调,一个副本只处理一次写入的两条消息。因此,无论副本数量如何,我们都可以看到恒定的写入吞吐量。该模块还通过维护一个全局序列号来解决写入间冲突,该序列号在接收到每次写入时单调增加。交换机将序列号分配给写入,这使副本能够区分写入请求的顺序,包括同一对象的并发写入。我们使存储副本仅在消息中的序列号大于或等于维护的序列号时才接受写入。因此,当处理同一对象的不同写入时,我们不必使对象无效以避免乱序写入更新。

4.2 切换控制平面和服务器/客户端

4.2.1 主动故障适应

交换机控制平面中的主动故障适应模块除了维护相关信息(例如,IP 地址、副本总数和副本 ID)外,还维护副本的活跃状态。该模块通过检查连接到副本的端口状态定期(≈10𝑚𝑠)更新活动状态。当检测到端口关闭(即服务器故障)时,模块会立即从副本 IP 和端口号列表中排除故障副本。该模块还更新交换机数据平面中的寄存器和匹配操作规则,其中包括活动副本的数量以及副本 ID 和 IP 地址的转换表。副本不需要任何操作来处理故障。由于该模块,数据存储可以快速适应服务器故障,而无需依赖复制协议。

4.2.2 存储服务器和客户端

NetLR 极大地简化了复制协议,因为整个复制功能都在交换机中执行。当读取请求到达时,存储服务器(即副本)发送带有请求对象数据的读取回复。服务器收到写请求后,仅当数据包的序列号大于或等于维护的序列号时,才更新对象数据并发回写回复。客户端只是发送请求并接收回复。我们注意到 NetLR 不会使本地请求通过交换机。服务器的网络堆栈通过环回网络接口将本地请求转发到服务器本身。

5 NETLR 设计

5.1 Packet格式

在这里插入图片描述

图 3 显示了 NetLR 的数据包格式。 NetLR 使用自定义 L7 协议消息。我们为 NetLR 保留一个 UDP 端口号,以便交换机可以将不同的数据包头解析器流用于 NetLR 数据包和普通数据包。 NetLR 消息的头部由以下三个字段组成:
• OP:消息操作类型,可以是 READ、WRITE、R-REPLY 和 W-REPLY。
• ID:请求对象的 ID。
• SEQ:写请求的序列号。开关为每个写入请求生成一个值。

5.2 请求与回复处理

NetLR根据消息的类型有不同的包处理逻辑如下。算法 1 是 switch.中请求处理的伪代码。
算法1

5.2.1 读取请求

NetLR 中的交换机始终将读取转发到具有最新数据的副本,从而确保线性化。当收到读取请求时,交换机首先检查请求的对象是否在不一致对象列表中(第 1-2 行)。如果对象包含在列表中,则交换机将数据包的目的地更新为最新的已知一致副本(第 2-3 行)。否则,交换机可以使用请求调度程序(例如,我们工作中的循环)选择任何副本作为目标,因为对象是完全一致的(第 4-5 行)。之后,交换机将读取转发到目标副本(第 7 行)。

5.2.2 写入请求

NetLR 交换机通过交换机内写入序列化和写入协调提供有序写入和高性能。收到写入后,交换机全局序列号加1并将该编号分配给写入报文的序列号(第 8-10 行)。接下来,交换机将对象插入到不一致的对象列表中(第 11 行)。之后,交换机使用数据包克隆(第 12 行)传播写入。具体来说,有多少副本就有多少个请求,每个请求发送到每个副本。

5.2.3 读取和写入响应

算法2

算法 2 是交换机中回复处理的伪代码。由于可以使用单个副本在本地执行读取,因此交换机只需将读取回复转发给客户端(第 1-2 行)。但是,对于写回复,交换机会执行额外的操作。
如果数据包的序列号大于最后写入的序列号,则此回复是较新的写入(第 3-4 行)。交换机将对象的最后写入序列号更新为数据包的序列号(第 5 行)。接下来,交换机将一致副本的数量重置为 1,因为新的写入协调开始(第 6 行)。最后,最新的已知一致副本更新为发送回复的源副本的 ID(第 7 行)。如果回复是针对当前写入的,则交换机首先将对象的一致副本数增加 1(第 8-9 行)。与较新的写入相同,最新的已知一致性副本也会更新(第 10 行)。在收到旧写入的回复后,交换机会简单地丢弃数据包,因为我们不再需要该消息(第 11-12 行)。
如果一致副本的数量等于副本的数量,这意味着所有副本都成功更新了对象数据(第 14 行)。交换机现在从不一致对象列表中删除该对象,因为该对象是一致的(第 15 行)。交换机最终通过将响应回复转发给客户端来提交写操作(第 16 行)。否则,数据包将被丢弃,因为我们需要更一致的副本来提交写入(第 17-18 行)。

5.2.4 操作示例

图4

我们现在展示 NetLR 中请求和回复处理的示例。图 4 (a) 说明了对一致对象 B 的读取处理。交换机可以选择任何副本作为目标,因为所有副本都包含对象的最新数据。在此示例中,交换机将请求转发到副本 2。副本只是将带有对象数据的回复返回给客户端。图 4 (b) 是读取不一致对象 C 的示例。与图 4 (a) 中的示例不同,交换机只能将请求转发到最新的已知一致副本(示例中的副本 3)。副本通过将回复返回给客户端来完成操作。
图 4(c)显示了对象 G 的写入示例。收到写入请求后,交换机将全局序列号增加 1 并分配请求的编号。因此,序列号更新为 10。应在所有副本中应用写入,因此交换机克隆写入并广播消息。同时,对象 G 被插入到不一致对象列表中。每个副本在更新对象 G 的数据后返回回复。本例中,副本之间,副本 2 的回复首先到达交换机。交换机将最后写入的序列号、最新的已知一致副本和一致副本的数量分别更新为 10、副本 2 和 1。图 4 (d) 显示了如何提交对象 G 的写入。来自副本 1 和副本 3 的写回复最终到达交换机。开关还会更新每个回复的对象状态。由于每个副本都被确认,交换机从列表中删除对象 G。此外,交换机将最新副本(即副本 3)的回复转发给客户端以提交 write.

5.3 处理失败

5.3.1 报文丢失

由于网络不可靠,消息可能会被丢弃。如果从交换机发送的写请求或写回复被丢弃,则对象将永久保留在不一致的对象列表中。在这种情况下,读取被转发到最新的已知一致副本,直到对对象执行更新的写入。这可能会在一段时间内降低性能,但不会损害一致性。我们还可以使用超时等应用程序级重传机制来防止客户端在写回复被丢弃时过度等待写提交消息。超时可以通过考虑延迟趋势来动态调整,以避免过早或长时间超时。

5.3.2 服务器故障

在 NetLR 中,服务器故障由交换机控制平面中的主动故障适应模块处理,如第 4.2.1 节所述。副本的添加或恢复可以通过在完成重新配置和复制数据后再次重新启动交换机控制平面来处理。具体来说,我们首先将最新副本的对象数据复制到恢复的副本中。我们还使最新副本将复制的写入请求转发到添加的副本,直到恢复添加的副本的服务请求。最后,我们更新控制平面中的成员信息并恢复为恢复的副本提供服务。

5.3.3 切换故障

交换机在所有数据中心硬件中的故障率最低。对于至少经历一次故障的交换机,一年的平均故障次数仅为 1.1 。当交换机发生故障时,我们可以重启交换机或更换备用交换机。这会影响可用性、性能和一致性。具体来说,在停机期间,数据存储变得不可用,性能也会下降。重启交换机的时间取决于交换机硬件。根据我们的经验,启动和运行交换机进程需要数十秒。可用性和性能问题并非特定于 NetLR,因为交换机故障会影响任何类型的分布式系统。与 NetLR 相关的关键问题例如,副本可能会丢弃写请求,直到交换机的序列号达到副本的序列号,因为交换机故障会重置全局序列号。为避免这种情况,就像在现有结果一样,我们可以使用交换机的唯一ID,该ID在交换机启动时单调增加。通过比较交换机的ID和序列号,服务器可以接受新交换机的写入。交换机ID还可用于防止由丢失对象状态引起的不一致读取。具体来说,我们可以将交换,ID插入到读取请求中。仅当携带的交换机ID与最新的已知交换机ID相同时,存储副本才接受读取。这使得读取请求被丢弃,直到对对象执行新的写入,但可以保留线性化。为了减轻基于交换机ID的解决方案导致的性能下降,我们可以使用数据存储的快照而不是交换机ID。这可以保持一致性并且不会损害性能,尽管对象状态会回到创建快照的时间。

5.4 讨论

5.4.1 多机架部署

图2

如图 2 所示,我们基本上考虑部署一个存储机架,其中所有副本都位于同一个机架中。这种单机架部署模型可以应用于许多实际用例,例如企业的本地数据存储和云数据中心的专用数据存储。
但是,一些数据存储可能使用不同存储中的副本用于复制的机架。在这种情况下,由于对象状态分布在多个 ToR 交换机中,NetLR 的功能可能无法正常工作。为了解决这个问题,我们可以利用如图 5 所示互连多个存储机架的聚合交换机。在图中,我们可以看到聚合1交换机协调 ToR1和 ToR2交换机下的副本。通过将副本组的请求转发到同一个聚合交换机,我们可以监控来自多个机架的每条复制消息。这不会不必要地增加延迟,除非客户端在目标副本的同一存储机架中,因为来自客户端的每个数据包都通过聚合交换机转发到目标副本。汇聚交换机的控制平面还可以监控连接的ToR交换机的端口状态,因为交换机控制平面也可以相互通信。但是,它可能会增加时间去适应由于网络跃点增加而导致的服务器故障。多机架部署的正确设计和评估是我们未来的工作。
在这里插入图片描述

5.4.2 支持大对象数据

NetLR 使用 UDP,因为该协议支持键值数据库的低延迟 [8, 12, 36]。大多数请求和回复都是通过单个数据包传递的,因为大多数对象值都是几十个字节[29]。这小于通常为 1500 字节的最大传输单元 (MTU) 大小。但是,某些工作负载可能具有较大的值,这些值被分割成多个数据包。在这种情况下,交换机可以将单次写入的数据包感知为针对不同对象的多次写入数据包。为了避免这种情况,像 Harmonia [40] 一样,我们可以使用不同的操作类型区分第一个数据包的处理与后续数据包的处理。具体来说,交换机在不访问哈希表的情况下转发以下数据包,避免重复数据包处理。

5.4.3 复制到副本子集

当前的 NetLR 设计目标是复制数据存储,其中对象被复制到连接到交换机的所有副本上。但是,数据存储可能希望仅在副本的子集中复制对象。 NetLR 可以通过将副本组 ID 添加到消息元数据来支持这一点。特别是,对于写协调,交换机可以使用与请求消息中的副本组 ID 匹配的不同多播组。对于读取,我们可以利用将属于副本组的副本表示为位图的寄存器值。

6 实施

6.1 切换控制平面和服务器/客户端

6.1.1 控制平面

开关控制平面应用程序是使用 Barefoot Runtime API 用 Python 2.7 编写的。当我们运行应用程序时,交换机控制平面首先使用预先配置的表规则和寄存器值更新交换机数据平面。之后,应用程序定期参考端口状态进行主动故障适应。

6.1.2 客户端-服务器应用程序

我们还使用 Python 的 Redis API 在 Python 3.7.10 中制作了一个单线程客户端-服务器应用程序。我们的应用程序基于 pypacker 库,因为它允许我们轻松定义和操作自定义数据包头。我们还使用pypy3来最大化服务器的数据包处理性能。客户端通过与副本通信来测量吞吐量和延迟。服务器使用复制协议处理请求。

6.2 数据平面实现

实现 NetLR 设计并不简单,因为交换机硬件资源有限且时序约束严格。因此,我们使用多种技术将设计转化为工作系统。我们的交换机数据平面是用 P416 编写的,并使用 Intel P4 Studio SDE 9.2.0 为 Intel Tofino 交换机 ASIC编译。总体而言,NetLR 消耗 5 个流水线阶段,仅占交换机内存的 5.68%。

6.2.1 数据包处理流水线

数据包处理管道由入口管道和出口管道组成。在两条管道之间,存在数据包缓冲区。我们的模块位于入口管道,因为 NetLR 为复制消息执行自定义数据包转发。入口管道由多个 Match-Action (M-A) 阶段组成。在每个阶段,交换机都可以执行由 M-A 表定义的相应动作。普通报文直接由L2/L3路由表处理进行报文转发。如果数据包属于 NetLR,则交换机根据消息类型对数据包应用额外的 M-A 阶段。 NetLR 流水线由 4 个阶段组成,这不超过交换机架构提供的预算。

6.2.2 带有寄存器数组的哈希表

为了保持不一致的对象状态,我们使用多个寄存器数组。我们使用四个数组来存储对象 ID、最后写入的序列号、最新已知的一致副本 ID 和一致副本的数量。理想情况下,我们应该为每个对象提供一个专用的寄存器槽。但是,寄存器数组的大小是在编译时静态确定的,可用的内存空间是有限的。因此,为了减少内存使用,我们使用寄存器数组作为哈希表。具体来说,数组的索引是对象 ID 的哈希值,它存储在 NetLR 标头的 ID 字段中。由于散列冲突可能会导致散列重复,因此我们将原始对象 ID 存储在寄存器数组中。注意原始对象ID可以携带在数据包有效载荷中,并且可以被交换机解析。哈希可以在交换机数据平面中计算,但我们从客户端生成哈希以简化处理管道。
图6:在跟踪不一致对象状态的哈希表中插入、搜索和删除操作。寄存器的索引是对象ID的哈希。对于删除,我们只删除对象ID以满足交换机计算预算。

图 6 显示了哈希表设计以及交换机如何执行操作。对于插入,交换机首先读取对象 ID 数组中匹配的插槽。如果槽为空,则交换机将对象ID记录在槽中,以避免覆盖相同哈希值的对象。对于搜索,开关只返回匹配槽中存储的值。为了在提交写入时从哈希表中删除对象,交换机会从匹配的槽中删除存储对象 ID。值得注意的一点是我们不会删除其他寄存器数组的值。这是因为从所有寄存器数组中移除值会消耗大量的 M-A 单元,这可能会超出计算预算。为了避免导致错误行为的访问,只有在存储的对象 ID 等于数据包中的对象 ID 时才能访问其他寄存器数组。

6.2.3 处理哈希冲突

由于散列函数的性质,不同对象的散列可能会发生冲突。正如我们上面所述,我们通过将原始对象 ID 存储在哈希槽中来防止碰撞对象的访问。交换机只是丢弃碰撞对象的数据包。这可以由客户端使用应用程序级丢失恢复机制重新传输。哈希冲突导致的性能下降并不严重,因为对象状态仅在提交写操作之前保持。这也意味着一次存在一些不一致的对象。此外,典型的生产工作负载读繁重,写比率为 5%。我们展示了 128K 哈希槽足以服务于性能评估中的只写工作负载,这是最具挑战性的工作负载。如有必要,我们还可以使用著名的开放寻址技术和 Harmonia所做的双重哈希。

6.2.4 组成员状态

交换机数据平面还维护组成员状态,包括副本 ID、IP 地址和端口号。为了将副本 ID 转换为相应的 IP 地址,反之亦然,我们使用了两个转换 M-A 表。表规则由控制平面更新。客户端不必知道副本的确切 IP 地址,因为交换机使用请求调度程序来确定目标副本以进行读取和数据包克隆以进行写入。这使交换机能够在没有存储服务器干预的情况下处理故障。

6.2.5 交换机硬件的限制

我们的数据平面实现表明,我们需要谨慎的方法和技术来满足可编程开关 ASIC 的限制。但是,我们澄清这是针对特定交换机架构的数据平面设计。请注意,每种交换机架构可能具有不同的优势和局限性。 NetLR 的设计可以在另一个交换机架构中完全实现。可编程开关 ASIC 得到了迅速的改进,新兴的 ASIC 也提供了新的特性。例如,英特尔 Tofino 不提供入口管道中的端口队列长度信息,这对于拥塞感知数据包转发至关重要。然而,队列长度信息在新出现的 Intel Tofino2 [7] 的入口管道中变得可用。

7 评价

7.1 实验

7.1.1 测试平台

我们的测试平台由 7 台服务器组成,这些服务器连接到带有 3.2 Tbps Intel Tofino 交换机 ASIC [6] 的 Edgecore Wedge100BF-32X。其中 6 台服务器是具有 Intel 6 核 CPU 和 16GB 内存的存储副本。每个存储副本的最大吞吐量大约为读取 18.4KRPS(每秒请求数)和写入 17.8KRPS。其中一台服务器充当具有 Intel 6 核 CPU 和 32GB 内存的客户端。这些服务器配备了 Mellanox ConnectX-5 以太网 NIC。与其他服务器不同,客户端服务器具有双端口 NIC。为了在一台服务器上使用两个客户端,我们运行两个客户端应用程序并分配一个单独的 CPU 内核和 NIC 端口。单个客户端的最大吞吐量约为 54KRPS。因此,使用两个客户端时,最大吞吐量大约为 108KRPS。我们将链接速度设置为 40Gbps。服务器运行带有 Linux 内核 5.4.0-77-generic 的 Ubuntu 18.04.3 LTS。(a) 中位数(b) 99th Percentile 60 40 2000 20 40 60 吞吐量 (KRPS) 15 10 5 00 20 40 60 80 吞吐量 (KRPS)CR HermesNetLR 1345图 7:延迟与吞吐量。

7.1.2 工作负载

除非另有说明,否则我们基本上使用 4 个副本和 5% 写入率的典型读取繁重工作负载,并像现有作品一样均匀分布。我们使用具有 32 位 ID 和 128 位值的 1M 对象,与 Harmonia.

7.1.3 比较方案相同

我们将 NetLR与CR和 Hermes进行比较,它们分别是典型的基于领导者和无领导者的复制协议。与协议的比较让我们知道网络内复制带来了多少性能提升。 Hermes 是使用 Infiniband NIC 的基于 RDMA 的协议。在我们的实验中,Hermes 使用 OS 网络堆栈和以太网 NIC 与副本通信以进行公平比较。我们还将 NetLR 与 Harmonia(最先进的交换机内解决方案)进行了比较。由于 Harmonia 的代码不公开,我们尽最大努力实现了原始论文中描述的 Harmonia 机制。一个区别是我们的实现提供了 128K 的单阶段哈希槽,而原始实现提供了 192K 的 3 阶段哈希槽。这不会误导我们得出错误的结论,因为 128K 的 slot 足以处理暂时不一致的对象。另一个区别是我们的 Harmonia 实现在处理写完成消息时不比较序列号以从脏集中删除对象。这可能会导致极端情况的弱一致性。详细地说,如果存在对同一对象的并发写入,这可能会导致读取转发到不一致的副本,因为在最新的写入完成到达之前,较早的写入完成将对象从脏集中删除。为了避免不一致副本中的读取停滞,我们使副本在不参考最后提交的序列号的情况下接受读取。这使我们能够通过交易一致性看到正确的表现。我们优雅地注意到我们比较的是性能,而不是一致性正确性。请注意,NetLR、CR 和 Hermes 在我们的实验中保持线性化。

7.2 实验结果

7.2.1 延迟与吞吐量

图7

我们首先将延迟评估为实现吞吐量的函数。客户端向副本生成请求,我们通过改变吞吐量来测量中值延迟和第 99 个百分位延迟(即尾部延迟)。我们将结果绘制在图 7 中。很容易看出 CR 在比较解决方案。这是因为 CR 处理每个请求类型的单个副本的请求。与 NetLR 相比,Hermes 的吞吐量较低。这是因为 Hermes 使用副本进行写入协调并执行额外的协调来验证副本中的对象。图 7(a)显示了作为吞吐量函数的中值延迟。由于 CR 的吞吐量受限于单副本性能,因此随着吞吐量达到单副本的吞吐量限制,CR 的延迟会迅速增加。当超过饱和吞吐量时,Hermes 的中值延迟也会飙升。在比较的方案中,NetLR 显示了吞吐量中最低的中值延迟。这意味着 NetLR 是为典型工作负载同时提供高吞吐量和低延迟的解决方案。同时,图 7 (b) 显示了第 99 个百分位延迟的结果。与中值延迟的结果相同,NetLR 在方案之间提供了最低的尾延迟。 Hermes 和 NetLR 之间的差距源于这样一个事实,即 Hermes 通过协调副本中的写入操作来增加写入延迟,这意味着每个副本应该比具有更多 RTT 的 NetLR 处理更多消息。

7.2.2 可扩展性

图8,9,10,11

我们根据副本数量和数据集大小评估 NetLR 的可扩展性。对于副本数的影响,客户端以客户端限制的发送速率生成请求。之后,我们通过改变副本的数量来衡量吞吐量。对于数据集大小的影响,我们将数据集大小从 1M 变为 100M,有四个副本。图 8(a)显示了副本数的结果。正如预期的那样,CR 的吞吐量受限于单副本吞吐量。 NetLR 和 Hermes 显示随着副本数量的增加,吞吐量也会增加。但是,NetLR 的吞吐量平均比 Hermes 高 1.18 倍。这是因为 Hermes 为副本间的协调牺牲了写入吞吐量。与 CR 和 Hermes 不同,我们可以看到 NetLR 提供了接近线性的图 11:具有不同写入比率的吞吐量。可扩展性。图 8 (b) 显示数据集大小的影响是微不足道的。这是因为数据集大小本身不会改变读/写操作所需的计算资源。

7.2.3 故障性能

在本实验中,我们检查了 NetLR 在交换机和服务器故障下的性能。对于服务器故障,客户端仅向四个副本生成读取请求,发送速率为 18KRPS,一个副本可以完全服务。每 2 秒,我们通过禁用端口导致一个副本失败。我们在有和没有主动故障适应模块的情况下测量 10 秒的吞吐量。图 9 显示了作为时间函数的吞吐量。我们可以看到,即使服务器出现故障,NetLR 也能保持接近发送速率的吞吐量。这是因为我们的故障适应模块会立即从副本列表中排除故障副本并更新数据平面状态。因此,请求被无缝转发到活动副本。但是,在没有故障适应模块的情况下,交换机仍然会将读取转发到故障副本,从而导致读取失败。对于交换机故障,我们手动停止并重新激活交换机。图 10 显示了故障和恢复期间的吞吐量。我们可以看到,随着交换机发生故障,吞吐量迅速下降。交换机重新激活后,吞吐量恢复到故障前的水平。重新激活开关大约需要 13 秒。我们注意到这一次取决于交换机硬件,而不是 NetLR 机制。

7.3 Deep Dive

7.3.1 写入比率的影响

我们现在检查写入比率对系统吞吐量的影响,以评估动态工作负载的性能,包括写入繁重和混合工作负载。客户端通过改变三个比较方案的写入比率来测量饱和吞吐量。图 11 显示了不同写入比率的吞吐量。我们可以看到,无论写入比率如何,CR 都能提供恒定的性能。 Hermes 的吞吐量随着写入比率的增加而降低。这并不奇怪,因为 Hermes 执行昂贵的副本间协调来处理写入。对于 NetLR,写入比率更高,吞吐量接近 CR 的性能,因为写入吞吐量受限于单副本性能。由于哈希冲突,当写入比率为 100% 时,NetLR 的吞吐量略低于 CR。图 11 中的结果表明 NetLR 可以为大多数比率提供最佳吞吐量。

7.3.2 极端工作负载的性能

图12,13,14,15

我们对只读和只写的极端工作负载进行了吞吐量和延迟实验。这些工作负载并不代表生产数据存储中的典型工作负载。然而,这让我们知道每种请求类型的明确性能。图 12 显示了只读和只写工作负载在不同吞吐量级别下的中值延迟。只读工作负载的结果与图 7 (a) 中的结果相似,因为写入率的差距仅为 5%。正如预期的那样,对于只写工作负载,我们可以看到 Hermes 由于副本间协调开销而导致吞吐量最低。 NetLR 的吞吐量受限于单副本性能(如 CR),因为必须在所有副本中应用写入。图 13 显示了极端工作负载的不同吞吐量级别的 99% 延迟。我们可以看到,由于网络内复制,NetLR 在工作负载的比较方案之间提供了最低的尾部延迟。在只写工作负载中,CR 的吞吐量比 NetLR 好 1.08 倍,如图 11 所示。这是因为这是因为交换机数据平面中的哈希冲突导致请求丢失。尽管发生吞吐量下降,但我们优雅地认为这并不重要,因为只写工作负载远离生产工作负载。

7.3.3 访问模式的影响

我们现在评估 NetLR 在倾斜工作负载中的性能。由于我们希望看到最坏情况下的性能,我们使用最偏斜的请求分布。这意味着所有生成的请求都是针对同一个对象的。这比使用 zipf-0.9的分布更具挑战性。图 14 绘制了具有不同访问模式的三种方案的吞吐量。总体而言,NetLR 在这两种工作负载中提供了最佳性能。均匀分布的 NetLR 的吞吐量比偏态分布的高 1.16 倍。然而,对于 Hermes,分布之间的差距是 5.52 倍。这是因为读取经常因为同一对象的许多并发写入导致对象无效而停止。与 Hermes 不同,NetLR 将读取转发到最新的已知一致副本,而不会出现请求停顿。由于请求是通过链进行序列化的,因此 CR 在这两种分布中表现出恒定的性能。

7.3.4 哈希表大小的影响

我们通过改变哈希表大小来检查交换机内存对性能的影响。我们在这个实验中使用只写工作负载。这是因为写入性能高度依赖于哈希表的大小,因为同一对象的并发写入。只写工作负载是最具挑战性的工作负载,它会生成许多并发的不一致对象。回想一下,典型工作负载的写入率仅为 5%。图 15 显示了 1 个客户端和 2 个客户端情况下不同哈希表大小的饱和吞吐量。无论客户端数量如何,我们都可以看到吞吐量随着交换机提供更多哈希槽而增长。 128K哈希槽,吞吐量
达到只写工作负载的最大吞吐量。我们还注意到,较小的哈希表大小足以服务于典型的工作负载,因为工作负载仅包含 5% 的写入请求。当使用 128K 哈希槽时,NetLR 只需要 5.68% 的交换机内存。考虑到交换机一般提供几十兆内存,我们可以说NetLR需要一小部分交换机资源来跟踪不一致的对象。

7.3.5与Harmonia的比较

图16,17

我们现在将 NetLR 与 Harmonia与第 7.1.2 节中描述的典型工作负载进行比较。图 16 显示了不同吞吐量级别下的中值延迟和第 99 个百分位延迟。我们可以看到这两种方案提供了几乎相同的吞吐量。但是,我们可以看到 NetLR 和 Harmonia 之间的延迟存在差距。在图 17 中,我们发现延迟差距受写入比率的影响很大。这些结果还表明,对于动态工作负载,NetLR 通常在尾部延迟方面优于 Harmonia。这是因为 Harmonia 依赖复制协议(在本例中为 CR)来协调写入,而 NetLR 协调交换机中的写入。在 NetLR 和 Harmonia 中,每个副本都会处理两条消息来处理写入。但是,Harmonia 需要更长的延迟,因为通过链接进行写入传播。有人可能想知道如果 Harmonia 使用 PB(一种基于广播的协议)而不是 CR 会怎样。但是,由于 PB 仅使用单个领导者副本来协调写入,因此由于写入负载不平衡,性能比 NetLR 差。

8 相关工作

复制协议 复制协议可以分为基于领导者和无领导者协议。 PB是使用稳定领导者处理读写的基本协议。其他副本仅用于可用性。 CR使用不同的副本进行读写提高了 PB 的性能。 CRAQ允许本地读取 CR。 Mencius和 EPaxos是无领导者复制协议,它们机会主义地改变不同请求的领导者副本。 Hermes是最先进的无领导复制协议,它允许多个写入协调器进行本地读取和并发写入协调。 NetLR 与复制协议的主要区别在于,NetLR 是网络级解决方案,而其他都是协议级解决方案。我们的方法比协议具有优势,可以实现无领导复制,而不会因副本间协调而导致性能下降。
网内计算 网内计算是一种新兴的范式,它利用网络交换机进行计算加速。 NetCache通过在交换机中存储流行的对象数据来提供网络内缓存。 Pegasus通过与交换机的协调有选择地在服务器中存储流行的对象来改进 NetCache。 NOPaxos是一项利用开关进行请求序列化的早期工作。 NetLR 中也使用了序列化的概念。 Harmonia是最先进的交换机内复制解决方案,无需协调开销即可解决读写冲突。 NetLR 比 Harmonia 更进一步,将整个复制功能移动到网络交换机中,实现无领导复制,无需协调开销。事务分类 (TT) 是最近的一项工作,它使用可编程开关加速事务处理。与 TT 不同,NetLR 不支持事务,因为我们以 Memcached 和 Redis 等 NoSQL 数据库为目标。

9 结论

我们展示了 NetLR,这是一种复制数据存储架构,通过利用网络交换机作为网络内无领导者来实现高性能、容错和线性化复制编排器。一致性感知读取调度模块使我们能够在没有协调开销的情况下解决读写冲突。高性能写入协调模块通过消除写入协调器副本来提高单次写入的写入性能。我们的主动故障适应模块使数据存储能够快速适应故障。我们在英特尔 Tofino 交换机上实现了 NetLR 原型,并进行了广泛的测试台实验。我们的实验结果表明,NetLR 在包括 CR、Hermes 和 Harmonia 在内的比较方案中提供了最佳性能。网络内计算受到了极大的关注,我们相信这项工作通过检查交换机作为网络内复制编排器的潜力来为数据库社区做出贡献。

阅读启发

  1. 无领导复制的一些模式和pgpool很像,如读取一个写入全部。
  2. 全篇读完感觉像是给英特尔的可编程交换机打广告的。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值