Spanner针对全球范围的分布式数据中心来实现高效的分布式事务,为了解决远距离的二阶段提交的巨大延迟,它通过让服务器间同步时钟来优化只读事务。经过优化后,一个读写型是事务根据数据中心的距离将花费10到100毫秒时间完成。

FaRM和Spanner不同,它侧重于提升性能,它无法适用于数据中心分布十分远的情况,它目前还并不完善,还只是个研究原型,它探索了RDMA技术在高性能服务器领域的潜力。它适用于所有服务器都在一个数据中心,有具有一定的容错性,由于是探索RDMA技术带来的潜力,而RDMA使得系统不得不使用乐观锁来进行并发控制,此外,性能方面也得到了巨大的提升,FaRM可以在58微秒内完成一个简单的事务,相比Spanner性能提升了百倍,在Spanner中影响性能的主要因素为数据中心之间的网络延迟以及持久化数据到磁盘的时间耗费,而在FaRM通过将所有服务器都放在了一个数据中心中以此来消除了延迟,并避过了持久化数据到磁盘的步骤,瓶颈反而变成了服务器上的cpu处理时间。

在FaRM中,数据中心中的所有服务器将通过配置管理器来决定哪台服务器是primary,哪台服务器是backup,这个配置服务器可以用zookeeper来实现,但这并不是重点。在这个数据中心中,存在大量的分片,海量的数据被划分到了这些分片上,这些分片也同样会有冗余备份。当primary发生了更新,backup自然就会跟着同步,但是primary和backup之间的数据复制并非是通过paxos之类的协议来实现的。数据中心中除了这些存储数据的primary和backup,还有一些机器将作为client,client将负责发起事务向各个分片读写数据,这些client作为一个事务的发起者,还会充当该事务的事务协调器。而paper中,作者实验是将一台机器既充当了client(事务协调器)还充当了存储数据的服务器。

数据分片显然能够带来巨大的性能提升,分片越多,越多的独立操作在分片上进行。

另一方面,FaRM通过将数据都放到RAM中,日常运行过程中无需将数据持久化到磁盘上,这让性能又得到了巨大的提升。但是,不将数据持久化到磁盘上,按照过去的经验会带来数据丢失的问题,例如数据中心断电了,RAM中的数据将全部丢失。针对断电这种情况,FaRM设计了NVRAM的方案来解决。

此外,数据全部都保存在内存中,通过RDMA技术,服务间之间可以通过网卡直接读写另一台服务器内存中的数据,这种方式不会发起中断信号,不给cpu添加额外的负担,同时绕过了内核,这使得性能得到了进一步的提升。

NVRAM方案

由于数据全部保存在内存中 ,无需持久化到磁盘中,这将节省大量的写数据到磁盘上的时间,数据写入内存仅需200纳秒,而写数据到固态硬盘需要话费100微秒,如果是普通的机械硬盘那就需要10毫秒了。从这些数值可以看出带来的性能提升。

但是,遇到意外如果确保数据不丢失?

如果是一台服务器发生了故障,还有其他的replicas可以顶替。但是如果发生了整个数据中心的停电故障,似乎同地点的复制冗余也没辙了。

因此,FaRM需要解决停电情况,即使停电了,整个数据中心依旧能够工作,确保正常。它采取的措施是在每个机架上都放了一个大电池,如果发生了停电故障,那么这个电池将作为立刻为机器进行供电,但是电池容量有限,因此所有的机器应当尽快将内存中的数据持久化到硬盘中,然后再关机。当故障恢复,所有机器就可以读取硬盘上的数据来恢复状态。

因此,这个NVRAM方案并非是实现了非易失性的内存,而是通过挂载备用电池来实现了内存的数据能够及时保存下来。

但是,该方案仅针对断电情况有效,如果发生的是其他原因导致服务器故障了,例如:硬件故障、软件bug等导致了崩溃,NVRAM方案将束手无策。因此,这也是为什么还需要给每个服务器设立多个replicas的原因了。

RDMA技术

NVRAM方案解决了磁盘写慢的问题,此时的瓶颈似乎就是CPU的网络交互的过程了。

传统架构中,一个程序想要通过网络来发送数据包,需要发起系统调用,从用户态切换到内核态,并将数据从用户空间拷贝到内核空间中的socket buffer,此外数据还要经过复杂的网络协议栈,RPC的话就是需要经过TCP网络协议栈,这个协议栈包含了数据包重传、序列化、checksum、以及流量控制等机制,因此数据包需要经过复杂的加工,后续还需要通过网卡驱动来对网卡上的一对寄存器进行交互和配置,后续即可通过DMA传输数据到网卡,网卡通过网线发送bit信息。

一个程序接受数据包时自然就会有上述的倒序的步骤来处理,网卡接受到数据包后,通过DMA传输到ring buffer中,后续发送中断给内核,内核通过网卡驱动对数据包进行处理,处理后的数据将会被保存到socket buffer中,后续应用程序需要通过系统调用,进入内核态并将内核空间上的数据拷贝到用户空间中。

以上的过程十分繁杂,十分消耗CPU资源。因此,在传统的网络通信速度是十分缓慢的,难以做到每秒数十万的RPC消息传输,况且每秒数十万条RPC消息其实并不算多,相比网线的传输带宽10Gbit/s,应该是能够做到每秒数千万条RPC消息。因此,FaRM通过RDMA技术来绕过了以上的繁杂的过程,首先会介绍的是kernel bypass技术。

kernel bypass

一般来说,用户态程序需要通过调用复杂的内核代码来和硬件进行交互,但是为了绕过内核那堆复杂的流程,放弃内核的保护机制,让应用程序能够直接访问网卡上的寄存器,来实现和网卡进行交互,此时应用程序会创建发送队列和接受队列,后续就可以直接通过DMA来传输用户空间中发送队列中的数据给网卡进行发送,网卡也会接受数据直接保存到用户空间中接受队列中。此时应用程序就可以绕过内核,但是需要自己来实现TCP协议栈的功能,当然网上提供有DPDK的工具包就是提供了这个功能,而FaRM就是用了这个包。此时,应用程序和网卡可以直接使用同一块内存地址了。当前最新的网卡已经支持了这种机制。

一般来说,操作系统不会允许应用程序直接和硬件进行交互,所以这个机制也应当是需要对内核代码进行修改才行。而在Linux中,这项技术已经支持了。此外,这项技术还需要使用最新的网卡,传统的网卡是不支持这项技术的。在机器上会有多个应用程序都使用这个机制,都将会建立各自的队列,现代的智能网卡能够应付这种和多个不同的队列进行通信的情况。

RDMA

RDMA是基于kernel bypass技术的,更加激进的一种技术。全名为remote direct memory access,远程直接内存访问。有一种特殊的网卡支持RDMA,一台机器上的应用程序可以通过网卡来直接读取另一台机器上的内存,也可以直接往另一台机器上的内存上写数据,这个过程不会涉及到内核,被写数据的那台机器将对这些读写操作毫不知情,这些读写操作都是由网卡的固件来完成。用RDMA这种kernel bypass networking来进行服务器之间的数据读写交互的性能远超普通的RPC调用。

RDMA技术在传输层并非是使用传统的TCP协议,而是使用sequenced protocol。这个协议相比tcp放弃了很多好特性,但是这都是为了性能的提升,并且RDMA一般用于本地网络而非大范围的互联网情况,这种情况下,我认为在短距离的链路传输的情况下,发生数据包丢失、网络堵塞、数据错误等问题会很少发生,因此完全没必要使用TCP协议。

paper中对RDMA使用了一个术语,one-sided RDMA。当一台机器上的应用程序通过RDMA直接读写另一台机器的内存的时候,就是使用one-sided RDMA。

FaRM并不是完全摒弃RPC,而是使用RDMA的方式来实现RPC的功能,不再是通过传统网络架构将RPC请求发送给服务器,而是通过RDMA直接将RPC请求写到服务器的内存中。此外,FaRM中,一台服务器正常给另一台服务器发送数据就是通过RDMA直接在目标服务器的incoming message queue中这个指定的内存地址写数据即可。

由于RDMA网卡往目标机器内存中写数据时,不会产生任何提醒信号,目标机器需要进行轮询,定期检查内存中是否有新消息。

paper中也展示了RDMA带来的性能提升,可以达到每秒1000万次的读写操作,延迟仅有5微秒,相比使用TCP协议的RPC来进行消息传递快了太多。

上面提及了,机器使用RDMA进行写数据的时候,并非是往目标机器的内存中直接写数据。这是因为一个多分片和多replication的事务系统中,对于机器之间通信的数据并不能就这么简单接受,需要经过应用程序的复杂逻辑检查。在我们目前见过的那些replication协议中,还是实现分布式事务的机制中,客户端都无法在没有服务器帮助下完成数据读写。

例如:two-phase commit中,服务器需要判断记录是否有锁,如果没有锁就会先给这个记录上锁再对该条记录进行读写。此外,在Spanner中的分布式事务系统中,服务器上存储了多个版本的数据,服务器需要定位到指定位置去取得最新版本的数据并返回。此外,一个事务需要被提交后,那些相关数据才能算被客户端读取。

因此,服务器都会弄清楚哪些数据尚未提交或者是被锁住了,避免这些数据被客户端读取。因此,这看起来似乎RDMA并不适合有replicas的分布式事务系统,一个台机器使用RDMA直接读取另一台机器上的数据并拿来执行事务的过程可能是违法上述的规则,将会产生错误的结果,不应该把错误的结果直接写到服务器上。

但是,上述的问题似乎都是在采用悲观锁的情况,因此FaRM选择采用乐观控制锁,在该情况下, 事务的执行过程中无需考虑锁的问题,直接读取数据,并进行事务的执行,但是需要在事务提交的时候,并不会直接把数据写入,而是先把结果缓存到本地client中,后续会有一个验证阶段,验证这个事务的执行是否合法,如果执行是合法的,那么就可以将这个结果进行写入,反之则终止该事务。

由于RDMA这个快速读取的特性,FaRM被限制只能使用乐观锁,而使用乐观锁中,最值得讨论的也就是验证阶段了。

乐观锁的验证阶段

FaRM的API了解

首先我们先了解一下FaRM中事务是什么样子的,它并不支持SQL,它的API相当简单,可以通过下面简单讲解来快速了解这个事务的代码应该长什么样的。

txCreate()函数用来创建一个新的事务

txRead(OID)函数用来读取对象,后续即可在本地内存对该对象进行修改

txWrite(OID,address)函数可以将用来更新一个对象的值

txCommit()函数用来提交这个事务,并进行验证。这一部分将会涉及较多东西,也是重点。如果验证成功则返回ok;如果事务发生冲突将返回no,那么就终止事务,重点在于这个事务的重试过程中是否涉及指数补偿,因为失败的事务是立刻去重试的话,可能会有大量的事务在同一时间去抢着更新一个值,但是只有一个事务成功,其余事务终止又去重试,这将浪费大量的时间。但是paper中并未提及指数补偿这个东西,但是这个机制很有意义,就好比raft中的randomization算法。

FaRM的API更接近于NoSQL数据库的API,没有SQL中那些join操作,那些花式操作。它的接口操作都是十分底层。因此,可以看作是带事务的NoSQL数据库也行。

txRead()函数用于读取指定OID的对象,OID就是对象的标识符。这个OID是一个复合标识符,有一部分为区域编号用于标识对象所处的区域。在FaRM中所有服务器的内存总体会被划分为不同的区域,配置管理器会记录每个区域编号对应的服务器,因此可以根据OID中区域编号来查表,找到这个区域编号对应的primary服务器和backup服务器。OID还有一部分为内存地址,那台服务器上的物理内存地址。RDMA网卡根据这两个信息,将找到指定服务器并定位指定的物理内存地址。

FaRM服务器的内存

每个服务器负责一个区域编号的内存区域,或者多个区域编号的内存区域。

在每个region的内存中存放了很多对象,每个对象的数据结构如下所示,有一个header,这个header包含了这个对象的版本号,而这个版本号的字段的首个bit还作为lock标志位,其余bit位表示该对象的版本号。其余部分便是该对象的内容了。

每次对一个对象进行修改时,都需要将该对象的版本号加一。

此外,每个服务器内有多个日志,每个日志对应数据中心的一个服务器,日志的数量取决于数据中心的服务器的数量。当该服务器想要和N号服务器进行通信,让N号服务器执行事务的某些操作,那么仅需将操作写到本地的N号服务器的日志中,同时还会将该日志追加到N号服务器的内存中。

同时每个服务器应当还要保存一组非易失性日志,就是在断电后,日志的内容将持久化到硬盘中。这些非易失性日志中的数据能够确保服务器重启后恢复状态。

每个服务器还可能有一个RPC消息队列,这个队列负责处理RPC那样的通信请求。此外,还会有一个incoming message queue,这个消息队列就是提供给其他服务器写数据的地方。

OCC提交协议

下面根据这张图来讲解OCC提交协议。首先执行阶段,客户端C开始一个事务的执行,对于P1和P2服务器上的数据涉及读写,对于P3服务器上的数据是只读的。

客户端C通过txRead()从P1、P2、P3读取了对象,获取了对象的初始的版本号,后续完成了事务的处理,并通过txWrite()对各个对象的值进行修改,后续便是通过txCommit()对该事务的结果进行提交。

客户端在这个流程中还充当了事务协调器的角色。后续机器C开始事务协调器的工作:

1、C发送LOCK消息给涉及修改的数据的服务器。通过给P1和P2的incoming message queue处直接写入更新后的对象,并将其作为P1和P2的一个日志条目,这个日志条目中的内容为对象原本的version和修改后的值。

P1和P2会不断轮询自身的日志,发现有新的日志则进行处理,发现日志要求修改的对象已经被上锁了,或者日志中对象的原本的version值和对象的当前的version值不符(表明这个日志中的请求是过时的,读取到的数据都是旧的)都会返回no,这将使得该事务被终止。如果发现对象没上锁,对象的version值也是对得上,那么就将对象上锁。整个检查版本号和锁的情况,并上锁的操作是一个原子操作,因为服务器都是多核处理器,可能CPU在并行处理多个事务,但是都需要对同个对象进行上锁修改。因此,作者才将对象的数据结构中的版本号字段的首个bit作为锁的标志位,可以用CAS(compare and swap)这个原子操作来对版本号和lock标志位进行操作。

如果事务协调器收到有一个no,则终止该事务,并告知所有参与者。

如果收到全部都是yes,则进入下一步。

2、对于读取对象而言,验证这一步骤是一种优化。C事务协调器需要去P3服务器检查事务提交时,读取的对象的版本是否发生了变化,因为事务的修改结果和读取的对象的值有关,如果发现P3处的对象的版本发生了变化或者是对象已经被上锁了,则表明当前事务使用了过时的对象,则需要终止。若发现版本没有发生变化则进入下一步骤。

3、步骤3类似步骤4,只不过把primary服务器变为了backup服务器。

4、C会给每个primary服务器的日志中添加一个commit的条目,C此时仅需收到RDMA网卡提示成功将commit条目写到服务器上即可,无需等待primary服务器去处理完成这个commit日志。只要成功给每个primary服务器都写入commit日志后,后续即可进入下一步。

primary服务器在轮询日志中,发现这个commit日志后,即可将根据日志将对象的数值更新,版本号加一,同时释放锁。

5、C会告诉P1和P2服务器可以丢弃该事务的日志,由于P3服务器仅仅只是读取上面的对象数据,并没有修改也就没有往上添加日志,因此无需通知。

如果是只读事务的话,那么就不需要经历lock、commit和truncate阶段,仅需在validate阶段使用one-side RDMA进行读取验证即可,因此只读事务的处理速度将会非常快。

总结

FaRM中进行读取数据是十分简单粗暴的,因为它使用了RDMA,同时还使用了OCC,但是OCC要求事务的冲突较少,如果一直冲突发生,那么可能就要终止事务。此外,FaRM还有很多限制,例如全部数据必须放在内存中,所有服务器必须放在一个数据中心,硬件上依赖NVRAM方案,同时还需要使用RDMA网卡。

6.824:FaRM笔记相关推荐

  1. MIT 6.824 学习笔记(一)--- RPC 详解

    从本文开始,将记录作者学习 MIT 6.824 分布式系统的学习笔记,如果有志同道合者,欢迎一起交流. RPC 的定义和结构 RPC 全称为 Remote Procedure Call,他表示一种远程 ...

  2. MIT 6.824学习笔记

    introduction 为什么需要分布式计算? 并行,容错,物理因素(地理位置),安全 分布式计算面临的挑战? 并发性,部分错误,性能问题 基础设施 存储,通信,计算----目标是抽象成从外部看上去 ...

  3. Sharepoint学习笔记--Farm Backup Error:Administration 2010 Service is not started

    做了一段时间的Sharepoint项目,今天在做Farm 备份时,出现如下错误: 这是由于没有启动 "Share point 2010 Administration"服务,导致备份 ...

  4. animal farm 第一章阅读笔记

    chapter 1 Old Major's dream. paragraph 1  //Mr Jones is the mastor of the Manor Farm.That night  he ...

  5. 《Animal Farm》笔记

    动物 boar 种猪 sow n.母猪:v.播种 mare 母马 mane 鬃毛 pigeon 家鸽:dove 和平鸽 raven / crow 乌鸦 cockerel 小公鸡 poultry 家禽 ...

  6. 6.824 2020 视频笔记五:Go Concurrency

    作者:穆尼奥 链接:https://zhuanlan.zhihu.com/p/138199791 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 内存模型 用线程有两 ...

  7. 笔记 MIT6.824 Lecture 17: COPS, Causal Consistency

    目录 前言 一.geo-replication 1.1 Spanner 1.2 Memchche 1.3 新的需求 二.预备方案One 三.预备方案Two 四.COPS 五.limitations 总 ...

  8. <笔记1>matplotlib绘图工具笔记

    matplotlib绘图工具笔记 python中有许多非常方便的可视化工具,例如matplotlib,seaborn等.在这里主要总结matplotlib的简单绘图方法. 设置图形的大小和中文显示,图 ...

  9. Sharepoint学习笔记---Sandbox Solution-- Full Trust Proxy--开发实例之(2、在Webpart中访问Full Trust Proxy)...

    上一篇Sharepoint学习笔记---Sandbox Solution-- Full Trust Proxy--开发实例之(1.创建一个能访问DataBase的Full Trust Proxy), ...

最新文章

  1. iOS自动化探索(九)使用Jenkins自动化打包并发布iOS App
  2. linux 设置变量在脚本之外可用,linux – 在ssh上运行脚本时,环境变量不可用
  3. PHP用支付宝沙箱账号测试支付功能
  4. sap gateway development mode
  5. cloudfoundry_在Cloudfoundry上部署RESTful服务
  6. web前端常用知识点
  7. 工作笔记-SDRAM的读写
  8. 设置 Web 服务器控件颜色属性 转
  9. Linux Makefile自动生成--config.h
  10. 新站快速收录同时也提高内页的收录
  11. 【BZOJ-3573】米特运输 树形DP
  12. C#操作Excel数据库方法
  13. 2022年申请亳州市发明专利材料,专利说明书摘要写作技巧
  14. QT修改releas发布的exe图标
  15. UVa 10015 - Joseph's Cousin
  16. Shiro源码剖析——Subject的创建与获取(一次完整的请求执行流程)
  17. python气象卫星云图解析_02_中央气象台
  18. 将自己常用的Ubuntu18.04备份为ISO文件,保留私人配置与文件
  19. matlab网孔电流法,网孔电流法解题方法
  20. 【elasticsearch】【Kibana】7.6.2版本kibana启动失败master_not_discovered_exception

热门文章

  1. linux搭建 eth节点,Ethereum全节点搭建
  2. 记一次Y7000P内存升级(骇客神条套条),让电脑飞起来~
  3. 尼尔机械纪元房顶机器人_尼尔机械纪元辅助机器人是什么 辅助机器人解析攻略...
  4. 安卓按键精灵手机助手(功能:安卓版抓抓、命令库、制作电脑UI界面)
  5. i.MX283开发板移植RTL8188ETV无线网卡驱动
  6. Linux 系统安装后优化项常见操作
  7. Unknown Faceted Project Problem (Java Version Mismatch)
  8. Ubuntu系统配置共享打印机及Windows连接教程
  9. JAVA计算机毕业设计网课系统(附源码、数据库)
  10. 四川大学计算机科学保研夏令营面试面经