Well, Hello There!


  • 22 Jun 2021
    毕业四年记

    毕业四年记 如果我们不曾相遇 如果我们不曾相遇 我会是在哪里 如果我们从不曾相识 不存在这首歌曲 每秒都活着 每秒都死去 每秒都问着自己 谁不曾找寻 谁不曾怀疑 茫茫人生奔向何地 那一天 那一刻 那个场景 你出现在我生命 从此后 从人生 重新定义 从我故事里苏醒 如果我们不曾相遇 你又会在哪里 如果我们从不曾相识 人间又如何运行 晒伤的脱皮 意外的雪景 与你相依的四季 苍狗又白云 身旁有了你 匆匆轮回又有何惧 那一天 那一刻 那个场景 你出现在我生命 每一分 每一秒 每个表情 故事都充满惊奇 偶然与巧合 舞动了蝶翼 谁的心头风起 前仆而后继 万千人追寻 荒漠唯一菩提 是擦身相遇 或擦肩而去 命运犹如险棋 无数时间线 无尽可能性 终于交织向你... Read more!

  • 11 Jun 2021
    LogStore -- A Cloud-Native and Multi-Tenant Log Database

    LogStore: A Cloud-Native and Multi-Tenant Log Database 0x00 基本内容 这篇Paper是将要发布在SIGMOD ‘21上面一排关于Log存储的一篇。LogStore像是一种特别类型的AP系统,其的基本架构如下图,其架构称之为cloud native的,很多基础的组件依赖于云厂商自己的一些系统。LogStore为一个shared data和shared nothing结合的一个设计,且计算和存储分离。主要的存储使用了对象存储服务。LogStore写入的数据实时可见,因为它将最近写入的数据保存到本地的磁盘上,然后通过Raft来复制多个副本。随着数据的持续写入,本地磁盘上面的数据会最终被上传到对象存储OSS上。 数据保存到本地磁盘上面的时候会以write-optimized row-oriented的存储格式保存,不会建立上面索引之类的。在数据写入OSS之前,LogStore会对其进行重新组织,组织为一种 read-optimized column-oriented indexed的格式,称之为LogBlock,并压缩。这个LogBlock根据不同租户和日志产生时间戳来划分。在主要的组件上,Controller来负责整个集群的管理;Query Layer会根据用户的查询请求生成directed acyclic graph (DAG)模式的一个执行计划。这个查询计划会被划分为sub-queries方法到后面的Execution Layer;Execution Layer要处理最近数据的写入,以及将增长了的本地数据转存到OSS上。查询的时候要负责执行计划的具体执行。后面的存储层直接使用已有的对象存储服务OSS。 0x01 Multi-Tenant 这篇Paper中,从标题和内容都强调了其Multi-Tenant的一些特性。在cloud的环境中,不同的tenant之间的workload差异是很大的,比如大部分的tenant都是较少活动,而少数的tenants贡献了大部分的数据;比如流量的不均衡性特别突出等。因为这样,Paper中中也较多地描述了LogStore在load balance方面的一些设计。因为不均衡的特点突出,LogStore使用根据运行时候的情况来动态负载均衡。负责均衡上关于global traffic control,LogStore使用的方式示意如下图。其会将系统抽象为一个single source/single sink flow network G(V , E),这个network中节点表示某种角色,边表示流量。抽象之后,将load balancing变成了一个最优化的问题,其的目标是最大化从源到目的T的流量,满足的限制条件主要有要最小化请求/流量routes,另外要满足一些容量限制,比如一个节点上的资源利用率不能太高等。 LogStore是根据前面的建模,然后根据其traffic control的算法来算出Router的table,Broker在方法任务到Worker的时候,根据这个table来作出方法任务到哪里的决策。其global traffic control的framework表示如下图。下图的HotSpot Manager实现在Controller这个组件中。其运行的时候,首先是要一个Monitor来获取运行时的一些信息,比如一个tenant的流量f (Ki ),shard的负载 f (Pj ),一个worker节点的负载 f... Read more!

  • 09 Jun 2021
    PolarDB Serverless

    PolarDB Serverless: A Cloud Native Database for Disaggregated Data Centers 0x00 引言 这篇paper也是即将发表在SIGMOD ‘21上面的一篇Paper,关于数据库disaggregation的一个设计。Disaggregation是最近系统方向的一个热点的研究方向,其核心思路是可以理解为各类资源,比如CPU、Memory以及Storage Resource等,分离并独立管理,实现按需分配。在PolarDB这样的cloud native,其本来是一个存储、计算分离的涉及,但是计算节点上面CPU和Memory还是在一起的,进一步Disaggregation的设计就是如何将这个CPU和Memory的资源也分离。这样带来的好处就是资源更新方便贡献,按需调度,可以实现更快的failover(achieves better dynamic resource provisioning capabilities and 5.3 times faster failure recovery speed),同时实现和只存储计算分离方式差不多的信念。但是性能还是有下降的,根据在ChinaSys上的Presentation,基准测试中性能下降在百分之十几。其基本架构的示意如下图所示。 PolarDB的基本架构如下图,其是一个模仿Aurora的设计,但是存在一些不同。其核心是将MySQL写本地的磁盘改成写一个专门开发的分布式文件系统PolarFS。系统运行事务的时候:1. 写入/RW节点只有一个,写操作操作flush redolog到下层的fs之后,事务即可以commit;之后异步将redolog最新的LSN信息广播给其它的read-only/RO的节点;RO节点在收到这个信息之后,从fs拉取新的redo log来在本地重放来实现对本地buffer pool中的数据进行更新;RO也需要将自己目前redolog消费到哪里的信息提供给RW节点,这样RO节点都消费了的redolog就可以安全地删除(要dirty pages被flush到下层的fs)。这个存储层的交互和Aurora存在比较大的差别。一个RO节点如果是snapshot读取一个较老的版本,可以直接读fs中的pages。可见RO节点消费redolog的速度太慢会影响到RW节点。 0x01 基本设计 将CPU和Memory分离,PolarDB Serverless的做法是将将远程的内存作为一个remote memory pool。带来资源利用率提高的同时也带来了几个问题:一个是remote memory还是比不上本地的,这样就需要一种分层的内存设计和预取的机制;另外一个是不同节点可能访问同样的内存资源,就需要一种互斥的机制;还有一个是page数据的加大了网络流量,这里优化为其它类似系统在存储层将redo log异步转化为pages的功能。这里提出来的是一组remote memory access的接口,如下所示: // increases the page’s reference count... Read more!

  • 07 Jun 2021
    Transaction Optimzations in CockroachDB

    Transaction Optimzations in CockroachDB 0x00 Parallel Commit CockroachDB在事务优化方面,在开源的分布式数据库中,是做的比较多的。比如引入了Parallel Commit、Transaction Pipelining、1PC、Non-blocking Transactions等诸多的优化,这些优化好像也影响了后面一些系统的优化策略。以Parallel Commit为例,因为CRDB使用类似于Percolator的2PC的执行方式,其要进行网络交互比较。Parallel Commits操作则使得commit的操作可以异步执行。其优化的思路来自于:一个如果一个事务的所有写入内容都被复制完成之后,2PC的第一步prepare返回了ok,则后面的commit操作是一定能够完成的。所以到了这里就可以先返回成功再去实际地/异步地commit。为了实现这个功能,CRDB引入了一个staging的事务状态,表示一个事务操作的所有写入是否都复制完成了。在Paper[1]中提交到的数据,这个优化取得的效果很明显。其基本思路如下图,其写入的时候: 按照CockroachDB基本的分布式事务流程,会先创建一个事务状态记录,transaction record。CRDB选择在第一个range写入这个状态记录估计也是方便来实现在第一个写入操作的时候和事务状态记录一起创建。在引入了 Parallel Commit 和 Lazy Transaction Record Creation优化之后,这个方式存在了一些变化。如下的一个事务流程,在使用Parallel Commit的时候,第一个操作写入一个key “Apple”。第一次写入操作的时候并不会创建一个事务状态记录,写入这个write intent包含指向事务状态记录的信息此时并不存在。每个write intent会赋予一个唯一的sequence number 。另外在CRDB引入了Transaction Pipelining的优化之后,写入的操作可以在操作没有完成的时候就进行事务后面的操作。在写入第二个key “Berry” 时,操作的过程和写入第一个的一样,如果使用了Transaction Pipelining也不需要等待write intent的写入实际完成。 后面进入事务commit的操作过程。Client在发送了一个client的指令之后,Coordinator会创建一个staging状态的事务状态记录,并在其中记录下这个事务会写入的key列表。在等待写入操作都完成之后即可返回。事务状态为staging且所有写入都完成的时候,实际上就是一种implicitly committed,而事务状态为committed为一种explicitly committed。而对于读操作,遇到了staging状态的事务写入的write intents,读取操作会先确定相关的事务是否在正常进行过程中。这个通过coordinator和状态记录之间的heartbeating来确定。如果是,则读取操作对应的事务会等待。 另外和事务commit相关的优化为1PC 优化,这个优化在很多的2PC方式中都会用到。基本上就是一个事务只会涉及到一个range的时候,就是一个非分布式事务的commit操作,可以直接1PC操作完成。 上面描述的过程,实际上是一个Parallel Commit,Lazy Transaction Record Creation 和 Transaction Pipelining几个优化同时使用的一个操作过程, Transaction Pipelining体现在两次写入操作之间,后面没有依赖于前面的写入可以不用等到前面的写入完成之间操作。Lazy Transaction... Read more!

  • 03 Jun 2021
    Optimzations of Distributed Txn With TSO

    Optimzations of Distributed Transaction With TSO 0x10 TiDB Async Commit 前面提到TiDB使用的方式基本沿用了Percolator的方式,这种方式的一个特点是网络交互次数较多。Async Commit顾名思义就是将2PC中,第2步的commit操作异步化,意味着返回给client就prepare完成即可以了。Percolator的方式中,一个事务的状态有primary key确定,如果要改成异步commit的话,意味着需要在prepare这一步完成之后,就可以知道事务的状态。考虑一个prepare返回协调者就crash的情况:一种情况是协调者知道了事务可以正常commit,但是没来得及commit,也可能参与者都返回了ok但是还没有收到就crash;另外一种情况是协调者收到了不能commit的信息,但是也没有来得及abort。后面其它的操作看到了这个事务遗留下来的信息,需要可以从其中恢复出来,这样就需要: 这个事务是可以commit还是不可以commit。一个操作在看到一个状态不确定的数据时候,就需要知道对应事务所有写入数据的状态。由于之前在非primary key上面保存了primary key,这样继续在primary key的信息里面,保存上这次事务其它的keys,就可以根据这个信息取一一询问。这里可以看出这种方式适合OLTP的应用场景,对大事务不是很适合; 可以commit的时候,和这个事务commit ts是什么。这里对commit ts有两个要求:一个是这个commit ts必须体现事务之间的commit的顺序,另外一个是这个commit ts不能太大,因为后面读操作的时候能改立即读取到committed的数据,又读取操作获取的start ts是从TSO而来,这样要求commit ts不能大于TSO已经分配的ts+1。为了实现这些要求,这里在TiKV上维护了一个max ts,另外在prewrite操作的时候,这个请求携带了一个从TOS获取的prewrite ts。KV的节点在收到请求之后,如果本地的max ts小于这个prewrite ts,需要增大这个ts。KV节点持久化prewrite的数据,并记录下min commit ts为max ts。KV节点给DB节点返回的时候,会带上这个min commit ts。事务commit的时候,选择commits为min commit ts中最大的一个。 对于只读的事务,其操作也会导致KV节点上面的max ts 更新。KV节点接受到只读操作的时候,会根据请求带上的start ts更新增大max ts。这样后面写操作选择的一个min commit ts至少为max ts +1。这样后面的事务commit之后,不会破坏前面的snapshot读操作的snapshot语义。引入了Async Commit之后,如果一个事务知涉及到了一个KV节点,就可以使用1PC的方式。Commi ts用前面同样的方式得出。 另外一个在Async Commit的设计文档中,谈到了其和副本读的一些兼容性。因为现在commit ts可能从KV节点得出(虽然最终的来源还是TSO),而且读操作也会推大节点上的max ts。为例保证读的snapshot语义,需要副本也感知到这些变化,读副本的时候也需要更新这个max... Read more!

  • 27 May 2021
    Distributed Transaction from Research Papers

    Unifying Timestamp with Transaction Ordering for MVCC with Decentralized Scalar Timestamp 0x00 基本思路 这篇paper是关于不使用中心化的TOS服务来实现分布式的MVCC的一种方式。其思路通过前面的一些方式的优化之后其实就可以得出一个大概。Paper是提出了一种不使用vector timestamp,也不使用中心化的TOS的MVCC的实现方式。Paper中描述了使用中心化的TSO实现MVCC的基本思路。其方式前面谈到的使用一个中心化transaction manager实现的思路是一样的,下面是用这篇paper的语言来描述。 // 2PL with global timestamp (GTS) At Oracle: GlobalTS, StableGTS, Queue // monotonic global timestamp, snapshot global timestamp, pending global timestamp INSTALL(gts): add gts to Queue STABILIZE(): // run asynchronously for each gts in... Read more!

  • 19 May 2021
    Distributed Txn Without Centralized Sequencer/TSO

    Distributed Transaction Without Centralized Sequencer/TSO 0x00 Spanner: Google’s Globally Distributed Database 这里总结的是分布式事务在没有一个中心化的Sequencer/TSO下如何实现。关于这个部分,影响最大的也是来自Google的一篇paper,即Spanner在OSDI ‘12上面发表的这篇。其核心思路是在引入了一个不确定的时间区间,然后通过使用atomic clock来尽可能得降低这个不确定的时间区间并保证这个不确定的区间在一个确定的bound内。差值在这个bound之外的timestamp,Spanner就可以直接知道timestamp之间的先后关系,在这个bound之内的,Spanner会在实现上处理这个问题,从而实现了完全分布式的时钟,满足linearizability。Spanner数据保存到分布式文件系统之上,这个和一些开源实现直接使用本地的KV Store存储数据不同。同样其也需要讲这个的key range拆分为更小的的部分,称之为tablet。每个tablet对应到一个paxos group来实现多个副本的存储。在这样的基本架构之上,对于读写事务: 一个paxos group中会有一个leader,处理paxos的一些逻辑之外,其还会维护一个lock table和实现transaction manager的一些功能,这个和事务功能相关。事务读取操作的时候,会讲读取请求发送到对应group的leader,加上一个read lock之后如何读取数据。Lock需要知道放弃事务的client还是存活的,所以会定期发送keepalive的消息来告知leaders事务还是存活的。数据的写入都是先buffer在本地。在commit的时候,使用2PC提交的方式进行:1. Spanner中一个事务会选择一个paxos group的leader作为Coordinator,协调者,然后向所有的所有参与的paxos group的leader发送一个commit的消息,消息中包含选择的协调者的ID以及要写入的数据。非协调者的leader在收到消息之后,先请求write locks,然后选择一个prepare timestamp,通过paxos写入一个prepare record日志。后面每个参与者会通知coordinator其选择的prepare timestamp。选择这个prepare timestamp都是要求必须大于之前赋予其它事务的timestamp,即严格增加的特性。也可以看出Spanner的一个特点是一部分协调的工作是client来完成,client直接广播消息,这个应该是考虑到spanner为广域网/全球部署设计的。 Coordinator同样会申请write locks,但是不会处理prepare phase。在收到其它leader的消息之后,选择一个timestamp作为commit的时间戳。这个commit timestamp必须要 >= 其它leaders选择prepare tiestamp,也要求大于此时它收到过的commit消息时刻的TT.now().latest,还要大于其赋予之前事务的任何timestamp。Coordinator通过paxos写入一个commit记录。此时,commit事务不能马上apply,来完成对事务的commit,还需要一个等待的操作,需要等到TT.after(s)成立之后。之后Coordinator发送commit timestamp给client和其它的participant leaders。每个participant leader在收到这个消息之后,写log记录下事务的结果。然后使用相同的timestamp来apply操作,并释放锁。 Spanner的读写事务中读写操作都需要加上对应的locks,这个应该是为了处理读写事务之间的读写冲突问题。而其另外支持的read-only事务和snapshot -read,都是不需要加锁的,其利用MVCC来实现读写事务和只读事务之间的读写不相互阻塞。这样Timestamp管理是保证事务正确性的重要内容。Paxos group中的leader通过lease来维护一个和不会给后面可能的leader切换之后重叠的lease interval,默认情况下每个lease长度为10s,在一次写入操作时候默认被续约。Leader切换之后,后面的leader需要等待前面leader最大的租约内的时间戳S-max满足TT.after(smax)成立。对于一个写入事务,其使用2阶段锁的方式,timestamp可以在所有锁被获取之后、任何锁被释放之前赋予。Spanner关于tiemstamp更多的一些东西: Spanner是满足external-consistency的系统,可以保证后面开始的事务可以看到先提交的事务的修改。对于tiemstamp,就要求如果一个事务T2开始在另外一个事务T1 commit之后,要求T2的commit时间戳必须小于T1的commit时间戳。即一个事务ti start event和commit event的绝对时间为ti-start-abs-ts和ti-commit-abs-ts。即这样要求t1-commit-abs-ts <... Read more!

  • 11 May 2021
    Distributed Txn With Centralized Sequencer/TSO

    Distributed Transaction With Centralized Sequencer/TSO 0x00 Large-scale Incremental Processing Using Distributed Transactions and Notifications 使用2PC的方式或者是某种2PC的变种方式,与一个中心化的Sequencer,或者是称之为Timestamp Oracle,来作为一个发号器或者是一个全局的时钟,是实现分布式事务的一种方式。很多的这类系统使用的并发控制方式为MVCC,这个中心的全局时钟会和MVCC也强相关。这种方式的一个优点是一些逻辑处理上会比没有中心时钟的要简单,一个缺点是由于事务的进行都需要访问这个中心的时钟,这样系统跨区域部署时候会不太适合。比较。在使用这样的方式的系统中,Percolator这篇Paper是分布式事务设计一般影响比较大一篇,后面很多的设计都是在此的基础上进行变化、改进。Percolator是一种2PC处理分布式事务的方式,其基本的设计核心点有这样的几个: Percolator也是利用一个中心话的Oracle来获取时间戳,实现Snapshot Isolation的隔离级别。在读取开始的时候获取一个时间戳称之为start ts,在事务要commit的时候获取一个时间戳称之为commit ts。读取操作读取到start ts为止的最新的版本,如果读取这个版本带上来锁,则要查看这个锁的情况:如果没有超时则需要等待,等待这个锁超时 or 被解除;如果这个锁超时了可能写这个版本的事务没有成功提交,也可能还没有提交。这里读操作会有一个尝试清除这个锁的操作。利用这种方式来解决写事务故障之后没有清除之前写入数据,加的锁的问题。 Percolator的存储是利用Bigtable,一个分布式的表格系统,Key-Value的value为多列的结构。Percolator利用这个特性, 每个key对应的value又以下这样列:lock列记录锁的情况,对于没有提交的事务这个会记录为primary key的位置,对于primary key记录自己为primary的信息,write列保存已经commited的最大版本,data列记录这个版本对应的数据。另外的notify列和ack_O和事务关系不大。这样Percolator的一个事务的提交与否就是通过primary key来确定来,利用了Bigtable支持单行事务的特点来将其作为一个事务是否commit的一个“开关”,而其它的key就保存这个primary key的信息即可。 这样,Percolator的有写操作的事务写的数据都先缓存在本地。事务commit的时候从其中选出一个作为primary,然后写入数据的时候先写入primary,如何写其它的行。每行写之前要检查冲突,基本的方式是检查一行的write列释放存在版本在[start ts , ∞]之间的commited or 活跃的事务,或者是版本在[0, ∞]之间,即任何加锁的版本,如果存在则由于写写冲突无法提交,地abort,基本方式是清除已经prewrite的数据。Prewrite写入的数据为data 和 lock,lock保存的为primary的信息。这样的设计下面,Percolator事务的状态信息,锁信息都是和数据保存在同样的地方。 在priwrite完成之后进入commit的流程,基本的方式是尝试提交primary行。由于锁可能被其它的操作清除,在提交之后要检查锁是否已经被清除,通过写入write列数据,这行写入write列的数据对用的start ts,这样就可以找到这行数据start ts的版本并从中读取到数据;并删除lock列即完成提交操作。Primary完成提交之后事务即可以完成commit,其它行数据的提交可以异步进行。而读操作看到这些没有提交的行的时候,可以实际上已经提交了,方式是通过其中记录的primary行的信息去获取对应事务的状态。这样相当于把事务状态的信息就记录到Bigtable之中,没有利用其它的组件。 0x01 Omid 的设计 Omid是在HBase上面做的一个支持分布式事务的系统,其系统类似于前面的Percolator,其实现有很多事类似,但区别还是有不少的。Omid中分布式事务的实现也是使用MVCC,实现Snapshot Isolation的隔离级别。在具体的设计上面,Omid有这样的一些特点: 使用中心化的timestamp发号器,称之为transaction status oracle,SO。Omid事务开始的时候,也会去获取一个start ts时间戳,数据读取的时候根据这个start... Read more!

  • 07 May 2021
    FoundationDB -- A Distributed Unbundled Transactional Key Value Store

    FoundationDB: A Distributed Unbundled Transactional Key Value Store 0x00 基本内容 这篇paper描述了FoundationDB整体的一些设计。FoundationDB的基本架构如下。其基本架构和一般的类似相同没有很大的部分,Control Plane负责处理元数据,里面包含多个角色。比如Coordinators其作为哟个Paxos Group存在。其会选举出一个ClusterController,负责监控集群的情况,另外会创建三个进程,分别为 Sequencer, DataDistributor, 和Ratekeeper,分别处理做为一个发好器、监控storage servers的情况以及处理overload protection的问题。在Data Plane方面,这里一个特别是使用了3个组件,和类似的系统对比,多出来一个Log System,LS。LS负责保存来自TS的 Write-Ahead-Log,这个TS为transaction management system (TS),负责处理事务的逻辑。TS中也会有一个Sequencer,另外的足迹为, Proxies 和 Resolvers。TS的Sequencer负责从这里获取read version和commit version的timestamp。Proxies负责处理事务的读写和commit,resolver则主要用于处理事务之间的冲突。StorageServer为一个range分区的存储节点,存储使用的是SQLite的一个修改版本。和多数的类似系统一样,其并发控制也是使用MVCC的机制,另外FDB是没有依赖其它的外部系统的。 0x01 事务 对于一个支持分布式事务的系统来说,其事务处理的流程是一个核心的部分。在FDB中,事务处理的开始由client向一个proxy发送一个请求,获取一个read version开始,即一个read timestamp。这个read version为proxy从sequencer获取,保证每次获取的version都是递增的。在获取了这个timestamp之后,client可以直接向storage servers发送读区请求。而一个写入的数据会暂存到本地的buffer中。在后面commit的时候,将写入的数据,包括read set和write set的信息,发送到一个proxy。Proxy处理事务提交的请求,如果不能提交,向client返回abort的信息,client可以选择重试事务。 FDB commit的流程:1. 从sequencer获取一个commit version(Sequencer chooses the commit version advancing it at a... Read more!

  • 30 Apr 2021
    Vector Quotient Filters, Chucky and Conditional Cuckoo Filters

    Vector Quotient Filters: Overcoming the Time/Space Trade-Off in Filter Design 0x00 基本思路 这篇Paper是将要发表在SIGMOD‘21上面一篇关于Filter的文章。Vector Quotient Filters的设计也是使用多个hash函数的设计,每个hash用于寻址一个block,称之为mini-filter。每个mini-filter在内部被划分为多个buckets,bucket保存fingerprint。对一个hash函数计算而来的一个hash值,其拆分为一个logb-bit 的bucket index,以及一个r-bit fingerprint。设一个key到一个bucket的映射关系为β (x ),到一个fingerprint的映射为f(x),添加一个key的过程就是将f (x ) 到bucket β (x )的过程,这样就可以从f(x)和β (x )恢复出f(x),即根据一个fingerprint保存的问题恢复出其完整的hash值。Mini-filter的基本结构如下,可以看出每个item x/key可以选择的block为2个,每个blocks中分为两个主要的部分:第一个部分为metadata bits,另外一个为fingerprint bits。在这样结构上的基本操作: 一个min filter的metabits部分保存一个(b+s)-bit bucket-size vector,一个最多支持s个fingerprint。另外的fingerprint bits部分就是保存实际的值。这样设计的一个原因是如果直接使用保存s个rbit的fingerprint的,那么hash冲突就很难处理,每个位置只能保存一个fingerprint。而如果使用固定大小bucket的话,空间利用率会很低,因为很难bucket里面的数据都塞满。这里通过metadata bits和fingerprint bit的组合来实现一个逻辑上不定大下的bucket。每个bucket的边界划分则是根据metadata bits来的,可以从其中看出来,metadata bit中bit 1表示一个bucket边界,前面多少个0表示这个bucket里面有多少个fingerprint。由于metadata bit都是1bit的,消耗内存不大。 所以在这样的结构上面,定义一个select操作,和一些succinct结构类型。select(m,i)表示在bit串m上第i个1的位置,比如select(001000000,0)=2。这样第j个bucket出现的第一个fingerprint的位置为select(m,j−1)−j。对于j > 0 的情况其fingerprint的范围为[select(m,j−1)−j+1,select(m,j)−j),为0时候,开始index为0。这些计算可以通过x86 PDEP之类的特殊指令直接计算。添加一个key的时候,先尝试讲对应的fingerprint fp添加到bucket b,fp选择的位置为select(m,b)−b,后面的数据也顺序往后移动。选择bucket的时候,有2个候选位置,选择更加空的一个。如果都满了会导致添加失败。这个可能添加失败的特性在一些情况下会是一个问题。 Vector... Read more!

  • 25 Apr 2021
    YugabyteDB -- A Distributed SQL Database

    YugabyteDB: A Distributed SQL Database 0x00 基本架构 YugebyteDB,YDB,也是一个开源的NewSQL的设计,和前面的CockroachDB有很多类型的地方,也有很多不同的地方。YDB和CRDB、TiDB之类的一样,总的来说还是模仿F1和Spanner的一个设计,总体架构上也分为实现SQL功能的查询层,YDB这部分称之为Query Layer,实现分布式存储功能的存储层,YDB这部分称之为DocDB。不同的是,YDB查询层和存储层部署的时候就是在同样的节点上面的,没有进行物理上的分离。YDB中对于一个table,也是划分为若干的tablet来保存,划分的方式只是range or hash的方式,一个tablet包含不同的一些部分。在YDB分布式事务的实现也是使用HLC,使用MVCC的方式,实现snapshot和serializable的隔离级别。YugabyteDB的一些特点: YDB使用的在实现上使用了C/C++,理论上可以比一些使用Golang的有更好的实现上的一些优化空间?在Query Layer,支持兼容PostgreSQL的SQL语言外,还支持Cassandra使用的一种CQL。YDB也就是不仅仅支持SQL的模型,还支持文档的模型。兼容PostgreSQL是因为SQL相关的实现好像就是直接从PostgreSQL改来的。总的查询相关的称之为YQL。存储层则使用了RocksDB作为存储。YDB查询层和存储层实际上是部署在一起的,部署在一起称之为Tablet Server。这个是和其它类型数据库一个不同的地方。其特点也可以在下面的关于事务的部分看到。 YDB中无论是SQL的模型还是文档的模型,最后都会被表示为Key-Value的形势保存到RocksDB中。其编码KV到方式如下图。Key中包含了3个部分,DocKey子部分包含一个16bit的hash,这个16bit的hash也涉及到YDB一个设计特点。以及主键key,可能使用hash划分 orrang划分的方式。另外SubKey部分对应到tuple中的列。最好的部分为hybrid time 加上write id,这个write id作用在后面会提到。YDB在使用RocksDB的时候只是简单的利用了其key-value存储的功能,好像其持久化保证的WAL,以及事务都不需要,有YDB自己来保证。 这里YDB的一个设计特点是其tuple中每个列都会对应到一个key-value,和一般整个tuple作为一个value的方式不同。可以猜测一下其优点是更新的时候可能可以选择更新,读取部分数据时候额外开销更小,而缺点是可能导致保存的数据量变大,要读取全部的数据时候开销增加。存储数据量可以利用RocksDB的前缀压缩的功能,可能实际上带来的开销不会很大。另外key前面16bit的hash表明了YDB涉及的时候,即使是range分区的方式,也是先使用hash的方式讲整个tablet partition到一定数量的分区,如何在划分为tablet。为一个两层的划分方式。其优点可以看得出来,在一个CRDB和YDB对比的blog[3]中也有提到,hash的优点是在处理一些热点问题时候会有明显的优势;在写入顺序的workload中,其能力上限会明显高于只使用range分区的方式,只使用range分区的方式,顺序写入数据一般有个能力上限,而这个上限基本上就是单机的能力。Hash + range的方式的话scan的性能很显然是很难比得上只使用range的。 0x01 Two Layers YDB的一个特点是在Query Layer支持多种的协议,兼容PostgreSQL和Cassandra。其查询部分的功能实现为YQL,和存储部分的DocDB部署在同一个TServer中,YDB关于Query Layer除了同时支持PostgreSQL的SQL以及Cassandra的CQL,相关的资料并没有很多的描述。在CRDB和YDB一篇对比的文章[3]中,也将到了YDB的查询层的一些问题。CRDB的查询层实现为一个 fully-distributed SQL engine,包含了为分布式查询做的各种优化。而YDB直接从PostgreSQL改,为其增加了访问存储层的LSM-Tree的实现,这些访问方式实现在下层的DocDB distributed KV之上。CRDB将其描述为在一个巨大KV系统上实现单体数据库,而不是一个分布式数据库(Rather than a distributed SQL database, Yugabyte can be more accurately described as a monolithic SQL... Read more!

  • 21 Apr 2021
    Key-Value Store in Production

    Evolution of Development Priorities in Key-value Stores Serving Large-scale Applications: The RocksDB Experience 0x00 Resource Optimization 这篇Paper主要是Facebook发表的一片关于RocksDB开发、使用过程中的一些经验总结的文章。其内容主要包含了比如RocksDB资源优化方面为何从write amplification转向优化space amplifiction、CPU利用率、以及对一些新技术看法的内容,其次是一些使用总结: 写放大是LSM-tree存在的一个问题,不够其实无论是B-tree和LSM-tree也好,都会存在写入放大的问题,特别是写入为随机的key写入的时候,这个放大是很难避免的。优化写入放大也是最近一些关于LSM-tree优化的研究的一个方面。在RocksDB这里起初写入放大的优化是RocksDB在优化方面的主要目标之一。为此,RocksDB之前加入了加入Tiered Compaction的方式。在一些应用场景下面,这个可以将写入放大有Leveled Compaction方式的10–30优化到4-10。Paper中提到,对应一些常见,比如value比较大的情况,将value单独存储也是降低写入放大一种可行的方式。这个功能这个正在准备加入到RocksDB中,称之为BlobDB。 随着RocksDB这些年的的发展,发现很多情况下space utilization变得更加重要。实际上,一般应用对于不会利用完硬件的写入寿命,以及写入的负载也没有太多的约束。也就是在很多情况下,写入不会利用完硬件的性能。这个时候优化space显得更加有价值。Rocks通过使用更加激进的Compaction方式减少空间使用带来的收益更多,另外由通过加入Dynamic Leveled Compactio的功能来实现可以动态调整每层的大小,来获取更多的回收掉dead data的机会。减少空间的使用,可以优化成本的问题。 in a random write benchmark: Dynamic Leveled Compaction limits space overhead to 13%, while Leveled Compaction can add more than 25% . Moreover,... Read more!

  • 10 Apr 2021
    Database Lock Optimizations

    Efficient Locking Techniques for Databases on Modern Hardware 0x00 基本内容 这篇paper是关于数据库上lock的一些优化,这些内容是在Shore-MT上面做的,可能和Shore-MT的实现也有一定的关系。这里讨论了range locking、intent locks和deadlock detection以及early lock release的一些优化。 Range locking的一些优化讨论了一些范围锁的内容。上图表示了range lock的一些类型以及其不同类型所之间的互斥关系。其中N表示not lock,而例如 ‘SX’ 表示‘key shared, gap exclusive’,其它类似。这里的一个优化是modes做得很细,优化了之前一些lock方法有些情况没有足够优化的情况,比如缺少‘RangeS-N’ (N stands for ‘not locked’)这样的模式。这种模式在有[10, 20, 30]这样的记录中查询`Select * From T Where T.a = 15时,可以在10上加一个NS-mode (key free, gap shared)的锁,这样key加的是N lock,即没有lock。类似的之前的方案也没有 ‘RangeS-X’ 和‘RangeX-N’ 这样的模式。在这里,一些操作的加锁的方式如下: 对于点查询/添加。以下面的查询为例,先找打对应的leaf page,这个时候持有leaf page的S... Read more!

  • 18 Mar 2021
    RAID and More

    RAID+: Deterministic and Balanced Data Distribution for Large Disk Enclosures 0x00 基本思路 这篇Paper是关于一种新的RAID的方式。随着磁盘的容量的增大,经典的RAID在性能和恢复能力上面已经不太适应了。之后就出现了RAID 2.0。这篇也是使用将数据stripe之后保存到磁盘上面的方式,其特别是利用Latin-square方式,可以得到一个确定性的数据分布方式,与下图所示的使用随机分配data stripe的方式不同。 Latin-square的一个例子就是数独。RAID+这里使用的是多维的。一个例子如下图。n为一个二维的矩形的长度,k表示有几个这样的square。这些squares为正交的定位了每个sqaure对应的位置值都不同。这里如果每个sqaures都是正交的,称之为a set of mutually orthogonal Latin squares (MOLS)。这里可以得到,对于一个n,最多有(n − 1) 个MOLS,最大在n为一个质数的幂的时候。在这种情况下,通过 $L_i(0 < i < n)$ using $L_i[x,y] = i·x+y的方式填充。满足这样数字要求的在4到128之间有4,5,7,8,9,11,13,16,17,19,23,25 27, 29, 31, 32, 37, 41, 43, 47, 49, 53, 59, 61, 64, 67, 71,... Read more!

  • 08 Mar 2021
    Start-Time-, Multi-Queue-, Device-Direct- Fair-Queuing

    Start-Time Fair Queueing and Its’ Variants 0x00 Start-Time Fair Queueing Fair Queuing是一种常见的QoS、调度的方法。以Weighted Fair Queuing为例,其会为每个请求附加上两个tags,stat tag和finish tag。两个tags按照如下的方式定义: \(定义p_f^j, l_f^j分为flow\ f的第j个packet和这个packet的长度.\\ 则S(p_f^j) = \max\{v[A(p_f^j)], F(p_f^{j-1})\}, j \geq 1 \\ F(p_f^j) = S(p_f^j) + \frac{l_f^j}{\phi_f}, j \geq 1. \\ 另外F(p_f^0) = 0, v(t)定义为 \frac{dv(t)}{dt} = \frac{C}{\sum_{j \in B(t)}{\phi_j}}. \\\) C为服务的整体容量,B(t)为backlogged flows的集合,即有要调度packets的flows的集合。调度的时候按照finish tag的升序调度。WFQ的一个问题就是v(t)的计算问题。Start-Time Fair... Read more!

  • 01 Mar 2021
    Key-Value Store with New Hardware

    ROART: Range-query Optimized Persistent ART 0x00 基本思路 这篇Paper出自清华,是关于ART在NVM上面范围查询的优化。ART是一种优化版本的Radix Tree,主要是使用不同大小的node来减少内存、路径压缩来减少内存的使用。这里针对NVM环境上ART范围查询优化提出了3个方面的优化: Leaf compaction:lead compaction的思路是将一些leaf接口压缩保存到其上面的inner节点中,思路如下图。这里的lead compaction将一些对leaf结点的指针压缩到leaf array中。这个更像是一种实现上的优化,如下图所示,如果一个leaf array包含m个leaf指针,如果一个结点下面的一个subtree,包含的leaf结点数量小于m,就可以将这个subtree压缩保存到这个结点的leaf array中。这里通过将一些leaf结点和上层的结点保存一起,可以优化range查询的性能。 ROART这里ART的整体结构没有改变,原来的ART添加、查找和删除算法也没有太大的变化。这里leaf array里面的数据是没有排序的,所以查找操作如果查找到了了leaf array,需要一个遍历对比的操作。这里使用了一些hash table中使用的优化方式,将一些bits的hash tag保存到指针中。利用了现在的指针只使用了48bit的特点,将高16bit保存为key的一个hash值,对比的时候可以先对比这个来避免取回实际的key做比较操作,这个是比较常见的一个优化。添加的时候需要考虑到leaf array可能满来,满来的话需要一个silit操作,基本方式也是将原来结点中的leaf array取出来根据radix tree要满足的一些特性来分裂操作。 Minimizes persistence overhead,减少持久化开销主要是优化ART node的结构。ART基本的node结构如下,ROART通过使用entry compression (EC)的方式将N4, N16, 和 N48类型的几个字段优化到8byte的空间,比如使用讲不同的字段压缩包村到一个8byte值中的方式,比如使用|empty: 8-bit | key: 8-bit | pointer: 48-bit|的方式来分配64bit的空间。另外的一个是通过Selective Metadata Persistence减少需要持久化的元数据。比如一些可以通过其它部分恢复出来的数据就不要去保证持久化,而是通过维护一个全局的generation number (GGN)(每次启动自增)和每个结点维护一个generation number,在对比上的情况下说明结点元数据非最新,需要恢复处理。而恢复处理之后,会将结点的GN更新为GGN。还有就是split操作过程中的一些减少sfence的优化。这里实际上就是一种类似epoch的机制。 Fast memory management。具体方式参见论文。由于NVM作为内存管理的话,分配带来持久化的开销也是需要优化,这里减少这个开心的思路是直接不去持久化分配相关的元数据。恢复重启之后,这里需要使用check操作检查处理那些被分配来但是实际使用的空间。ROART的内存管理基本思路是全局pool加上thread-local pool的2 layers的设计。全局的first... Read more!

  • 24 Feb 2021
    Facebook's Tectonic Filesystem

    Facebook’s Tectonic Filesystem: Efficiency from Exascale 0x00 基本架构 这篇Paper是关于Facebook的一个分布式文件系统,Tectonic。这种类型的分布式文件系统最经典的设计为GFS。但是GFS的设计存在一些取舍,这些tradeoff可能在今天就不是很适合了。所以近些年出现另外的分布式文件系统的设计,其特点比如使用分布式的Key-Value or 数据库等代替取代GFS中使用逻辑上单个的Master,元数据保持到内存中的设计;使用分布式的存储池系统来代替Chunk Store。总体上元数据和数据的存储都变得更加解耦,都是用更加通用的分布式存储系统,而这个Distributed FS更加聚焦在维护文件系统的语义上面。Tectonic 也是一个类似的设计。Tectonic整体的架构为见1. 元数据通过hash partition的方式保存到一个分布式的key-value store中,2. 数据保存到一个分布式blob store中,3. 另外在multitenant有不少的一些内容。 Tectonic的总体架构如上图所示,在Tectonic中: Chunk Store就是一个一般的Object Store,其保存了数据的Chunks,其由文件的Blocks组成。Paper中这里描述的是 Chunks make up blocks,paper这里描述的简短,不是很清楚。从上下文来看,应该是Tectonic中的文件系统又一些blocks组成,block在chunk store中,一些block组成来一个chunk。也就是chunk作为chunk store层面的抽象,而block为FS层面的抽象。而在操作的时候,block做为单个的逻辑单元和持久化单位。而Chunk Store更像是一个Block Store,一个Chunk最终保存到storage node的文件系统之上。这里storage node来保存chunk,而不是使用裸盘等更加激进的方式。做这样的一个Chunk Store会有不少的内容,但是paper中对这里没有多少的描述; Block写入的时候会被EC之后写入,根据EC编码RS(r,k)的配置将数据拆分为r个data chunks和k parity chunks,在保存到不同的fault domains内。对于不同类型的数据,会选择不同的EC配比。这里对于短生存时间的文件,会使用更小的配比,比如3+3。Client直接写入Chunk Store。写入chunks选择那些磁盘在考虑了fault-daomins之外,也不是随机选择的,而是会维护一些固定数量的Copysets,在data unavailability和reconstruction load之间取一个平衡。因为如果是随机选择的,即copysets数量非常多,较短时间内有多个disks故障的情况下丢失数据的可能性会更大,而copysets太少的话,数据恢复的带宽受限; 元数据转化为key-value的形式保存到一个分布式KVS中。映射方式对于文件路径上的信息,就是id+name的方式,通过不变的id加上变的name组合,方便rename的操作。对于文件的数据,通过file id映射到block id,在通过block获取到保存到哪里的chunks的消息。这个kvs使用的是其ZippyDB。在数据分区上,这里选择了和一般不同的hash分区的方式,其优点之一是可以避免掉一些热点的问题; 在上面的元数据和数据不同的服务之外,还有诸多的后台服务,比如rebalance、GC和一些后台数据收集和数据检查的一些服务。这些里面有不少在工程实现上,也应该是比较麻烦的,比如GC,paper中对这些没有描述。 0x01 Multitenancy 这里后面就花了较大的篇幅来介绍Tectonic... Read more!

  • 17 Feb 2021
    Stacked Filters and Xor Filter

    Split Block Bloom Filters 0x00 Block Bloom Filters Block Bloom Filter是用了解决一般的Bloom Filter其Cache不友好的问题的。 Block Bloom Filter基本思路是将一个key要设置的bits都弄到一个block中,这个block一般根据cache line的大小来设计,比如一般的cache line大小为64bytes,512bit。Block Bloom Filter就可以看作是一个一般的Bloom Filters的一个数组,其添加/查询可以看作是现从Bloom Filters的数组里面找到一个Bloom Filters,然后设置这个Bloom Filters。这样就是Block Bloom Filters的第一个hash函数用于确定选择哪一个block,后面的hash函数用于选择一个block中的那些bits。其添加算法可以描述如下。 void block_insert(block b, uint x) block masked = mask(x) int bits_num = sizeof x * 8 for i in [0..7] for j in [0..(bits_num-1)] if... Read more!

  • 15 Feb 2021
    Perceptron Branch Predictor and More

    Dynamic Branch Prediction with Perceptrons 0x00 基本内容 这篇Paper是关于使用Perceptron,感知机来做分支预测的。根据目前找到的一些资料,基于Perceptron和TAGE模式的分支预测是现在的高性能CPU里面很常用的分支预测方式。通过Perceptron做分支预测的方式基本思路是将一些参数值,每个计算一个weight,这里是实际上对于每个参数都是一个一元一次方程。对歌weight对应一个简单的Perceptron。其表示如下: \(\\ y = w_0 + \sum_{i=1}^n x_i \cdot w_i.\) 在这里做分支预测的时候,x-i的取值只会是-1 or 1,对应到分支不跳转 or 跳转。每个x在运行的时候训练出一个对应到w,然后根据上面的式子计算出y,如果结果为负数,则branch不会跳转,否则认为其会跳转。剩下的几个问题就是: 1. x从哪里来?2. 如果训练w。对于第一个问题,x-i实际上就是 global branch history 中对应的bits。对于第二个问题,其训练的方式为,令t = -1 if branch not-token else 1,定义另外一个阈值a。训练方式: if sign(y) != t or |y| <= a then for i := 0 to... Read more!

  • 13 Feb 2021
    Analyses and Optimizations for Tail Latency

    Tales of the Tail: Hardware, OS, and Application-level Sources of Tail Latency 0x00 基本内容 这篇paper是一般的client-server模型下面服务的一些关于tail latency的分析。这里讨论的主要是一些请求排队带来的影响。排队的模型使用A/S/c的方式表示,A表示请求等待的分布,S表示服务时间的分布,而c表示处理请求的workers的数量。一般情况下要求处理请求的速度在较长时间内的平均大于请求达到的平均,否则会导致排队的队长无限增长。在paper的数据中,其测试了单核和多核的情况下,一个echo rpc server、memcached服务和nginx服务在不同情况下请求的tail latency。paper中给出的测试方式从请求的network packets从到达网卡被网卡驱动处理,进入到kernel的TCP/UDP协议栈处理逻辑,到调度应用线程到一个CPU核心上面运行,到应用线程使用syscall从kernel中读出取钱,到用户线程处理完成然后调用syscall回复数据,到数据包被网卡驱动通过网卡发送几个过程分别计时。使用的echo rpc server、memcached和nginx三个服务中,echo rpc server使用的是多线程的模式,即每个请求启动一个新的线程来处理,而memcached的模型是固定线程数量的处理方式,而nginx则是 event-driven的架构。得出了这样的一些基本结论: 在FIFO/先到先处理、LIFO/后到先处理,两种方式都放到一个全局的队列的排队方式下,FIFO的方式有更低的tail latency,LIFO方式的tail latency要差一些,但是其median latency,即中位数延迟表现更好。另外的两种模式是random worker和random request的一些统计,其中random worker的方式每个worker有一个FIFO队列,每个work处理自己队列里面的任务,而random request的方式为一个全局的队列,每个worker从这个全局的队列中取task(不考虑其任务添加进来的顺序),两种random的方式其tail latency都比FIFO的更差,但是median latency更好。同样的结论在后面的一些ZygOS的论文上面也有提到。 在单核的情况下,其它的Background Processes是一个造成tail latency的主要原因之一。一般情况下user-level的进程有相同的优先级,在只有一个CPU核的情况下容易造成资源的争抢。考虑到一般的Linux Kernel使用CFS调度的方式,其调整优先级能够对tail latency影响很小。在使用Linux实时调度器的情况下,对tail latency的提升很明显。因为Linux总是会优先处理实时进程,而CFS这样的方式调度不同优先级进程/线程的时候,其执行顺序和优先级没必然关系。CFS使用的调度方式是一种非FIFO的方式,而调度实时进程的时候可以使用FIFO的方式。 在多核的情况下,rpc server表现出更好的tail latency,而memcached和nginx则没有。Paper中认为rpc server的模型更像是一个random request的方式,而其它两个更像是一个random worker的方式。使用一个global的queue可以有更好的tail latency表现。通过将使用的传输协议由UDP改为TCP,memcached也可以切换为类似于使用global queue方式的处理模型。而nginx要向改为类似这样的模型,paper中使用的方式是client端美发送20-40个请求之后关闭连接,然后重新连接。 另外影响tail... Read more!

  • 01 Feb 2021
    Distributed Consensus Revised

    Distributed Consensus Revised 0x00 引言 这篇《Distributed Consensus Revised》是一篇博士论文,因为某个大佬的点赞以此被更多人知晓。其讨论的还是Distributed Consensus算法的一些优化设计的讨论。在paper的前面,讨论了一个简单的Signal Acceptor,即只有一个Acceptor的一个Consensus算法,和Classic Paxos的一些特性。其总结了Classic Paxos这样的几点Properties,这里的epoch应该是一般的proposal id的含义: Property 1. Proposers use unique epochs for each proposal. 即每个proposal会有独特的epcoh。 Property 2. Proposers only propose a value after receiving promises from ⌊n/2⌋ + 1 acceptors. 收到了大部分的acceptors的回复,这样就能保证之前有更大提案号proposal会被这次知道,以及chosen的value也会被这次操作知道。 Property 3. Proposers only return a value after receiving accepts from... Read more!

  • 27 Jan 2021
    Rate Adaptation to Video Streaming

    A Buffer-Based Approach to Rate Adaptation: Evidence from a Large Video Streaming Service 0x00 引言 这篇Paper讨论是一个基于buffer的视频流传输的速率调整方案。视频在互联网流量占比越来越高,这个速率调整策略也是一个研究很多的问题。adaptive bit rate selection,即ABR,播放视频的bit rate根据目前的网络情况进行自适应的调整。Buffer-Based的方式基本思路是预先下载一部分视频到一个buffer中,buffer会有一个容量。下载视频的bit rate根据buffer占有的比例来进行调整,直观的思路是如果目前buffer占用比较高的时候,就可以选择下载bit rate更高的视频,buffer占用地的时候表面目前网络速度不理想,可以选择下载bit rate更低的视频。而这里提出的思路则是在这样的基本方式上面进行的一些优化。其基本的模型如下,buffer保存的视频会根据其以秒计的视频时长来计算,每次播放的时候为播放一个unit,client下载视频的时候以chunk的粒度下载。这个chunk为固定时间长度的一段视频,在paper中这个chunk的视频长度为4s。这样同样的视频,bit rate越大,这个chunk的bytes也越多。 之前这样的根据buffer占用调整bit rate为这样的一个模型:某时刻系统的capacity,即下载视频的速度表示为C(t),其video rate表示为R(t),其目标是实现一段时间内这个R不要超过C,有能尽量使用更大bit rate的视频。这里使用一个chunk传输的速度来估计一个时刻的capacity,C'(t)。这里估计下载什么样bit rate的视频的时候可能还要考虑到buffer的占用,这个adjustment factor表示为F(B(t)),即根据buffer占用加上一个调整的参数。通过这样的选择video rate表示为R(t) = F(B(t))C'(t)。如果目前的网络是足够的,可以选择R(t) = C'(t)这样bit rate的视频。 在一个时刻网络不够用的情况下,最好是在目前的chunks被播放完成之前,后面的chunk就被下载下来了。paper中先距离一个简单的例子,如果目前buffer里面只有一个chunk,这样就要去VR(t)/C(t) < B(t),这里使用VR(t)表示下载的chunk大小,in bytes(VR(t) = R(t) * V, 每个chunk为V秒长度)。B(t)即表示目前buffer里面的还能个播放的时间。即要求R(t) < (B(t)/V)*C(t),这个有前面式子变换话速率的表示而来。又根据前面F(B(t))和R(t), C’(t)的关系,可以得出F(B(t)) < (B(t)/V)(C(t)/C'(t)),这个要求对于所有t都成立。这样如果C(t)/C’(t)由于网络速度变化大,造成这个比值很小的话,这样选择的F(-)只能选择很小的一个值,从而导致有C’(t)选择R(t)的时候作出选择很低bit... Read more!

  • 19 Jan 2021
    The IBM z15 High Frequency Mainframe Branch Predictor

    The IBM z15 High Frequency Mainframe Branch Predictor 0x00 基本内容 这篇Paper对IBM z15处理其内部的一些结构进行了比较多的描述,比较详细描述了z15的 Branch Predictor,分支预测器的设计。z15是一种非常非常高端的CPU。Paper中给出了其pipeline的示意图。z系列的使用的指令集是一种CISC的指令集,和一般的CPU一样,其也会将指令集转化为一种RISC风格的内部指令去执行。z15有4 level的cache,Level 1和2都是每个CPU核心私有的,而且都是指令缓存和数据缓存分开的,L3为有12个核心的central processor (CP) chip共享,每个256MB,然后每4个通过一个system control (SC) chip通信,这个SC还可以和其它的system drawer通信。这里还维护了另外的一个L4的缓存,大小应该是960MB。 Each of the four CP chips per system drawer communicate with a system control (SC) chip, which in addition to enabling communication across up to 5 drawers... Read more!

  • 16 Jan 2021
    GPPM, L-TAGE and Perceptron-based Branch Predictors

    A PPM-like, Tag-based Branch Predictor 0x00 基本思路 TAGE Branch Predictor是目前很多CPU使用的Branch Predictor,比如使用 TAGE Branch Predictor 和 Perceptrons Branch Predcitor的组合。TAGE即TAgged GEometric length predictor。这篇Paper提出的是一个很接近TAGE的Branch Predictor。其基本结构如下图,其核心思路是使用不同的历史长度来index不同的bank,发现branch在不同历史长度上branch之间的相关性,以实现比使用单一历史长度更好的效果。其有1+4个banks,其中bank 0直接使用branch地址最低的12bit来index,这样看作是一个不考虑branchs之间相关性只考虑自身倾向性的一个预测bank。bank 0是一个bimodel predcitor,实用3bit的counter加上1bit的meta bit,m bit被meta predcitor实用。另外的4个实用3-bit的counter和8-bit的组合,另外还有一个u bit,即useful bit。 不同的bank实用不同的历史长度,分别是10,20,40 和 80bit的global history。在global history长度超过了index需要的长度的时候,实用折叠的方式而不是直接截断,比如实用40bit历史的时候,index实用 pc[0 : 9]⊕h[0 : 9]⊕h[10 : 19]⊕h[20 : 29]⊕h[30 : 39]这样的方式得到(⊕ 为 xor)。获取预测值的时候,5个banks同时预测,高4个的bank的处理index到一个entry外,还会根据tag和PC+history的hash进行比较,匹配了的才是命中。在命中了的bank的结果中,选择bank实用历史消息最长的那个的结果。 更新的时候,3-bit counter的更新只更新提供了最终预测结果的那个。预测正确+1,错误则-1。如果预测错误,设最终实用的bank为X,如果X... Read more!

  • 14 Jan 2021
    Tow-Level Branch Predictor and its Optimizations

    Two-Level Adaptive Training Branch Prediction 0x00 基本内容 分支预测对CPU的性能影响非常大。一般来说,分支的跳转与否都有明显的规律,对于一个分支来说其跳转与否的倾向性是很明显的,这样的情况下预测下一次分支跳转与否可以通过记录前面这个分支跳转与否就可以预测,这样的方法就能实现比较高的预测准确率。基本的方式比如使用饱和技术器的方式,最常见的就是使用2-bit的饱和计数器。这样的方式是让简单,但是很有效,后面的branch predictor的设计都会有这样的思路。在此基础之上,Two-Level的是改进了简单的2-bit计数器不能识别更加复杂的pattern的缺点。基本思路如下图:这里2-level的意思是,通过一个PC找到一个Branch History Register,然后在通过这个BHR的值去寻值Pattern Table/PHT里面值,得出预测的结果, Since the history register table is indexed by branch instruction addresses, the history register table is called a per-address history register table (PHRT). The pattern table is called a global pattern table, because all the history registers access... Read more!

  • 11 Jan 2021
    Scaling Replicated State Machines with Compartmentalization

    Scaling Replicated State Machines with Compartmentalization 0x00 基本内容 这篇Paper相比较是一篇干货较多的,主要的内容是针对Multi-Paxos的这样的Distributed Consensus算法存在的bottlenecked提出一些优化方案,获得了比较明显的性能提升(compartmentalize MultiPaxos to increase its throughput by 6× on a write-only workload and 16× on a mixed read-write workload)。Compartmentalization的基本思路是将功能划分,是一种优化的方式,而不是一种Consensus Protocol,所以具有一定的普遍适用性,而Paper中的例子主要用的是MultiPaxos。Paper中先分析了MultiPaxos存在的bottlenecks: 增加proposers的数量不能提高性能。Client都需要将请求发送到leader,有leader对请求进行排序,然后将请求广播到其它的acceptors。这样leader承担的工作明显多于一般的角色。 增加acceptors的数量反而会降低性能。Leader需要获取一半以上的acceptors的accept才能完成一次请求。更多的acceptors需要leader处理更多的工作。 增加replicas的数量也会影响性能。Leader需要将被选择的value广播到所有的replicas,同样地,更多的replicas需要广播的数据量更多。 优化的总体思路是Compartmentalization,即将原因的部分化/工作拆分的方式。其优化的总结如下: 0x01 Compartmentalization MultiPaxos Compartmentalization 1: Proxy Leaders,MultiPaxos中,leader的bottleneck是比较明显的,在一般的没有使用其它优化的MultiPaxos中,处理一个请求会发送至少3f+4个消息。这里的思路是将leader的工作分为ordering和broadcasting两个部分。这里的方式是引入了一个Proxy Leader的角色,这里会加入>= f+1 个的proxy leaders(proxy leader的数量应该和算法的正确性没有关系,f+1个就可以容忍f个节点故障)。Leader在接受到一个client的请求command x的时候,会讲这个command加上一个log entry i,即一个log的位置信息发送代proxy leaders中的一个。后面发送给acceptors、接受acceptors恢复以及发送chosen value的工作都是proxy... Read more!

  • 05 Jan 2021
    Optimizations for Tail Latency

    RobinHood: Tail Latency-Aware Caching — Dynamically Reallocating from Cache-Rich to Cache-Poor 0x00 基本思路 这篇Paper的思路是比较直观的。它的目标是优化如下图所示系统中request的tail latency。这种系统在现在的互联网服务中很有代表性,其特点是一个用户的请求,会导致很多个请求不同backend的请求。这样导致的一个问题就是其请求的latency和所有请求backend的最大的延迟是有很大关系的。这种tail latency的优化之前也有很多:比如使用load balance的方法,不过其缺点是不同的backend负载不同的时候不能处理。另外一个方式是动态的调整某个backend的大小,即动态扩容,但是其缺点是在这样的stateful的场景下面很难快速扩缩容。之前也有使用cache的方式,但是一般都是静态为每个backend分配cache空间的方式。RobinHood观察到,PCT99的latency一般和cache miss的请求关系比较大,但是cache miss的请求也不一定就到tail latency,因为cache miss里面的请求也可能比较快的完成。RobinHood认为如果将那些队cache大小不敏感的backend使用的cache资源分配给那些对cache大小更加敏感的backend的话,能够有效地降低tail latency。基于这样的思路,RobinHood的设计就是如何在不同的backend之间共享并动态分配cache资源。 0x01 方法 在上面的基本思路之上,首先是一个basic RobinHood algorithm。在这个实现中,RobinHood会不停地回首一个backend的cache空间,每次1%。然后统计latency的变化,通过这个变化来发现cache-poor状态的backend。这个操作在要给周期∆ 内进行,这里定义为∆ 为5s。在这样一个时间窗口内,会统计每个请求的延迟。由于这里的目标是优化PCT99的latency,所以统计中会特别注意latency在P98.5 到P99.5之间的请求。对于这些请求,RobinHood会追踪其请求的backends中最慢的backend的ID。然后使用一个request blocking count (RBC)来几个这个backend,这个RBC值最大的就更可能是瓶颈所在。Paper中解释了选择这个指标的原因:对于延迟最大的backend,其并不一定会导致最终请求的延迟很大,而慢的请求中出现的慢的backend更加可能是最终慢的原因。在这个基本的方式之上,RobinHood还进行一些方面的优化: 基本的RobinHood算法存在的一个假设是,cache空间的改变会很快反映到查询的latency上面。但是实际上这个是存在一个过程的。RobinHood会监控为一个backend分配的cache空间和其已经使用的cache空间,如果分配的和使用了的直接的差值超过了30%的话,这些backend会被暂时忽略。 实际的请求会被复制均衡到多个的app servers,而实际中这些servers接收到的请求不一定是系统的。所以这里每个app server分配cache空间的请求是独立作出的。而RBC统计服务还是一个全局的服务, ... as long as two controllers exchange RBC data, their cache allocations will... Read more!

  • 29 Dec 2020
    Deterministic in Database

    Aria: A Fast and Practical Deterministic OLTP Database 0x00 引言 Aria这篇Paper描述乱一种Deterministic OLTP Database的设计,Deterministic Database的一个特点,没有通信的几个副本各自的执行一系列的事务之后,能得到相同的结果。简单的实现的话,使用单线程顺序执行的话,就能够得到相同的结果。但是这样就会带来比如性能上面的一些缺点。目前的一些Deterministic Database要实现这样的效果,一个问题是要提前制定一个事务要访问那些数据,即在事务执行之前就可以知道write set和read set,然后事务的执行顺序进行一个排序,要求后面事务执行的结果等同于以某个顺序执行的结果。确定这个顺序的方法有比如根据dependency graphs的方法,比如ordered locks的方法,后者是calvin database使用的方法。而Aria则不需要预先知道一个事务需要访问那些数据。Aria的基本思路是先使用一个sequence layer,确定事务的一个顺序,然后批量地执行这些食物,执行一个batch之后对执行结果进行检查。这个batch的执行可以是并发的,这样需要在执行完成之后对结果进行检查,确定其结果和按照之前决定的顺序执行的结果相同,然后commit。 0x01 基本设计 其基本的算法描述如下,其核心是通过事务将会访问的write set和read set来发现不能保证得出确定性结果的冲突。其事务的执行访问Execution Phase和Commit Phase,都是batch方式执行的,每个batch并发执行。事务执行之前会被一个sequence layer赋一个TID,事务执行的时候,每个事务都是从目前数据库的snapshot来读取,执行事务的逻辑,将要写入的数据保存到一个local write set中。在执行完成之后,会计划一个write set中对应的write reservations,这里记录下每个write数据的遇到的最小的事务的TID,不能处理reservation的时候事务就需要abort,在处理reservations操作之后如果有一个reservation操作不成功,则可以提前abort。这个reservation操作以执行T1: x=x+1,T2: y=x−y,and T3: x=x+y为例,T1执行完成之后,table中记录下{x : T1},执行T2的完添加一个{y : T2},而后面执行T3的时候则不能完成reservation操作,x以及被T1 reservation了而且T3的TID更大,T3事务会被abort。而如果是T3在前面的话,则T1可以更长reservation的table,后面在commit的时候,通过HasConflicts检查来发现其不能满足commit的条件,而被abort。在HasConflicts中,也会检查读写之间的冲突,其keys为writes set和read的并。这些abort的事务会被调度到下一个batch中被执行。其如何可以满足Determinism 和 Serializability特性在paper中有详细证明。 Function: Execute(T, db) Read from... Read more!

  • 24 Dec 2020
    IO Scheduling

    mClock: Handling Throughput Variability for Hypervisor IO Scheduling 0x00 基本思路 mClock是一个结点的IO QoS算法,这篇Paper描述的是在Hypervisor上面运行多个VMs的情况下如何调度VMs之间的IO请求,当然mClock算法完全不仅仅可以用到这个Hypervisor IO Scheduling方面,是有不同的IO请求需要控制其共享存储设备能力的都可以用到mClock。mClock算法的核心是使用三个值来控制不同请求原来的QoS,shares (即 weights)即表示一个请求来源的权重,reservations表示至少为一个请求来源预留多少资源,表示一个下限,而另外一个limits值表示能够使用资源的上限。一般情况下,为一个请求来源分配的资源为weights值在总的值占的比例,也就是说mClock是一种Proportional Share Algorithms。而reservations和limits的加入是处理资源争用的情况,即在根据weight分配的资源不足reservation的值时候,会增加到reservations的值,而根据weight分配的资源超过limit的时候,会减少到limit的。后面就是如何实现。 0x01 算法 mClock实现的时候,使用为每个请求打tag的方式。打tag的方式沿用了mClock之前算法的一些方式。以权重为例,其基本思路是根据权重w,每次间隔1/w-i的间隔给一个来源的请求打上tag。处理IO请求的之前,根据这个tag值排序,然后处理这个请求,这样就能实现按照权重共享资源的效果。使用R,L,P分别表示Reservation,Limit和Share-Based-Tag(Weight)的tag,使用w,r,l分配表示权重,Reservation和Limit值。则其打不通tag的方式是一样的。都是按照如下的方式: \(\\ R_i^r = \max{\{R_{i}^{r-1}+ 1/r_i, CurrentTime\}}, \\ L_i^r = \max{\{L_{i}^{r-1}+ 1/l_i, CurrentTime\}}, \\ P_i^r = \max{\{P_{i}^{r-1}+ 1/w_i, CurrentTime\}}, \\\) 也就是谁其打tag的基本算法是一样的。即理想的情况下,请求被安排到1/r or 1/l or 1/p间隔的时间点被处理,从而实现满足R,L和P的条件。但是一段时间内,分配给一个请求来源的没有使用分配的资源的时候,其也不会后面补偿,使用取下一个间隔时间和目前时间的最大值。在此的基础之上,由于w是一个相对的值,想要进行特殊的一下处理。R和L的标准是固定的,所以不用特殊处理。P表情的原因是新client or 一个来源重新变得活跃的时候,新来请求会其打tag的基准点不一样了。可能导致饥饿问题的出现(一个请求来源的P tag可能已经超出了目前时间,新来的以目前的时间为基准): The initial... Read more!

  • 18 Dec 2020
    Several Points about Object Store

    Ambry: LinkedIn’s Scalable Geo-Distributed Object Store 0x00 基本内容 这篇Paper是关于LinkedIn的对象存储系统Ambry的设计,其基本价格如下图所示,其基本架构和Facebook的Haystack类似,存储也是使用100GB一个大文件,里面保存多个blob。对于上传的很大的对象,也会对其进行拆分,拆分为chunk,每个chunk对象大小在4-8MB左右。每个chunk就类似于一个blob的方式保存到相同中,同样的为了记录下一个blob为拆分为那些blob,Ambry会创建另外的一个b-metadata的blob,记录下这个信息,这个metadata又作为一个blob保存代系统中。同样为了定位一个partition中的一个blob,也适用来本地的一个index。这些没啥特别的。 Paper中对其复制有详细一点的讲解。Ambry复制利用了一般这种类型的系统append-only写入,不会修改的特点。使用多点并发写入的方式,而不用care并发写入带来的同样的blob数据不一致的问题,而blob保存在不同副本上面的位置不同,则利用每个副本的index来各自定位。这样多副本并发写入的方式,对降低延迟又比较好的效果。而对于跨地理区域复制的情况,使用异步复制的方式。比如写入3个副本,2个ACK就能返回的话。需要处理GET的时候读取到最近写入到问题,这里的处理方式也就是一个没有GET到的时候请求另外的副本即可。这样每个副本上面的数据不一定是完全一致的。为了处理这个问题,Ambry的方式是每个副本之间周期性同步数据的方式,为了记录下来最近写入一个partition的数据,Ambry使用一个内存中的日志。记录下根据其在partition保存的offset排序的blob。同步操作的时候,第一步根据这些信息发现从最近一次同步点依赖的,副本自己缺失写入的数据,第二步操作就是同步到本结点。对于负载均衡,Ambry使用了2中不同的策略: Static Cluster,即将大的blob拆分,然后随机选举partition保存的方式。 Dynamic Cluster,在这里定义了3个ideal state,(idealRW, idealRO, idealUsed),表示 ideal number of read-write partitions, ideal number of read-only partitions 以及ideal disk usage each disk。这个值通过总的请求的量除以磁盘数量得到。算法的基本思路是第一步大于ideal值的,加入到一个pool中。然后将其移入到低于ideal的磁盘中。移入的基本方式是创建一个新的副本然后删除之前副本的方式。 // Compute ideal state. idealRW=totalNumRW / numDisks idealRO=totalNumRO / numDisks idealUsed=totalUsed / numDisks // Phase1: move extra partitions... Read more!

  • 10 Dec 2020
    Spanner -- Becoming a SQL System

    Spanner: Becoming a SQL System 0x00 基本内容 这篇Paper是关于Spanner的第二篇Paper,应该是也是比较有名的了。这篇主要的内容是关于Spanner在SQL方面的进化。Spanner开始的时候更像是一个Key-Value的系统,支持SQL。而现在更像是体格关系型数据库系统。在SQL的执行中,query compiler会先将SQL查询编译为一个relational algebra tree,即SQL查询的一个tree的表示,然后根据schema和数据的一些特性来对查询进行重写,使之成为一个更加有效率的执行方案。这里的重写Paper中描述的是通过transformation rules,所以看来是一种rule-based的方式。比如常见的优化方式如谓词下推,使用索引,字查询消除等。查询计划会有一个cache,对于相同模式的查询可以避免重新编译。Query Complier会用到很多的 correlated join operators操作,包括查询优化里面的algebraic transformation,以及一些physical operators。Spanner中将logical operators分为两种类型,CrossApply和OuterApply。CrossApply签名类似于CrossApply(input, map) 的操作,类似于函数式编程的map,而OuterApply(input, map)也是将map作用到input中每一个tuple上,但是不会有map的输出。由于是分布式的数据库,查询编译器生产的查询计划会包含在remote servers上面执行的subplan,还包括将每个shard的结构聚合的部分。这里就涉及到Spanner的分布式查询。 0x01 Query Distribution 前面简单地提到Spanner的执行模式。考虑到Spanner的分布式环境,其很多查询结果是每个shard查询的和。这样就引入了Spanner的一个分布式operator,称之为Distributed Union,即实现将每个部分的结果汇总。这个Distributed Union是一个很核心的operator,用在查询进行的时候,也包含在查询restart的时候。比如一个分布式的scan,可以表示为Scan(T) ⇒ DistributedUnion[shard ⊆ T](Scan(shard))。为了优化执行的性能,Spanner会尝试就可能地将Distributed Union放在relational algebra operator tree的更高的位置,也就是说尽可能的将其它的一些operators放到每个每个分区上面进行。达到类似于一个算子下推的效果。当然这样就要求这些下推的operators在每个部分执行在聚合和聚合之后在执行最终得到的结果是一样的,Paper中将满足这种特性称之为partitionability。Join操作很多时候不能满足这个partiitonability,但是Spanner支持一个table interleaving的特性,即将不同的tables(sharing a prefix of primary keys)的数据,交叉地保存。在这样的保存方式在进行一些join操作的时候,同样也可以使用operators下推然后进行Distributed Union。有些这样的可以使用Distributed Union是通过multi stage的方式实现的,比如一些Top操作和一些Group By操作。这样的操作下相当于将查询重写,Op(DistributedUnion[shard ⊆ T](F(Scan(shard)))) =... Read more!

  • 02 Dec 2020
    Storage Engine and Buffer Pool in Umbra

    Umbra: A Disk-Based System with In-Memory Performance 0x00 基本内容 这篇Paper的主要内容是一个Disk-Based的数据库系统的Buffer Pool相关的设计。之前一段时间内全内存的数据库设计是一个热门的方向,然后这篇Paper认为圈内存的数据库成本太高了(A modern 2 TB M.2 SSD can read with about 3.5 GB/s, while costing only $500. In comparison, 2 TB of server DRAM costs about $20 000, i.e. a factor of 40 more),而设计了Umbra这样一个Disk-Based的数据库系统,而且接近In-Memory数据库的能力。而这Umbra的buffer manager的核心是一个variable-size pages的设计,其基本思路如下图。一般的Disk-Based的数据库使用page为单位来管理磁盘上面的数据,而这个page大小是固定的,常见的page大小有8KB,16KB等。这样简化了buffer manager的设计,但是处理一些大字段 或者是字典压缩相关的lookup tables的时候超过了这个大小处理起来就会比较麻烦。 0x01 基本设计... Read more!

  • 26 Nov 2020
    CrossFS and Horae, File Systems for New Hardware

    Write Dependency Disentanglement with Horae 0x00 基本内容 这篇是OSDI ‘20上面一篇关于NVMe SSD上如何优化并发写入性能的文章,关注点是写入的顺序控制上面。一般的文件系统接口下面,其操作持久化/完成的顺序是乱序的,而且写入操作返回之后并不能保证数据已经只持久化了。为了处理顺序和持久化的问题,文件相同的fsync提了这样的功能,同时带有确定操作的顺序和确保数据已经持久化的功能。OptFS提出fynsc保护的顺序和持久化的两个语义和拆解,可以拆为数据持久化和确定数学两个分开的接口。还没的BarrierFS在这样的基础上提出了,提出了针对高速SSD优化的Barrier-Enabled IO stack。这篇Paper则关注在多个高速硬件的时候,如何充分发挥其性能。在多个设备的情况下,有顺序要求的写入由于写入顺序会导致性能随着硬件数量的增加提升不上去,而对于写入请求没有要求的,则可以比较充分发挥出硬件的性能。所以操作满足交换律还是比较好优化的[2]。 在目前Linux的系统,mq block layer的情况下,software queue可以对上层的请求进行合并、重新排序等操作。而在hardware queues这边,执行IO操作的指令的执行也是没有顺序保证的。目前解决这个问题的方式就是对于有顺序要求的,就是操作完成一个之后再去进行下一个,这样严重影响了性能。二BarrierIO的核心思路是让IO栈个层都可以告知到一个操作的顺序,使得这些操作可以并行的进行一些操作,同时完成操作的顺序有可以保持。而BarrierIO对于多个硬件的情况,其还是限制了多个硬件并发的性能。Horae的思路是数据流和控制流分开。对于数据流,其完全是无序的,二对于元数据的完成会给一个顺序上的保证。其关于操作顺序相关元数据持久化在前,而数据持久化在后。如果处理到中间crash的话,需要根据先持久化的元数据,如果有没有完成的操作,依赖于这个没有完成操作都需要进行会滚: Moreover, Horae separates the ordering control from the data flow: the ordering layer translates the ordered data writes (1) into ordering metadata (2) plus the orderless data writes (3). The ordering metadata passes... Read more!

  • 16 Nov 2020
    Fault Tolerance for Partial Network Partitioning

    An Analysis of Network-Partitioning Failures in Cloud Systems 0x00 基本内容 这篇Paper研究了限制的一些分布式软件系统的Network-Partitioning的容错能力。网络分区在目前的环境中,一般要被认为是会发生的,这样事就是CAP中的P总是会有的,很多系统就变成了C和A之间的取舍。这里将Network-Partitioning分为complete network partitioning、partial network partitioning和Simplex network partitioning。第一种指一个部分的节点和其它的结点完全隔离开了,第二种指的是一部分结点之间直接的连接不通了,但是还可以通过其它部分的连通。Simplex network partitioning则指的是一个结点可以发送消息到另外一个,另外一个发送的消息这个结点确收不到,这种在UDP这样的协议下会发生,很多是因为路由故障的原因。现在的很多分布式系统都理论上有处理网络分区的功能,这篇Paper则开发了一个NEAT的系统,对一些系统进行了世界上的测试。发现大部分的系统在处理Network-Partitioning问题上或多或少都有一些问题。 0x01 General Findings 针对多个分布式系统的测试发现了这样的一些问题:约80%的Network-Partitioning导致的故障都有一个catastrophic,灾难性的影响。有27%导致了数据丢失。比如MongoDB在网络分区的时候,连接primary replica的client可能读取脏数据,即发生了dirty read。90%的问题都是silent的,另外一些会导致很难处理的警告信息。即使系统返回了一些warnings的消息,很多情况下也不能很好的区分这些warnings消息的原因。21%的复制导致了永久性的隐患。比如RabbitMQ一个结点在发生Network-Partitioning故障的时候,它会认为其它部分故障了,自己作为单独的一个部分运行。后面即使网络恢复了也不会系统也不会恢复到之前的状态。 Leader election, configuration change, request routing, 和 data consolidation这些部分是最容易出现问题的。常见的问题有old leader在被隔离之后,其写入可能失败了,但是读取可能仍然提供服务,这样会有读取到过期数据、脏读的问题。一些系统使用的选举leader的策略也有问题,比如选择log最长的,比如VoltDB。选择最后操作时间戳最新的,比如MongoDB。选择ID最小的,比如Elasticsearch,一些情况下可能导致数据丢失, 0% of leader election failures are caused by electing a bad leader. This is caused... Read more!

  • 09 Nov 2020
    The SNOW Theorem and Performance-Optimal Read-Only Transactions

    The SNOW Theorem and Latency-Optimal Read-Only Transactions 0x00 基本内容 这篇Paper仿照CAP Theorem提出了一个SNOW Theorem。即S,N,O和W不能同时满,根据这里SNOW Theorem来知道系统的设计,Paper中也给出了两个分布式事务系统的例子,一个满足SNW,一个满足NOW。其中: S表示的是Strict Serializability,即保证全系统中的事物中,存在一个total order,全局的顺序。即事物是serializable的。另外Strict有要求了这个total order反应的是real-time ordering,即如果事务t2在real time中发生在事务t1已经完成之后,则t2在total order中必须出现在t1之后。这里的real-time应该是实际时间的意思,而不是Computer Science中常见的实时的意思。但是有另外的两个事务t3和t4,其中t4开始的时候,t3已经开始了但是还没有完成,在total order中哪个出现在前面都是可以的。 N表示的是Non-Blocking Operations,即系统在执行Read-Only Transaction的时候,不需要等待任何的event,这个event可以是等待锁,等待其它server的消息,或者是等待超时等等。 O表示的是One Response Per Read即client请求server读的时候,client只要发送一次的read请求,而server也只会回复一个的response。 W指的是Write Transactions that Conflict,即可以有冲突事务同时进行,比如一个写事务更新多个server上的数据的时候,读事务还是可以进行的。 证明 Paper假定的环境是一个N个Servers的分布式系统,N大于1。Client和servers通过网络通信,这个网络是asynchronous network,即message delay可以是任意时间的(partially synchronous network则可以是有delay的,不过这个delay存在一个上界)。这里定义 invocation time为一个clieng发送请求到参与这个事务的server的时间,response time定义为client收到所有server回复的时间。Lamport的happened-before关系定义了这样的关系: 1) If a and b are events in... Read more!

  • 05 Nov 2020
    Overload Control and Threading Models for RPC

    Overload Control for μs-Scale RPCs with Breakwater 0x00 基本思路 这篇Paper主要是关于RPC做Overload Control的思路。Breakwater的基本思路是一种server-driven admission control的方式,client只有在收到server的credits的情况下才能向server发送请求。对于server来说,它使用排队延迟来作为一个overload的判断。在Breakwater之前,场景的overload control方式有这样的一些策略:一个是Active Queue Management (AQM),Control的组件作为一个 circuit breakers运行在server端 or 另外的一个 proxy,其使用的策略可以是限制server正在处理的请求的数量。这种方式的一个缺点是即使一些请求被拒绝,还是会造成server的一些开销;另外的一种方式是Client-side Rate limiting,使用某种策略来限制client发送请求的速率,client端通过deplay等信息来判断server的处理能力,避免让server过载。Client端控制的方式在client数量很多的时候处理并不是很好。另外的一些方式是结合这两种方式。Breakwater提出的对Overload Control的要求是: 1. Short average service times; 2. Variability in service times; 3. Variability in demand; 4. Large numbers of clients; 基于上面的思考和对Overload Control要求的总结,Breakwater的思路是: 1. Explicit server-based admission... Read more!

  • 02 Nov 2020
    Virtual Consensus in Delos

    Virtual Consensus in Delos 0x00 基本内容 这篇Paper值发表在OSDI 20上面的一篇关于Consensus的paper。Delos可以看作是一种Shared Log的实现,其特点之一是总体上将系统分为Virtual Log和Loglets两个部分,也可以对应到Control Plane和Data Plane两个Plane。其基本架构如下图,对于Virtual Log和Loglets,两个部分提供的都是一般的Shared Log的接口,基本接口示意如下的代码,Loglet的核心是append的操作,读取为每次读取下一个entry,删除使用prefixTrim。这些接口和Corfu种使用的很类似,队医VirtualLog,在其之上还加入了一个Control Plane功能的接口。 class ILoglet { logpos_t append(Entry payload); pair<logpos_t,bool> checkTail(); Entry readNext(logpos_t min, logpos_t max); logpos_t prefixTrim(logpos_t trimpos); void seal(); } class IVirtualLog : public ILoglet { bool reconfigExtend(LogCfg newcfg); bool reconfigTruncate(); bool reconfigModify(LogCfg newcfg); } 在两层的抽象设计之上,只有VirtualLog必须要考虑fault-tolerant,Loglets则不是必须的。VirtualLog在一个Loglets的集合之上构建出一个Shared... Read more!

  • 27 Oct 2020
    Non-Volatile Main Memories File Systems(3)

    Kernel/User-level Collaborative Persistent Memory File System with Efficiency and Protection 0x00 基本思路 这篇Paper是一篇关于NVM上文件系统设计的paper。这篇Paper提出的KucoFS的思路是内核态和用户态结合的思路,来解决完全的内核态文件系统 or 完全的用户态文件系统存在的各自的缺点。在兼容原来的接口的情况下,还可以实现应用直接访问文件系统的数据,并实现很高的protection功能。KucoFS的基本架构如下。其核心思路是用一个用户空间的lib,ulib来实现文件系统的接口。所以这里并不是兼容原来的syscall,而是原来的posix的文件操作接口。不过这样的话并不是完全兼容的,毕竟还是依赖于ulib。在ulib下面,是内核中文件系统逻辑的实现,这个一个特点是ulib可以直接看到文件系统的结构,进而可以直接访问数据。但是对于更新来时,需要通过一个msg buf来放松到内核中的一个master来处理。 0x01 基本设计 整体设计上,KucoFS将文件系统image的一部分以只读的方式映射到用户空间,这样读取数据的时候可以直接访问数据。写入数据的时候总是以CoW的方式写入,ulib先想master申请可以写入的数据pages,然后想其中写入数据,写入完成之后再将元数据更新的请求发送到master,由master来完成更新元数据的操作。管理文件系统中内部结构的时候,KucoFS使用NVM+DRAM结合的是,一般情况下只会设置的DRAM,这样可以提高性能。内存中的一个inode table保存了指向实际inode保存位置的指针。这个inode table实际上就是一个预先分配的数组。对于每一个user,这个table的第一个都是指向root inode。这样也就是说每个user看到的root inode可能是不一样的。空间管理上面,使用类似于ext2的block mapping来管理pages,这种方式更加简单,便于实现lock-free fast read 。另外对于dentry,每个dir使用一个dentry list来保存下面的dentry。这个dentry list也是保存在内存中的。为了保证元数据的 durability 和 crash consistency,每次操作元数据的时候,会先写log。在这样的基础设计之上,KucoFS的另外的一些设计: Index Offloading,master在处理请求的时候需要根据index来查找相关的结构,以及更新的时候更新index。这些完全由master来处理的话会给master带来不少的压力。由于一部分文件系统image以及映射到用户空间了,这里的思路就是直接由ulib来完成index查找的工作,对于一个更新的操作,比如creat请求,ulib会在请求中带上parent dentry的信息。Master就可以直接进行检查和更新相关的操作了。 要实现这样的思路,还有几个问题需要处理:1. 第一个就是在master可能并发更新 directory tree的时候如何读取到consistent directory tree。这里对于每个dir都使用一个基于skip list实现的dentry list。更新的时候原子地更新一个pointer就能完成添加的最后一步操作,这样不需要lock,ulib就可以看到一个consistent view。对于rename的情况,需要更新两个dentries,这样就可能同时看到两个相同的文件,这里的解决方式是在dentry在一个flag来标记这样的操作,避免ulib读取到中间的不一致状态。2. 另外的一个问题是ulib在读取的时候,一个数据可能被删除了。这个是并发数据结构中常见的一个问题。这里的方式是对于inode和dentry都加入了一个dirty bit。其被删除的时候,先标记这个bit,垃圾回收的时候使用epoch-based reclamation机制。Master维护目前的epoch,ulib会记录目前工作的epoch,master回收最老的epoch之前的数据,不过这样受到ulib被blocking的影响,而paper认为这个问题不是很大。3. 另外的一个问题是提前定位的dentry,pre-located dentry,可能已经改变了。使用master操作的时候需要检查。... Read more!

  • 22 Oct 2020
    Parallel(s) On Paxos/Raft

    ParallelRaft on PolarFS 0x00 基本思路 ParallelRaft是再PolarFS[1]中应用的一个针对特定应用的Consensus算法。ParallelRaft的特点是Out-of-Order ACK(乱序复制确认),Out-of-Order提交以及Out-of-Order Apply。一般情况下Consensus不会关系应用是证明apply log的。通用的情况下,log需要顺序地apply才能保证得到预想中的结果。但是很多情况下,不是顺序的乱序的apply也是可以的。最典型的情况就是如何就是一般的Key-Value Store的情况。如果log是关于KV Store的操作,只需要保证乱序操作的部分没有针对一个Key的两个操作就行了。这样乱序处理带来的一个问题就是可能每个节点上面都没有完整的日志,而在Raft中,是要求被选为leader的节点有全部的可能已经committed的日志的。因此就需要对ParallelRaft的leader election算法进行一些修改: ParallelRaft新leader仍然保证来会有全部的已经committed的日志,这样就需要一种方式来补全刚刚选出的新leader可能缺失的日志。为了处理这个问题,ParallelRaft引入了额外的一步merge的操作。Merge操作中,1. 对于已经committed的但是新leader没有的entry,会从其它的已经有了的节点拉去回来;2. 对于在其它结点上都没有committed的entry,如何每个结点都没有对应的数据,可以选择跳过;3. 对于没有committed的/不知道有没有committed的,总是会选择term更大的。除此之外,ParallelRaft还引入了一个checkpoint的逻辑,用于确定在某个点之前的所有的log entries都已经有了。 一个落后的follower想要追赶leader时,可以使用fast-catch-up or streaming- catch-up的方式。其中fast-catch-up用于实现leader和follwer之前的增量同步,一般在leader和follower的差别不是很大的时候。如何两者的差距比较大,就可能需要同步全量的数据。这个时候就使用 streaming- catch-up。那么如何确定可以OoO Apply呢?ParallelRaft这里使用的记录LBA的方式。Leader在commits一个log entry的时候,之后会将这个消息广播大其它的follwers。在Ack-Commit-Apply这样的操作步骤中,后面的apply操作ParallelRaft也不一定会是按照log entry的顺序apply的。OoO Apply也是基于一个范围内的log entry表示的操作之间没有冲突。如果没有冲突,按照什么样的顺序执行,可以得到一样的结果。这里检测冲突的方式就是记录LBA,因为这里面向FS。为了实现这个思路, ParallleRaft引入来一个look behind buffer,保存在每个log entry中。这个 look behind buffer保存了前面的N个log entry中会修改的LBA。N就是一个最大的能乱序apply的单元,这样带来的一个限制也就是log中的空洞不能大于这个N。Paper中这个N数值并不是很大。 ... the follower can tell whether a log entry is conflicting, which means that... Read more!

  • 20 Oct 2020
    Schema-Agnostic Indexing with Azure DocumentDB

    Schema-Agnostic Indexing with Azure DocumentDB 0x00 基本内容 这篇Paper是关于 Azure DocumentDB如果建立索引的的。Azure DocumentDB是微软的一个文档数据库。文档数据库中的每个数据库中的每个Collections保存的是JSON式的Document。特点是没有Schema,可以随时添加新的字段,带来了很大的灵活性的同时也带来了一些问题,比如在这种Schema-Agnostic的数据模型上面如何构建Indexing。这篇Paper描述的就是一种Schema-Agnostic Indexing。默认的情况下,DocumentDB会为所有Documents自动构建索引,不用用户自动指定schema或者是次级索引。Indexing构建的时候,会有一个性能,存储空间以及一致性等上的一个tradeoff,DocumentDB可以选择不痛的indexing policy,选择不同的tradeoff方案。Schema-Agnostic的索引方案,DocumentDB首先有这几种方式处理Document, 首先DocumentDB将Document解析为一个JSON Tree,基本思路如下图所示,对于一般的Key-Value的时候,子结点就是Key。对于数组的情况,子结点为数组索引,从0开始。这样对于一个Value,都可以对应到这个JSON Tree上面的一个Path。这里将node称之为一个label,Document会有一个虚拟的root node。对Documents构建索引的时候,默认情况下DocumentDB会为Documents上每一个Path都构建索引(可以配置排除)。 每更新一个Document的时候,这里就希望即使是一个很复杂很多层的JSON结构,也能想yiceng的Key-Value一样索引的更新成本。索引实际上就是Path和Doc IDs之间的一个映射。这样forward index mapping的思路是(document id, path),即Doc ID映射到Path,另外一个是inverted index mapping,即 (path, document id),Paht映射到Doc ID。inverted index是一种很有效的方式,因为不同的Documents会有很大一部分相同的部分。所以这里将不同Documents union之后的结构称之为index tree。Index tree的node称之为一个index entry,包含了label和position values,以及保护了这个node的文档的ID集合。其基本结构如下图。由于是一种inverted index,使用的术语和倒排索引的术语类似,Terms以及Postings等。 0x01 索引结构 在上面描述的索引模式下面,DocumentDB将Index Entry的逻辑结构表示如下图。其Key是一个Term,默认使用5个byte表示,Value为一个Postings Entry,为了压缩存储的空间,引入了PES(posting entry selector)。这里的Term只使用了5个byte表示是一个有意思的地方。Term在DocumentDB就是一个有向的Path,这个又向可以有不同的模式:forward path为有root node出发到leaf node的方向,而reverse path与之相反。不同的方向有不同的存储和维护的开销,也会影响到查询。比如SELECT * FROM... Read more!

  • 12 Oct 2020
    Azure SQL Database Always Encrypted

    Azure SQL Database Always Encrypted 0x00 基本内容 这篇Paper讲的是Azure SQL Database的Always Encrypted(AE,第二个版本)加密功能,其可以实现加密的数据从client出去之后就一直是加密,并利用enclave running within a trusted execution environment可以提供在加密上面的一些查询功能的支持。在AEv1时,AEv1使用的方式是对要加密的列使用的 deterministic encryption的方式,即同样的明文在同样的密钥加密之后的密文是一样的,这样会有一些的安全问题。 deterministic encryption的优点是可以很简单就支持点查询,以及equi-joins, 和 equality-based grouping基于等值的查询操作。而且AEv1在切换加密密钥的情况下也很麻烦, turning on encryption for the first time (initial encryption) and rotating encryption keys both require a roundtrip to client systems possessing the encryption key(s), which can... Read more!

  • 07 Oct 2020
    Paxos Made Live - An Engineering Perspective

    Paxos Made Live - An Engineering Perspective 0x00 Algorithmic Challenges 这篇Paper是比较有名的一篇,应该是早就读过了。Paxos Made Live给出的是Multi-Paxos工程实践上面的一些总结。Multi-Paxos在是Paxos上面改进而来的用来在多个value上面达成一些的算法。Multi-Paxos可以设计为在一段比较长的时间内指定一个coordinator,并尝试让这个结点的coordinator角色不改变。这里将这种的coordinator称之为Master。使用了这个优化之后,也就是加入了一个Master的角色,一般情况下一个Paxos instance只会要求一次磁盘写入。主要的设计下面总结了一些Algorithm上面需要处理的问题: Master leases,使用basic Paxos来实现数据复制的时候,读取数据也要求执行一个Paxos instance。这样来决定读取能过读到最新的数据。如果没有其它的改动,直接读取Master上的数据副本是不行的,因为其它那些的结点可能已经选举出了另外的Master,而且没有通知到这个Master。为了处理这个问题,这里使用了master leases的机制。在这个master leases机制的限制下面, 只有有这个lease的结点才能submit value,其它的结点submit则会被拒绝。这样就能保证Master一定包含了最新的数据。在一个lease要过期的时候,Master会尝试去续租,一般通过heartbeat来处理。Paper中描述的一般情况下,一个Master的lease租约可以续约上几天的时间(不是一次lease的时间)。在这里的实现中,一个副本会隐式地给上一个Paxos instance的master一个lease,这个lease有效的时候会拒绝来自其它结点的请求。Master上这个lease的有效期会短于其它结点上面通过lease的有效期,这个是为了处理clock drift的问题。 这里会有一个可能的问题导致系统的不稳定,一个Master暂时的和其它结点断开连接的时候,其它结点选举出来一个新的Master,这个master会使用一个sequence number。如果这个之前的Master有和其它的结点连接上了,使用一个更大的sequence number,使得其它的Master失效。这样可能反复,导致系统的不稳定。这种情况下,在网络不佳的情况下容易变成经常快速地Master变更。这里使用的优化方式是Master会周期性的通过一轮Paxos增大自己的sequence number。这种在其它的Consensus算法实现中也是一个需要优化的问题,比如在Raft中PreVote优化,避免一些不必要的Leader切换。 这里还谈到了非Master副本的lease,这篇Paper中提到这个还没有实现。这种思路在后面被另外的研究发表了”Paxos Quorum Lease”的文章,其基本思路也是获取一些keys本地读的权限。 Note that it is possible to extend the concept of leases to all replicas. This will allow any replica... Read more!

  • 03 Oct 2020
    Asymmetric Replication in Databases

    Parallel Replication across Formats in SAP HANA for Scaling Out Mixed OLTP/OLAP Workloads 0x00 基本内容 这篇Paper是关于HANA数据库复制机制的一些内容,其主要的内容是如何实现并行的replication,以及适应OLTP/OLAP混合的workload。HANA这里提出的方式称之为Asynchronous Parallel Table Replication (ATR),和很多的HTAP的系统类似,ATR的思路也是实现在primary replica上面实现OLTP的服务,而在另外的一些副本上面实现OLTP的服务。ATR这种情况下需要处理OLTP实现的行层和OLAP使用的列存之间的差异。另外的一个内容就是其Parallel Replay特性,利用HANA使用的MVCC的机制来实现一种optimistic lock-free parallel log replay 方式。在这样的基础上,ATR的几个设计决策: 一个是使用replicate使用跨行存和列存的数据格式;将storage-level recovery log和replication log隔离。两个使用不同的格式,和MySQL有点类似;log的产生和发送和storage engine紧密结合;另外对于primary上,log记录record-level的SQL执行的结果(record-level result logging),即一种value log的方式,以此来避免一些不确定性和parallel log replay的一些冲突。对于其它的replicas,主要是parallel log replay,还有就是类似adaptive query routing的一些功能。 一般情况下,复制使用异步的方式(lazy replication),也可以支持同步的方式(eager replication)。ATR还会使用early log shipping方式,在相关的事务提交之前,对于的DML语句完成之后,就发送相关的log,而不是等到事务committed。这样要求primary的事务后面abort的话,replica执行了的操作也需要回滚。这种方式可以尽早地让操作在replicas上面可见。为了处理replica落后于primary的问题,ATR也支持查询设置一个maximum acceptable staleness。primary执行操作的时候,会在log里面commit log下面记录提交的时间。Replica上面replay log的时候会更新其replay到那个时间了。查询如果指定了最大的落后时间的话,查询可以被重新路由到primary上。Lazy的方式在性能上面有优势,但是也可能造成一些数据丢失,所以又引入了一个post-failure... Read more!

  • 29 Sep 2020
    Can Applications Recover from fsync Failures?

    Can Applications Recover from fsync Failures? 0x00 基本内容 PostgreSQL之前有过一个丢失数据的BUG,这个BUG和fsync的错误相关。PostgreSQL使用来错误的方式处理fsync返回错误时的情况。Linux上面某些文件系统在fsync错误的时候可能会直接丢弃内存中的错误,这个时候重试操作可能是错误的方式。fsync的运作可能产生一些错误,一般的系统也会有一些处理fsync的逻辑,POSIX对fsync发生错误的时候,具体的语义并没有明确的定义。是这篇Paper考察的几个开源的存储系统,认为它们的处理方式都存在一些缺陷。fysnc syscall可能返回多种类似的错误,不同的FS还存在一些细节的差别。一些errno比如ENOSPC、 EDQUOT、EBADF、EINVAL和EIO等。Paper中先测试了一些FS在Single Block Update、Multi Block Append两种workload发生一些错误的情况下,FS的一些行为。这里的错误是使用工具注入的。 Single Block Update: open, lseek(4K), write(4K), fsync, fsync, sleep(40), close. Multi Block Append: write(4K), fsync, sleep(40), write(4K), fsync, sleep(40), close. 对于上面的测试,这里关系这样的一些问题: Basics of fsync Failures: Q1 Which block (data, metadata, journal) failures lead to fsync... Read more!

  • 21 Sep 2020
    Concurrent Updates to Pages with Fixed-Size Rows Using Lock-Free Algorithms

    Concurrent Updates to Pages with Fixed-Size Rows Using Lock-Free Algorithms 0x00 基本内容 这篇Paper讨论的是SQL Server中一个具体的优化。SQL Server中使用PageFreeSpace (PFS) 的结构来管理空闲的存储空间,每个PFS Page管理64MB大小的chunk,一般情况下更新FPS的信息要加上写类型的锁,这里可以优化为Lock-Free的方式。Paper中的例子都是以FPS的更新为例子说明这里的算法,但是可以推广到其他的使用Fixed-Size Rows的Page更新中。SQL Sever中PFS的基本结构如下,SQL Sever使用8KB大小的Page,每个PFS Page前面的几个bit是标志位,后面为记录chunk使用前面的部分,所有这里可以标记8088个page的使用情况。可以看到对应page的标记是固定的,且更新其中的一个不会干涉到另外的一个,这个为这个算法提供了一定的基础。除此之外,SQL Sever使用Index Allocation Map (IAM) Page来记录4GB大小的extent,这个extent为一个allocatation的单元,使用Global Allocation Map (GAM) Page记录依据allocated的extent的情况。 SQL Server是使用ARIES风格的WAL,会周期性地scan buffer pool将dirty page写入到磁盘上面,以及其它的一些操作,来完成checkpoint。SQL Sevrer使用DirtyPageManager管理一个数据库中的dirty page,将它们保存到两个list中,一个list保存是准备更新,后面会变长dirty的,另外一个是记录依据变长dirty的。这里的两个list估计和获取到锁之后,开始写日志到写日志完成的时间过程中使用的。Dirty Page Context(DPC)用来记录一个buffer中 checkpoint ID,也记录buffer中的为dirty状态的第一个 LSN,即用于确定一个checkpoint中最老的page。目前PFS更新的时候,会使用独占类型的latch来保存更新的互斥。在更新一个PFS Page的时候,如果这个信息已经在DPC中存在了,则不用管,否则可能需要记录为最小的LSN。 Void UpdatePage() { Latch the data... Read more!

  • 09 Sep 2020
    LSM-Tree Database Storage Engine and Adaptive Caching for LSM-based KVS

    MyRocks: LSM-Tree Database Storage Engine Serving Facebook’s Social Graph 0x00 基本内容 这篇Papper时关于使用RocksDB作为MySQL存储引擎的时候的一些优化策略。在总体的设计上,RocksDB为LSM-tree的结构,应用到MyRocks时,索引为cluster的。Primary Key中,一个内部的index id和数据库primary key的组合为一个RocksDB的Key,数据看cloumns值作为其RockDB的Value,元数据会包含一些SeqID和Flag的信息。而次级索引包含的Key包含Index ID加上次级的Key,在加上Primary Value,没有Value。 在此的设计知识,这里主要讨论的是MyRocks使用的一些优化方式: Mem-comparable Keys,Key的比较在LSM-tree or B-tree这样的结构是一种常见的操作。LSM-tree在一些操作的时候会比较B-tree进行更多的比较操作,比如找到下一个Key的时候,B-tree用不着比较,而对于LSM-tree来说,需要在多个level中比较,找到实际的下一个。另外MySQL的字符串比较默认是不区分大小写的,这个给比较操作带来了更大的开销。这里会选择将MySQL Key编码为bytewise-comparable的格式。来避免一些额外的操作,比如序列化。这个格式这里没有具体说明,但是这个之前网上就有一些描述了。另外对于RocksDB逆序扫描笔顺序慢不少的情况下,这里引入了everse key comparator,以inverse bytewise order的方式存储到RocksDB中,将逆序扫描转化为顺序的。 Faster Approximate Size to Scan Calculation,这个优化主要是用于指导优化器。这里的scan key的数据在RockDB中,会找到min-key和max-key所在的blocks,并计算两者之间的block数量, We implemented two features to improve the performance of query cost calculation. One was completely skipping... Read more!

  • 03 Sep 2020
    HTAP Database / HTAP as a Service

    F1 Lightning: HTAP as a Service 0x00 基本架构 VLDB‘20上面出现了不少的关于HTAP的Paper,其中这篇是Google的F1最新的一篇,主要的内容是是在现在的OLTP系统和F1 Query上面实现一个HTAP的系统。其核心的方式和不少的系统类似,通过消费OLTP系统的Log,来构造OLAP的部分,实现列式部分的存储。同时AP的查询利用了已经存在的F1 Query系统。从而实现HTAP as a Service。F1 Lightning的基本架构如下,主要的组件有这样的一些:1. Data Storage部分负责对数据进行存储,存储的格式以AP型应用优化;2. Change Replication,负责消费OLTP系统的日志,来更新对于AP的数据;3. Metadata Databse,存储系统的一些元数据和状态信息;4. Lightning Master,负责协调管理Servers。 0x01 基本设计 F1 Lightning使用MVCC的并发控制方式,并提供SI级别的隔离。对于F1 Lightning中的一个查询,会有一个对应read-ts,类似于在TP系统中这个read-ts的一个快照下面的数据读取。这个ts的选择可以决定查询能够看到的数据。这里引入了safe timestamp的概念,即可以被F1 Lightning查询的数据,其中max safe timestamp为到这个时间戳为至的所有变动都已经应用到F1 Lighting中,而min safe timestamp则表示F1 Lightning中能够查询的最老的数据。这里从而得出一个queryable window的概念。和一般的OLAP的系统一样,F1 Lighting存储数据的时候也是使用delta data + base data的方式。F1 Lighting使用LSM-tree来保存,这里保存数据称之为为partial row versions,包含了一行数据一个版本的部分信息,由一个primary key和一个timestamp指定。主要包含三种类型的partial row versions数据:1. inerts,表示添加信息,包含一行数据的全部信息;2. updates,包含一个非key行的某些列的信息,没有更新的列没有包含;3.... Read more!

  • 31 Aug 2020
    Replication Protocols

    Hermes: a Fast, Fault-Tolerant and Linearizable Replication Protocol 0x00 基本思路 这篇Paper提出的Linearizable Replication Protocol比较有意思,和经典的Paxos、Raft之类的方法比较起来,Hermes看起来要简单不少,而且还可以支持从任意一个节点写入操作,而不用和Paxos、Raft一样制定一个Master/Leader。与Paxos、Raft之类的通用的共识协议不同,Hermes更像是一个为Key-Value Store设计的 Replication Protocol。Hermes协议中的一些基本操作如下图,描述如下: 总体的角色分为coordinator和follower两种。客户端请求一个写入操作的机会,向coordinator发动一个写入请求,coordinator将这个写入请求作为一个 Invalidation (INV)消息广播大其它的节点,这些节点称之为follwers。Cordinator本地写入这个Key会处于Write状态。INV消息接受到的时候,这个数据处于无效的状态。Coordinator在INV消息发出之后,等待follwers的ACKs。在收到所有的ACK之后,广播一个 Validation (VAL)消息给其它节点,完成写入操作。如果从这两步的操作来看,这个就是一个2PC的操作。 由于Hermes协议支持从任意节点写入,所有需要一种机制来处理其写入冲突的方式。这里使用的是常见的logical timestamp。这里的每个写入操作的消息都会带有一个递增的logical timestamp,使用lamport lock来实现。这个timestamp逻辑上分为两个部分,[v, cid]。v为这个key的version number,每次操作递增,另外一个cid为coordinator的node id。两个及以上的节点对一个key进行写入操作的时候,这样cid更大节点的写入会成功。 在没有冲突的情况下,Hermes的写入操作话费1.5个RTT,即INV→ACK→VAL的流程。这样这里只要接受到所有的ACK,写入就会被视作完成了。这样的效果是在一些节点故障or网络分区的情况下,可能造成follwers对应key的状态一直处于INV状态。为了处理这个问题,Hermes使用了两种机制,一种是对于一个写入操作来说,如果遇到了之前的INV值,后面的写入会带上新的值,follwers接受到消息之后还是会处于Invalid状态。另外的是logical timestamp使得对于一个Key的写入操作保持了一个全局的顺序。另外如果一个节点发现一个Key处于INV状态太长的时间,它可以作为coordinator的角色,带上原来的original timestamp,replay这个write。 对于follwer接受到写入请求来说,它会先比较这个操作中的logical timestamp,只有在logical timestamp更大的情况下,才会接受这个请求,并将状态置为Invalid,而如果之前处理Write状态 or Replay状态,要置为Trans状态。无论follwer本地进行上面操作,都会回复一个带上INV消息的logical timestamp,也就是如果是这些写入操作接受的话,就是这个请求中带的,如果没有接受的话,会带上之前的。Follower接受到一个VAL消息的时候,如果时间戳对得上,则将Key置为Valid状态,其它情况下这个VAL消息会被忽略。 对于读取操作来说,它可以读取任意一个节点,如果这个Key处于Invalid状态,会一致等待,为Valid状态的时候会返回请求。 0x01 故障处理以及成员变更 故障处理方面,主要总结了这几个方面的处理:1. 网络方面的原因,比如丢失和乱序等。Coordinator对于一个请求会维护了一个超时时间,对于超时没有回复的INV请求,会重试操作。而对于VAL请求,则有Replay机制来处理,这个VAL请求的超时时间由folloer来计时。2. 对于网络分区的情况,前面coordinator处理写入请求的时候,是要等待所有的followers确认INV消息,这种格式简化了一些异常情况的处理,但是却不利于处理网络分区的情况。对于这样的复制协议来说,是很难去区分网络分区还是节点故障的,所有处理办法就是将其当作是一种情况来处理,即一个/一些节点不能正常服务了的情况。 对于网络分区 or 节点故障的处理,这里和要求全部ACK INV消息的特点有些冲突。Hermes的处理方式是使用Membership Lease的方式。意味着这两种故障的情况下,这个Lease的时间段内,不能正常提供服务了, ... the... Read more!

  • 24 Aug 2020
    Zero Downtime Release -- Disruption-free Load Balancing

    Zero Downtime Release: Disruption-free Load Balancing of a Multi-Billion User Website 0x00 基本内容 这篇Paper是Facebook的关于LB的一篇Paper,这篇Paper的主要内容比较有意思:主要是关于如何实现LB的Disruption-free,即可以实现在LB升级的时候也可以不影响到Load Balancing的操作。在FB的系统中,LB在系统中的部署模式如下图,整体是两个部分,Edge PoP和Data Center,两个部分都是一层的L4和一层的L7。L4一层是FB使用最近的Linux内核的一个技术XDP实现了,不知道这个新技术实际部署的比例。另外的L7是FB最近开发的一个库。总体来说。 一个请求的在这个系统中的生命周期如下:1. Edge PoP服务器作为一个类似网关的角色。这里一般是TCP,这个连接的一方是Edge L7LB;2. Edge Proxygen处理用户请求,如果是可以直接处理的, 使用Direct Server Return来直接返回结构给客户端,如果不能则转发到上游的Origin DataCenter;3. Edge 和 Origin会保持一个HTTP2的长连接和MQTT连接,用于传输用户的请求;4. Origin Proxygen负责将请求转发到App. Server(based on the request’s context (e.g., web requests to HHVM, django servers while persistent pub/sub connections to their... Read more!

  • 17 Aug 2020
    Several Papers about KV Stores(3)

    SplinterDB: Closing the Bandwidth Gap for NVMe Key-Value Stores 0x00 基本设计 SplinterDB提出的是一种新的微NVMe优化的数据结构,这个结构称之为STBε-tree。其整体的结构如下,STBε-tree本质上是一个tree的tree,主体称之为 trunk tree,trunk tree的元素为指向B-tree,称之为branch trees。branch trees保存实际的Key-Value Pair。每个branch还有有一个对应的quotient filter, 这个quotient filter的功能类似于LSM-tree中的Bloom Filter。STBε-tree也会有一个Memtable,有点像LSM-tree,Memtable这里实现为一个B-tree。对于一个chuck node指向的一些B-tree,是从旧到新排列的,也就是说,branch i对于的B-tree里面的数据,都添加在i+1的branch之前。另外,在chunk node的一项中,有一个整数a-c,表示对于其一个子节点来水这个branch处于active状态,其它的是inactive状态。这个和STBε-tree的flushing特性相关。STBε-tree的一些基本操作, Query,查询的时候,首先在Memtable中查找,找打就返回。否则继续向下查找,在一个chunk node t查找的时候,先通过pivots找到这个key应该在那个子节点c中,然后在c中从新到旧查找这个key,找到就返回。一个branch中查询的时候,先试查询quotient filter,存在的情况下才实际地在B-tree中进行查找操作。在这种结构中scan操作的时候,需要构建多个B-tree上面的iterator来完成scan操作。 Insert,添加操作的时候,先添加到Memtable中。在Memtable满了的情况下,Memtable作为一个新的branch统计到root chunk node的branch集合中,作为一个最新的。这个操作称之为incorporation。这个Memtable的大小在这里设置为24MB。删除操作和LSM-tree一样,也是添加一个tombstone记录的方式。 Flushing and Compaction,随着Memtable的不断的incorporation操作,root chunk node的branch会变得越来越多。这里引入了Flushing和Compaction操作来处理这个node size增长带来的问题。一个简单的方法是一个trunk node满了的时候,compacting这个node的branchs到一个branch,然后flushing到子节点中。这样的操作可能需要递归操作。STBε-tree会给trunk node设置一个大小的上限。Leaf node满了之后,就需要split操作来分裂leaf node。 一个trunk node p如果被认为是full的(这里的判断依据是其branchs占的总bytes数达到一个阈值)。compacting的时候,这里会创建一个新的branch b,然后选择p的子节点中active key-value pairs最多的c,将p所有branch的c子节点添加到brach b中,然后将这个branch flushing到c。这个过程中还会为b创建一个quotient... Read more!

  • 27 Jul 2020
    Akamai DNS -- Providing Authoritative Answers

    Akamai DNS: Providing Authoritative Answers to the World’s Queries 0x00 基本架构 Akamai是证明的CDN厂商,这篇Paper是关于其DNS服务的一个设计。Akamai DNS的基本架构如下,系统中心的核心是一个authoritative nameservers,为了提供给全球各地用户的DNS查询服务,这个authoritative nameservers的服务器数量是很大的。这些authoritative nameserver服务器分布在全球各定的100多个points of presence (PoPs)中。和一般的DNS服务一样,Akamai DNS也非常依赖于IP的anycast,即任播功能。anycast方便讲DNS请求路由到比较靠近的地方,从而降低RTT,提高性能。这里使用了24 个不同的 IPv4-IPv6 anycast prefix pairs,每个座位一个PoP的anycast cloud,为了容忍PoP的故障,这24个(clouds)是分布在100多个的PoP节点中的,但是一个PoP节点最多使用一个的prefix pair。 PoP的基本结构如下,前面是一个PoP的router,后面是运行着nameserver的若干机器。每台机器也运行着一个BGP-speaker,于router连接advertises地址prefix等的一些信息。另外的一个agent负责监控机器的健康情况。Router在接受到一个BGP advertisement时候,其会将相关信息advertises给BGP neighbors, or peers。Router接受到的anycast的数据包,会通过ECMP的方式发送到这个PoP中的一台机器,一般都是使用addr+port的hash的方式。 authoritative nameserver支持Authoritative DNS Hosting Service (ADHS)。这里还支持DNS zones,企业可以选择6个不同的clouds集合,这里选择6个不同的cloud组成一个集合是配合后面的Attack Resiliency机制。 Enterprises add NS records, each corresponding to a cloud in... Read more!

  • 20 Jul 2020
    Data Center Congestion Control

    Swift: Delay is Simple and Effective for Congestion Control in the Datacenter 0x00 基本内容 Swift是Google提出的一个为数据中心内通信使用的基于延迟的拥塞控制算法。Swift的设计是基于target delay的,即一个目标的延迟,而不是类似的一些算法的delay的变化情况。这就意味着Swift需要对系统中正常的延迟有一个了解,更加适合于情况较为明了的地方。这个算法实现在Google自己的一个网络栈Snap中,Paper中提到这个算法已经使用了数年的时间。Swift将延迟分为了两个部分,一个是NIC-to-NIC (fabric) delay以及 endpoint delay两个部分。Paper中分析了通信过程中的delay的来源, Local NIC Tx Delay,write操作到NIC Tx Queue发动packet的延迟。Paper中提到在使用pull模式的情况下,host在NIC准备好发送的时候才移交packet,这种情况下这个延迟是很小的; Forward Fabric Delay,即packet传输过程中serialization, propagation and queuing delays等等带来的delay,NIC的serialization delay也包括在内; Remote NIC Rx Delay,packet在remote的NIC queue中到被remote的网络栈拿走处理的delay。在远端的host处理能力到达一个瓶颈的时候,这个delay会显著增大。 Remote Processing Delay,remote的网络栈处理的delay,从remote的网络栈开始处理packet到产生和这个packet相关的ACK的过程的delay; Remote NIC Tx Delay,和Local NIC Tx Delay是一样的,这里指的是ACK Packet;... Read more!

  • 17 Jul 2020
    Copysets and Tiered Replication

    Copysets: Reducing the Frequency of Data Loss in Cloud Storage 0x00 问题 这篇Paper很有意思,这里提到的问题解决起来不是很复杂的问题,但是能发现这个问题倒是需要一些灵感。在大型的分布式存储系统中,一般有很多的node,数据以多副本的方式保存。如果这些副本是从node中随机寻去的若干个,比如3个,那么在1%的节点故障的情况下,有数据丢失的可能性是多少呢。这里在加上机器是同时故障的情况下(如果没有及时发现故障数据的情况下,其实也和同时故障差别不大了),如果有5000个节点,则有数据丢失的可能性接近了100%, With this scheme, we will only lose data if all the nodes in a copyset fail simultaneously. For example, with 5000 nodes, this reduces the data loss probabilities when 1% of the nodes fail simultaneously from 99.99%... Read more!

  • 23 Jun 2020
    Long-lived Transactions Made Less Harmful

    Long-lived Transactions Made Less Harmful 0x00 基本思路 这篇Paper是关于如何处理数据看长事务的。在MVCC的系统中,数据以多版本的方式保存,一个版本的数据不会在有事务访问的时候,就可以进行回收操作。一般的系统就是以目前系统中活动的“最老”的事务来判断哪些版本的数据可以进行回收操作。这样的方式在有长事务的情况下会导致一些数据迟迟不能回收,对系统的正常运行影响比较大。这里提出的思路是Single In-row Remaining Off-row (SIRO) versioning,即只将一条记录目前的数据和其之前一个版本的数据放到数据Page中,另外的版本放到另外的一个地方来保存。SIRO的思路在两个场景的开源数据库MySQL和PostgreSQL中都实现了,而且测试的结果看来很不错。不同版本的数据存储使用的方式一般就是in-row的方式或者是off-row的方式,而如下图所示,MySQL使用的就是off row的方式,非当前的数据会被保存到undo space。而PostgreSQL使用的是in row的方式,旧的版本也会保存到一般的数据page中。这里的思路优点类似于两者思路的结合,又加上了其它的一些优化。对于PostgreSQL,这里分析认为PostgreSQL的方式会造成Repeated page splits would severely impinge on a degree of concurrency,而MySQL的方式 latch duration on a page increases as a version chain grows in MySQL, whereas travers ing an elongated version chain from the oldest version... Read more!

  • 17 Jun 2020
    CockroachDB - The Resilient Geo-Distributed SQL Database

    CockroachDB: The Resilient Geo-Distributed SQL Database 0x00 事务 与上面Taurus Database的Paper相比,这篇Paper描述的CockroachDB数据库的架构师模仿Spanner的架构。Paper的内容没有太多新的内容,因为CockroachDB主要的技术都是已经被网上有了相当多的描述,这篇Paper类似于一个总结。看这篇Paper需要对CockroachDB(CRDB)已经有了一些的了解。事务这里首先就设计到了在CRDB中事务操作的基本逻辑和写入事务两个核心的优化。CRDB中,一个事务从一个gateway节点接受到SQL请求,这个节点会负责和客户端进行交互,另外有作为一个 transaction coordinator 。对于一个coordinator事务相关的部分操作逻辑如下。这个描述地很简洁,一些细节方面就里面设计到很多的,具体可以参考网络上面能够找到的资料。这里按照Paper中的描述来说明一些事物操作的基本流程已经一些主要的优化。从coordinator的角度来看,这里已经是SQL转化为来若干的KV层面的请求。一般的逻辑下面,下一个操作的发出得等到上一个操作发挥,另外就是操作得复制到足够的节点上面才能认为是完成了。为了优化这两个问题,CRDB引入的优化就是Write Pipelining 和 Parallel Commits:Write Pipelining可以使得一个操作在没有复制完成之前就返回,而 Parallel Commits使得commit操作可以和write pipeline replicate操作并行进行。 Write Pipelining。这里讨论的一般的事务情况形如这样的操作: BeginTxn; Operation-0; Operation-1; Operation-2; CommitTxn; 不同的操作一般的情况下就是先后执行。最直接的方式是每次操作都成功之后在执行下一个操作,这样的方式性能方面会有比较大的问题。另外的实现方式,和很多相关的系统使用的一种思路是将写入操作的数据先保存到本地,然后在Commit的时候一起去写入,这样避免了一些分布式的操作。而这里使用的方式是Write Pipelining,即每个操作可以直接返回结果,然后异步的执行操作。在Commit的时候再去评估一个操作是否成功,这个也利用了这个BeginTxn然后在执行操作最后执行Commit操作上面的特点。所以在这种情况下,Coordinator需要知道目前正在操作中的操作,记录在inflightOps中。CRDB使用MVCC的方式,这里在开始的时候也是获取了一个时间戳。这里的时间戳也是从本地获取的,和一些类似的系统使用一个中心化的时间戳分配服务不同,也和CRDB主要参考的Spanner的TrueTime有所不同,不需要特殊的硬件支持。一个操作在不是commit操作的情况下,且和前面的操作没有重叠,这个操作就可以pipeline执行。如果一个操作和前面的操作有重叠,就需要等待前面的操作被复制完成,这个称之为pipeline stall。实际的操作被发送到Leaseholder来执行。这里注意的是Leaseholder操作可能返回一个更大的时间戳ts,这种情况下,需要检查对应的key在ts到返回的ts中间的这段时间也没有改动,如果没有更新这个txnTs,如果有这个事务就被认为是操作失败,可能需要重试操作。 Parallel Commits操作则使得commit的操作可以异步执行。体现在下面算法中的最后两步。一个如果一个事务的所有写入内容都被复制完成之后,后面的commit操作是一定能够完成的。所以到了这里就可以先返回成功再去实际地commit。为了实现这个功能,CRDB引入了一个staging的事务状态,表示一个事务操作的所有写入是否都复制完成了。这个优化取得的效果很明显, Parallel Commits improves throughput by up to 72% and reduces p50 latency by up to 47%... Read more!

  • 12 Jun 2020
    Taurus Database - How to be Fast, Available, and Frugal in the Cloud

    Taurus Database: How to be Fast, Available, and Frugal in the Cloud 0x00 基本架构 这篇是SIGMOD ‘20上面关于发表的关于分布式数据库的Paper,使用了今年来的分布式数据库的一种的经典架构。Taurus Database是一种类似于Aurora的架构,在一些地方进行了一些调整。总体的架构上面,前面的是Database front end,多使用改造之后的MySQL or PostgrSQL来实现,相当于一个计算层,一般都是一个主节点,若干的从节点。这里没有提到多主的内容。存储层分为LogStore和PageSroe。计算节点和存储节点沟通使用称之为Storage Abstraction Layer的Library。显然LogStore由于处理数据人日志的存取,而PageStore处理数据库Page的存取。LogStore在环境中作为集群来部署。 LogStore中一个写入Log的抽象称之为PLog,使用一个24byte的ID表示。在写入数据的时候,写入LogStore三个副本成功就相当于写入操作成功。如果写入失败,则会导致切换PLog的操作,选择集群中其它的节点来创建新的PLog再执行写入操作。PLog会设置有一个大小上面的限制。LogStore的读取操作主要来自两个地方,一个是读/从节点会从LogStore读取主最近写入LogStore的数据。所以为了加速读取,对于最近的数据LogStore会使用一个FIFO的方式来缓存。另外一个是数据库recovery的时候需要从中读取committed log records的数据。一个数据库对用的多个PLog的元数据信息被保存到另外一个PLog中,这些信息同时也会换成在数据库节点的内存中。 PageStore保存数据库的Page。主节点更新Page的时候,通过LSN来表示这个Page的版本。所以唯一表示一个Page使用其PageID+LSN。PageStore提供的API主要是下面几个, (1) WriteLogs is used to ship a buffer with log records (2) ReadPage is used to read a specific version of a page... Read more!

  • 08 Jun 2020
    Several Papers about KV Stores(2)

    Rosetta: A Robust Space-Time Optimized Range Filter for Key-Value Stores 0x00 基本思路 这篇Paper是关于LSM-tree中一个Range Filter的一个设计以及其数学方面的一些分析。目前LSM-tree使用Bloom Filter来优化查询一些不存在key的情况,而这个Bloom Filter只支持单点查询的Filter,不支持Range Filter,也就是一个范围内有木有数据存在这个KV Store。在SIGMOD ’18上面发表的一篇论文是基于Succinct的。这篇Paper则提出来一种基于Boom Filter来实现Range Filter的法案,和之前的一些统计方式类似,比如Persistent Filter,使用了层次式的结构。其基本结构如下,这里显示的不同层的Filter差距为一个bit,是一个示意。Paper中实际算法描述的时候为下一层的prefix长为前一层的两倍(最后一层应该特殊处理)。对于添加数据的时候,对应的filter构建就是以其不同长度的prefix来构建不同的Bloom Filter的过程。这里又有点Segment Tree的思路。 在这样的设计下面,查询的操作基本思路如下:1. 对应点查询,很简单的就是对应到最后一层的Bloom Filter的查询;2. 对应范围查询,基本的思路如下图,查询的思路和在Segment Tree类似结构中的查询类似。每次往下查询,都是选取更长的prefix,将以每个可能的prefix都查询一次。在一些情况下,结构可能不必要查询到最后面就可以返回。 结构本身不是很复杂,Paper中对此进行了详细的数学方面特性的分析,涉及到不少的推导,和这个团队的其它论文的风格很相似呀。得出一个核心结论如下图:对应Paper中的分析,核心就是一般来说,对于Short and Medium Range Queries,Rosetta比现在的SuRF更加有优势,而更大的Range,则直接就是列存更好,SuRF更好的范围比较小。另外,在使用内存越多的时候,Rosetta比SuRF的优势家更加明显,大到一定程度的时候,两者的内存开心都显得划不来了。 0x01 评估 这里的具体内容可以参看[1]. EvenDB: Optimizing Key-Value Storage for Spatial Locality 0x10 基本思路 从将故事的角度来看,这篇Paper讨论的是KV Store在Spatial Locality上面的改进。总的来说,EvenDB的思路是一种单层的、range partition的LSM-tree的一种变体。基本结构如下图。整个的数据被分为一个个的chunk,就是一个range... Read more!

  • 28 May 2020
    Resumable Online Index Rebuild in SQL Server

    Resumable Online Index Rebuild in SQL Server 0x10 引言 这篇Paper关注的是数据库论文中很少涉及到的一个内容,是一篇工程性质的论文。主要的内容是关于数据索引重建,一般在某些操作之后进行索引重建的工作可以提供性能,减少占用的磁盘空间等。这里主要关注在在云环境的情况下,如何处理在索引重建工程中的failure问题,从而提出了Resumable Online Index Rebuild的思路,即索引重建可以从系统failure之前的位置重新开始。另外的一些race condition的处理也比较有意思,相关的心Index创建的问题在92年的一篇Paper中有讨论, 提出了两种基本的方法,这里使用的方法类似于其中描述的NSF,No Side File的方法。索引重建工作一般分为三种步骤: Preparation Phase,这一部分先建立一个新的空索引。在这一部分的时候它先先获取一个表上的S LOCK,用于等待这个表上面的更新操作完成,以及阻塞后面的更新操作。更新元数据之后,就释放这个S LOCK,所以不会有影响。这样做的目的是更新元数据,以便让后面的更新操作知道有这个重建过程中的索引,而进行更新添加到这个索引中; Build Phase,这一部分操作会扫描原来的索引,在需要的时候对数据进行排序,然后重新添加到新的索引中。在这个过程中,对表的更新操作要同时更新所有存在的索引,包括创建中的索引。 Final Phase,在新的索引创建完成之后,索引创建进程/过程会请求一个table的X LOCK,一个原因是等待现在的操作完成,同时Block后面的操作。请求到X LOCK之后,更新元数据,更新完成释放LOCK。后面的操作使用元数据更新完成之后table的情况进行处理。 在前面的基本操作流程之上,还有一些额外的race condition需要处理,1. 比如一个删除操作删除一行数据的时候,这行数据以及被Index Builder读取到了,但是还没有添加到新的数据中。这种情况下,这个删除操作可能删除新index的数据的时候没有看到这行数据,但是之后有被重新添加进去。2. 一个添加操作需要添加到原来的index和新的index,Index Builder读取的数据的时候,和添加新数据的操作之后操作原index和新index的顺序相关,可能导致一个duplicate key的错误。3. 一个并发的DML操作可能在任何时刻进行回滚操作,Index Builder操作需要保证操作完成的时候只会包含一句提交的数据。SQL Server这里使用如下的方法来解决这样的一些问题, 这里没有使用某些特殊类型的lock or logging方式来保证新 index中值包含以及被提交的数据,而是使用扫描的时候扫描一个snapshot。Index Builder扫描原index的时候不需要获取LOCK(s),而在讲数据添加到新index的时候,想要获取exclusive row locks,来同步并发的在新index的更新操作。这里还使用批量出来的方式来提高性能。 为了解决前面提到的删除的问题,这里使用了一个deleta anti-matter的方式。一个删除操作在新index中没有发现对应行的数据的时候,会在新index中添加一个对应key为deleta anti-matter的数据。Index Builder添加数据的时候,发现这样的一行记录的时候需要讲这行数据删除,需要讲对应行的数据删除。Index Builder扫描的是一个snapshot的数据,能保证deleta anti-matter的数据在最后都会被删除。... Read more!

  • 22 May 2020
    Buffer Pool, Logging, Checkpoints, and Recovery for LeanStore

    LeanStore: In-Memory Data Management Beyond Main Memory 0x00 基本设计 这篇Paper是一个关于Storage Engine的一篇Paper。这篇Paper之前的一些研究是关于如何讲数据都放到内存中来处理,之后的研究中变为了来将一部分冷的数据放到磁盘上面来。又回到了类似之前普通数据库系统的思路,当然还是存在一些差别。这篇Paper重要将的是LeanStore的Buffer Pool方面的设计,存储上面LeanStore还是一个基于Btree的设计。其核心的一个设计是Pointer swizzling。Pointer swizzling就是一种引用数据Pape的一种技术,在一般的数据库系统中,一个page可能在Buffer Pool中,也可能还在磁盘上面。在这里一个swizzled的pointer指向一个已经load到内存中的page,而一个swizzled的指针引用的是磁盘上面的一个Paper。一般的Buffer Pool使用的时候,都要经过PageID到Pointer的转化,才能引用到内存中的Page。这里的实现一个就是使用一个hash table。基于hash table的buffer pool一个好处就是在一个地方统一管理内存中的page,page替换算法实现比较简单。 而这里基于pointer swizzling方法的情况下,引用一个page的指针是可能有很多个,而是是分散的。这里的解决办法是一个page只会有一个引用的结构。另外设计上面的一些考量是不会unswizzle掉一个有内存中page的page,这样处理的时候可以避免一些麻烦。另外一个page上面的指针信息可能被写入到磁盘,但是重新启动之后,这些指针的值对于新的进程来说是没有意义的,这样需要在evict一个inner page的时候,处理好其上面保存的子page的信息。这里和前面的不会unswizzle掉一个有内存中page的page设计相适应。在此基础之上的另外一些设计: Cooling Stage,Cooling Stage用于处理page替换的问题。基于hash table的buffer pool由于集中管理page,page替换实现比较直接。一般的LRU的思路是将最频繁使用的page放到一个list的前面,实际上是监控最频繁使用的page。而这里选择的方法是监控不频繁使用的page。LeanStore会speculatively的去unswizzle一个papge。speculatively地选择的page会不立即被evict,而是放到一个cooling stage的结构中。这里的思路类似于一些缓存替换算法中在给一次机会的思路,如果判断事物,可以被简单地重新拿回来。 这里Cooling Stage中会保存大概10%左右的page,大部分的page还是会在hot stage中。这里的主要结构是一个fifo队列,一个pape在到达这个queue的末位的时候就会被真的evict。访问page的时候,想要知道这个page在不在Cooling Stage中。为此这里又加了一个hash table来记录Cooling Stage的一些信息。如果访问的一些page在这里,那么会被从Cooling Stage中撤销。这个移动page的操作可以同步or异步地完成,LeanStore选择的是同步的方式。LeanStore还使用一个另外的一个hash table来管理loading中的page。对于每个load中的page使用一个mutex,到达serialize这里操作的效果。估计是类似于single in-flight的设计。 在这些设计的基础之上,一些操作的示意如下。Speculatively地unswizzling一个page就是使用随机选择的方式。由于要满足不会unswizzle掉一个有内存中page的page,就需要迭代查找器子page的情况,如果发现其子page中存在swizzled的,就使用这个子page替代。 另外这里的Optimistic Latches设计和Epoch-Based Reclamation都是来自已有的一些设计,没有太多特别的地方,内存的分配上面也考虑到NUMA的一些特点。另外LeanStore提到了实现上面的一些优化,比如将buffer frame和page的内容直接放到一起(buffer frame是buffer pool管理单位的一个抽象,对应到一个具体到page),而不是和一般的buffer pool一样一个buffer frame中使用一个指针来引用这个page,这样来提高数据的局部性;使用thread-local cache for deleted pages的思路来提高请求一个新page的性能;使用... Read more!

  • 18 May 2020
    Real-time Analytics and Transaction Processing in SAP HANA

    Efficient Transaction Processing in SAP HANA Database – The End of a Column Store Myth 0x00 基本思路 SAP HANA数据库是一个列式存储的数据库。这篇Paper的核心是将了SAP HAMA 2层的delta的数据存储的设计,这里虽然还将到HANA数据的一些功能特点,但是好像就是一些功能介绍。HANA主要还是一个为分析类型的workload设计的数据,使用列式存储,这样对于高效执行一些事务处理就会比较麻烦。一般的设计是使用存储delta数据和存储主要数据的部分组成,比如前面的SQL Server的为分析型workload的优化。HANA这里的特点是不仅仅是单个的保存delta数据的设计,而是使用了2层的设计。基本的思路如下图, L1-delta,L1-delta数据保存方式是一个写入优化的设计。一般的数据写入的时候都是先写入到L1-delta,然后通过merge操作到L2-delta。这里数据是没有压缩的,数据上面的操作也应该是直接直接操作的方式。单个节点上面L1-delta一般保存10000到100000行的数据,从下面的图来看,这里的存储方式是以行存的方式存储的; L2-delta,L1-delta类似于长的delta+main-store的设计。而L2-delta是HANA这里有特点的一个部分,这里的存储方式是以列存的方式存储的。除列列存之外,这里还使用了dictionary encoding来实现数据压缩,但是这里的dictionary数据是没有压缩的。未来更高效地支持一些操作比如点查询,这里需要一个索引。单个节点这里L2 delta Store的大小在10 Million级别; Main Store,这里复制保存大部分的数据,这里保存的数据会以更高压缩率的方式保存: .. all values within a column are represented via the position in a sorted dictionary and stored in a bit-packed... Read more!

  • 12 May 2020
    Column Store Indexes

    SQL Server Column Store Indexes 0x00 基本设计 前面看了SQL Sever中指出OLAP功能的一些设计,这篇Paper就描述了其Column Store Indexes的设计,在看前面的两篇的时候最好看看这篇。在SQL Server中,primary index支持 heaps index(unordered) and B-trees index(ordered),但是secondary index支持btree index,不支持heaps的,当然还有另外的一些类型的index。这里的column index是添加了另外的一种index模式。在column index的物理存储设计上面如下:全局的数据会被分为row group,每个row group的数据量在、million左右,然后每个group中,不同的列会被分别压缩保存,称之为segment。segment使用SQL Server的 separate blob (LOB)来保存。 在这些segments之上,会有一个segment directory,记录了每个semgent的一些原数据,比如number of rows, size, how data is encoded, 和 min and max values等的信息。这样的保存方式之上,如何压缩数据是一个比较重要的内容, Encoding,这里关于如何将书表示为32bit or 64bit的整数表示,使用两种方式: a dictionary based encoding 和... Read more!

  • 03 May 2020
    HTAP with SQL Server

    Real-Time Analytical Processing with SQL Server 0x00 基本架构 这篇Paper是关于SQL Server的OLAP拓展。下面的SQL Server的基本架构图上面,近些年在原来的传统的Disk Based ROW Store的基础之上,有发展了内存存储引擎和Column Store。这里主要是关于OLAP的部分,即Column Store部分,这里功能的实现也会利用Hekaton提供的一部分功能。SQL Server这里将列存的索引称之为,columnstore index (CSI) 。CSI的存储利用了SQL Server blobs (LOB)的功能,这里的数据会被按列拆分分别存储,然后将这些数据拆分为segment,每个segment有million左右行的数据,一个segment作为一个压缩的整体保存,一个directory结构会保存segment的位置信息以及用于压缩的相关数据,频繁使用的数据会被cache在内存中, ... A directory keeps track of the location of segments and dictionaries so all segments comprising a column and any associated dictionaries can be easily found. The... Read more!

  • 20 Apr 2020
    Inverted Files for Text Search Engines

    Inverted Files for Text Search Engines 0x00 引言 这篇Paper是一篇总结性的文章,发表在06年,是一篇关于Inverted Index的一篇很好的文章。Inverted Index涉及到很多的数据结构和算法的设计,这里主要讨论的是Inverted File的设计。Inverted Index简单地说就是为文档建立索引,是Text Search Engine的一项基本的技术。Paper中先介绍了搜索中要考虑的一个重要因素,就是如何判定一个doc为用户想要搜索的doc。这里设计到以下的概念/统计数据, — f_{d,t}, the frequency of term t in document d; — f_{q,t}, the frequency of term t in the query; — f_{t}, the number of documents containing one or more occurrences of term t; —... Read more!

  • 17 Apr 2020
    Statistics in Orcacle Database

    Efficient and Scalable Statistics Gathering for Large Databases in Oracle 11g 0x00 基本内容 这篇Paper主要的内容是Oracle数据一些统计方式的算法,主要讨论的是在分区表的情况下如何统计一些表的信息。Paper中描述的统计信息主要是一列中不同值的数量,类似于HyperLogLog做的事情。数据库统计主要用于优化器,一般有row sampling和block sampling的策略,前者更加接近于随机的取样,但是可能造成读取更多的数据,而后者随机性差一些,可能需要读取的数据更少。这里使用One-Pass Distinct Sampling的方式来统计一列不同值的数量。基本的算法比较容易理解,和HyperLogLog的思路有一些相同的地方。这里使用的算法也是在之前的算法上面优化而来的。基本的算法表示如下: 算法维护一个暂存的集合S,一个depth值d。对于每一个数据,计算其hash值h。如果hash值的前面d个都为0(实现的时候一般就是一个64bit hash的前面d bit都为0),且h不在s中。如果S的大小达到了一个阈值N,则将d自增1。移除此时d位hash为1的对象,否则将h加入到S中。最终的结果为2^d * S. Paper中对于这个算法的精确度给出了证明,表示为 \(\\ error ≈ \frac{\alpha}{s}\sqrt{s\cdot 2^d(1-2^{-d})}≈\frac{\alpha\cdot 2^{d/2}}{\sqrt{s}}.\\\) 如果将s设置为2^d * N/2,可得 \(\\ error ≈ \frac{\alpha\cdot 2^{d/2}}{\sqrt{2^d\cdot N/2}} = \frac{\alpha\sqrt{2}}{\sqrt{N}}.\) 其中s为实际不同值的数量,N暂存几个的大小,a为统计标准差,variance表示为$ s\cdot 2^d(1-2^{-d}) $. For example, for N =... Read more!

  • 13 Mar 2020
    The Snowflake Data Warehouse

    The Snowflake Elastic Data Warehouse 0x00 引言 Snowflake是一个Data Warehouse的解决方案,基本特点是面向云,Software-as-a-Service (SaaS)的设计,采用存储计算分离的架构,支持弹性伸缩。Snowflake支持关系型数据库的一些特性,比如ANSI SQL的支持,以及还支持 ACID事务。Snowflake中保存的数据是半结构化的,本身就支持JSON、 Avro结构的数据。另外一点就是Snowflake支持end-to-end的全程数据加密,这个也是对安全性要求很高的企业服务的一种特性。部分功能特点: Pure Software-as-a-Service Experience,完全作为一个服务; Fault Resilience,高可用,高可靠。无缝在线版本升级; Semi-Structured and Schema-Less Data。处理长久的关系型数据中的数据,还支持ARRAY,OBJECTs,VARIANT之类的数据类型。 0x01 计算&存储 Snowflake的基本架构如下图,其主要分为三层。底层的是存储,Snowflake很特别的使用了S3存储最底层的存储方案,中间一层称之为Virtual Warehouses,为计算层,使用Amazon的EC2服务。最上层的是Cloud Services层,这里主要负责管理查询、Virtual Warehouses和处理元数据等的任务。 存储层Snowflake使用了S3的存储方式,其特点是应用参数、高可用性,可以实现很高的吞吐。缺点是高延迟、另外不支持append这样的操作,但是支持完整覆盖一个Object。S3在Snowflake中不仅仅用于存储持久化的数据,而且被用于存储临时数据,方便Snowflake可以支持产生非常大量中间结果的操作。S3最为一种Object Storage,其特性也影响到了Snowflake的设计:Snowflake将Table的数据拆分为一个个的partition,每个partition比较大,是不可变的。在一个partition内,Snowflake使用一种行列混合存储的、类似PAX的存储方式。每个File(在S3中应该称之为Object),会有一个header,记录不同的Column在在这个Object中的Offset,这样获取一个Column数据的时候,就可以根据这个Header的信息,利用S3提供的Get Range的操作只Get这一部分的数据,而不用Get全部的数据。元数据,比如一个table有哪些 S3 files组成, 统计数据, locks, transaction logs,被保存一个支持事务的分布式key-value store中,这个组件属于Cloud Services部分; VWs最为计算层,实际上就是一些EC2的实例。使用EC2好处就是其可以被按需求创建,拓展和销毁等。在没有查询的时候,可以完全将VMs的机器关闭,这样就可以节省成本。一个查询操作只会运行在一个VW中,这样就可以获得很好的隔离性。Paper中这里提到,目前一个Worker Node不会在多个VMs中共享,但是会是未来工作的一部分。共享可以获取到更好的资源利用率。一个查询在被分配到一个VM中的时候,其工作会被拆分为多个部分,由VM中不同的Worker Node执行。失败的查询会通过重试来解决。一个查询只会早一个VM中执行,但是一个用户可以的任务可以在多个VMs中支持。 因为使用S3存储会带来更高的延迟,Snowflake在计算层使用了一层缓存。缓存数据被保存到本地的磁盘上面,根据Column使用不同的文件保存。并使用LRU算法管理缓存淘汰。多个Worker Node可能带来缓存多份的问题,Snowflake通过将在一个files上面的work根据一致性hash的方式分发到worker nodes上面。同一个文件上面的操作会一般在同一个node上面运行,提高缓存命中率。Snowflake这里的一致性hash使用一种lazy的模式,即在节点数据增加 or 减少的时候,不会立即导致data shuffle, This solution... Read more!

  • 09 Mar 2020
    Packets Drop in Data Center

    Pingmesh: A Large-Scale System for Data Center Network Latency Measurement and Analysis 0x00 引言 Pingmesh是微软开发的一个测量数据中心中网络延迟和丢包率的Paper。Pingmesh在这个方面是一篇比较重要的文章。Pingmesh的思路在于使用数据中心内全部的服务器进行TCP or HTTP的ping操作,来测量数据中心内部的网络情况,可以提供最大的覆盖率。测量到的数据会被汇总处理,之后在多个层面展示数据,比如一个机架内的、以ToR交换机为一个抽象节点的已经整个数据中心层面的等。这个系统也是微软在实际的环境中使用的多年的一个系统。 0x01 基本设计 Pingmesh的基本架构如下,主要包含这样的一些组件:1. Pingmesh Controller,用于控制每个server上面的agent的操作。会对每个server产生一个pinglist文件,这个文件包含了这个server需要ping的servers已经相关的参数。这个pinglist有Controller根据网络拓扑产生,server通过一个RESTFul的API获取到;2. Pingmesh Agent,Agent从Controller下载pinglist文件之后,会对这个pinglist中的server进行TCP/HTTP的ping操作,将数据保存在本地的内存中。在一段时间过后 or 本地buf的数据达到一定量之后,在这个数据上报保存到一个分布式存储系统Cosmos中。另外Agent也会收集一些性能统计信息,会讲这些信息上报到Perfcounter Aggregator中;3. Data Storage and Analysis (DSA),这个DSA就是用于数据处理、分析用的。 Pingmesh Controller,Controller的一个核心功能就是产生pinglist。这个的设计考虑了从不同的层面,首先是一个Rack/Pod level的,这里应该就是单个的server,另外就是一个intra-dc的level,这里不是将每台server作为一个节点,而是将一个ToR作为一个抽象的节点,减少节点的数量,还有局势inter-dc level,每个数据中心作为一个虚拟的节点。虚拟的节点不执行实际的ping操作,而是选中这个节点中的一些server执行。ping对象选择上面,则选择了ping不同层面的所有节点的方法,以达到最高的覆盖率。经过三个层次的抽象,这个每台机器需要ping的servers数量在2000-5000的级别。 Ping Agent,Agent ping操作的实现使用了TCP/HTTP层面实现ping操作,而不是一般的ping命令的ICMP层面的。这样更方便用于区分出网络出现了那种类型的问题。在实现的时候,Agent特别注意使用很少的资源,所以Agent使用C++实现,而且不使用其它任何的库,直接使用winsock实现。 Data Storage and Analysis,这里就是一个数据存储,分析类型的应用。 0x02 数据分析 关于不同数据中心,不同Level的延迟Paper中总结了一些数据,这个和具体的数据中心的情况相关性很大。因为就是丢包率的测量,Paper中使用的是如下的计算方式, \(\frac{ProbesWith3sRTT+ProbesWith9sRTT}{TotalSucessfulProbes}.\) 这里计算的时候只使用成功的探测的次数,而不是全部的。对于失败的,这里还无法区分具体是哪里出现了问题。公式中的3s和9s和Windows系统中TPC连接建立的超时时间时间相关。9s应该是下次的超时的时间,这里只计算了一个丢包,因为Pingmesh认为前后的两次丢包存在比较大的联系,比如第一次丢了,第二次丢的可能性很大。另外一个特别提到的问题是静默丢包,比如packet black-hole 和... Read more!

  • 03 Mar 2020
    Fault Tolerance in Practice

    Maelstrom: Mitigating Datacenter-level Disasters by Draining Interdependent Traffic Safely and Efficiently 0x00 基本概念 这篇Paper描述的Facebook用于将一个Datacenter内部的流量转移到另外的Datacenters的工具,用于解决DC级别的容灾的问题。Maelstrom很好的解决了不同类型的服务的流量迁移操作,并将相关的演练经常进行,常态化。在了解Maelstrom的基本设计之前,Paper描述了Facebook很High Level的一个架构。用户的流量经过PoP接入,在这里一个四层的Edge LB流量转发到不同的DCs中,一个DC会逻辑上面将其分为不同的Clusters。Cluster有Fronted Cluster和Service Cluster,两者前面都会有一个七层的LB。一个服务会使用到不同DCs的多个Clusters,对于一个服务,会分配一个VIP用于用户请求到对用的服务,一个VIP包含了edge weight和cluster wight属性的信息,前者用于edge LB转发到那个DC的流量的比例,而后面决定了转发到那个Cluster流量的比例。 流量会分为不同的类型,Maelstrom这里总结为这样的几种,1. Stateless,很大部分的流量都是Stateless的,这种力量转移起来比较简单,改变转发的方向就可以了;2. Sticky,这种类型的流量包含了Session信息,比如Messaging类型的服务。这类型的转移起来需要重新建立Session;3. Replication,这类型的流量来自于分布式存储系统复制的流量,改变这些流量需要对系统进行重新配置。需要停止使用这个数据中心,或者是使用其它的数据中心替代。需要相关的系统有对应的处理逻辑。一般而言对相关系统要求比较高。4,Stateful,一般是主从类的系统,如果是Master在故障/模拟故障的数据中心,需要有切主的操作。另外可能需要讲一些states信息复制到新的DC。 0x01 总体设计 Maelstrom作为一个generic流量迁移到系统,它将相关的操作抽象为一个个的tasks。若干的tasks组成一个runbook,代表了迁移流量的具体的一些操作。一个runbook记录了这样的一些内容:Task specifications。具体描述这个runbooh包含的tasks。比如这样描述的一些task: TaskTemplate Parameter Description TrafficShift {vip type, target, ratio, ...} Shift traffic into or out of a cluster or a datacenter (specified... Read more!

  • 27 Feb 2020
    New Ideas for Key-Value Store and Cache

    FPGA-Accelerated Compactions for LSM-based Key-Value Store 0x00 基本思路 这篇paper是关于如何用FPGA处理LSM-tree Compaction的问题。LSM-Tree的Compaction是LSM-Tree设计实现中一个很麻烦的问题,处理不好就容易导致性能的问题,特别Compaction带来的性能抖动。LSM-tree的Compaction操作会消耗大量的资源,这篇Paper的思路就是将一部分Compaction的操作offload到辅助计算设备上面,这里使用的是FPGA。之前微软有一些关于用FPGS处理网络的研究,而这里则是用来处理一些存储系统的问题。 0x01 基本设计 这里设计的基本架构如上兔所示,由于FPGA的工作模式和CPU存在很大的差别,不是一般意义上面的冯诺依曼架构。一般在利用FPGA处理认为的时候,很常见的一个实现方式是想要工作拆除一个个流水处理的单元。这里也是使用这样的思路。由于FPGA这里作为一个协处理器的角色,很多事情还是要CPU来处理。这里CPU要处理的事情就是将工作任务包装作为一个个的Task的抽象,并要负责这些Task的调度以及直接结果的处理。基本的处理如下图所示,工作流程中主要有这些的一些角色以及其处理的工作, Builder线程。在一个Compaction操作被触发知乎,Builder线程负责将要进行Compaction的数据进行拆分,包装为一个CompactionTask的结构。在这个结构中,主要的字段是指向对应的task queue、输入数据、运行结果以及回调函数等。一个CompactionTask构建之后被添加到一个Task Queue中,等待被FPGA执行相关的操作。FPGA处理完毕之后,结果被添加到Result Queue,Builder线程也会检查Result Queue,处理FPGA返回的结果。在FPGA处理识别的时候,会转移到CPU处理逻辑,Paper中提到FPGA处理会有0.03%左右的识别概率,主要是一些比较长的数据字段导致的; Dispatcher线程。Dispatcher线程线程负责从Task Queue获取Compaction Task,然后分发到合适的FPGA的Computation Unit来处理。这里使用的负载均衡的测量就是简单的RR测量; Driver线程。Driver线程负责负责相关的数据传送,并在将数据传送到FPGA上面的时候,通知FPGA进行实际的Compaction的操作。在一个Compaction Task操作完成的时候,Driver线程会执行回调函数,用于将操作之后的数据传送回主机内存。然后将结果push到Result Queue中。 FPGA上面的处理实际上就是一个多路归并的过程。这里的LSM-Tree使用的Tier Level的分层的方式,意味着一层内的SST文件的Key Range是可能重合的。这里带来的是写入性能的提升,但是读取的想念回变差。这个时候就想要将一些SST文件归并操作,达到提高性能的目的。这里从内存中输入来的多路数据,会先进入一个Decoder来对数据进行decode的数据,方便内部操作这些数据。这些多路归并的路树选择是一个想要tradeoff的问题,这里选择的是4路,一般和具体的情况相关。在decodeer之后是一个ing buffer,用于暂时保住被decoded的数据, The KV Ring Buffer caches the decoded KV records. We have observed in our practices that KV sizes rarely exceed 6KB.... Read more!

  • 21 Feb 2020
    New Ideas for Replication

    Fault-Tolerance, Fast and Slow: Exploiting Failure Asynchrony in Distributed Systems 0x00 基本思路 这篇Paper是Raft,ZAB之类分布式一致性协议的一些优化。这里提出的优化称之为situation-aware updates and crash recovery (SAUCR)。现在的很多一致性协议的实现,为了保证数据的持久化,会在返回结构之前使用fsync之类的方式来将数据刷到磁盘上面,数据每次都持久化可以提供可用性,降低数据丢失的风险,但是也会损失一些性能,而另外的对应设计是Log保存到内存中就返回,优缺点互换。SAUCR从实际的数据中分析出,在集群中会经常有机器故障,但是有多台机器同时故障的概率是很低的的。SAUCR从这点出发,给出了一个Memory Log和Disk Log结合的设计:在集群完整正常运行的时候,出于fast mode情况下,数据保存到内存中就可以直接返回,而如果一部分的机器故障,则切换到slow mode,数据得fsync到磁盘上面才能返回。这也主要影响到Raft、ZAB的两个方面的设计,一个是如何在这两种模式下切换,另外一个是恢复如何处理。 Mode Switches SAUCR在集群中有超过bare majority个节点正常工作的情况下出于fast mode。Bare majority即指的是刚好超过一般的节点数量,而超过bare majority最少的输入自然就是bare majority + 1。这样看来,如果集群的节点数量,SAUCR是起不到优化的作用的,所以Paper中讨论的时候都是假设系统是5个节点。至于为什么要比bare majority还要多1,主要和SAUCR恢复操作相关。故SAUCR假设Protocol是一个leader-based的协议,所以这里故障分为leader的故障和follower故障, follower故障,在follower故障到只有bare majority正常工作时(leader认为目前是这样,不一定实际上就是这样)。Leader会发送一个特殊的请求。Followers在收到这个请求的时候,需要将内存中的数据flush到磁盘上面,而且确定数据被持久化之后才能返回给leader这个请求。之后的运行就会处理slow mode状态。而如果leader重新认识到集群中有足够数量之后,可以统一发送一个特殊的请求来将mode切换到fast mode。 leader故障,followers在通过hearbeat的方式认为leader故障的时候,就会将自己内存中的数据flush到磁盘上面。 也就是说对于一个节点,其故障之后,可能以及返回给client的数据已经丢失了。节点故障恢复需要知道其故障之前处于的mode。这个也是在log中记录特殊的一条记录。在处理fast mode下面的第一个请求之前,节点在日志中记录fast-switch-entry,并持久化。这条日志中会记录下<epoch,index>。同样的在切换到slow mode的时候,flush内存中数据的时候也会记录一条latest-on-disk-entry。通过这两种特殊类型的entry就可以知道故障之前节点处理的mode。在回复处理的时候,一个节点需要知道在故障之前其已经写入了多少的日志,如果是处理slow mode下面,这个操作时trivail的,直接从磁盘上就可以获取到。但是在fast mode下面,可能之前写入的日志已经丢失了。最好一条写入的日志称之为last logged entry,LLE。在fast mode故障的情况下,需要从其它节点来恢复这个节点的LLE的数据,还要从其它节点恢复丢失的数据。 恢复 LLE Map用于处理LLE的问题,包含了每个节点在log复制到了哪个epoch那个index下面,记录为⟨S1 :e.10,... Read more!

  • 25 Jan 2020
    LogDevice -- A Distributed Data Store for Logs

    LogDevice: A Distributed Data Store for Logs 0x00 引言 LogDevice是Facebook开发的一个存储日志类似数据的存储系统(不是存储日志数据)。在LogDevice中,一个写入的记录都是顺序写入,会赋予一个唯一的LSN,这个LSN规定了日志记录之间的顺序关系。在读取的时候,LogDevice可以保证不同的客户端读取的时候都以同样的顺序读取到这些数据,而且在发生数据丢失的时候,可以报告某个LSN数据以及丢失了。LogDevice中一个设计特点是non-deterministic decentralized record placement,也就是是说一条记录保存在集群中哪一台机器上不是确定的。这样的设计在对于写入处理是有利的,但是读取的话需要麻烦一些,LogDeice会有对应的机制来处理。在LogDevice Docs中提到LogDevice适合这样的一些应用场景, Write-ahead logging for durability Transaction logging in a distributed database Event logging Stream processing ML training pipelines Replicated state machines Journals of deferred work items 0x01 基本架构 LogDevice的基本架构如下,写入的时候经过类似proxy的一层,这个称之为log sequenceers。log sequenceers的主要功能是对于多个writers写入的记录赋予一个LSN,作为一个log上面不同记录之间的顺序关系。在读取的时候则没有这个log sequenceers一层,readers直接链接storage nodes进行读取。一条日志记录会保存对个副本,保存到storage nodes中指定数量的节点上面,保存一条日志记录的节点集合称之为copyset。数据副本数量记为R,LogDevice中这个值一遍为2 or 3。根据前面的描述,LogDevice有个non-deterministic decentralized... Read more!

  • 24 Jan 2020
    SLOG -- Serializable, Low-latency, Geo-replicated Transactions

    SLOG: Serializable, Low-latency, Geo-replicated Transactions 0x00 基本思路 SLOG这篇Paper可以看作是之前Calvin数据库的优化设计。SLOG设计为一个跨区域复制的且满足strict serializability一致性的数据库。目前支持跨区域复制且满足strict serializability的数据库的代表就是Spanner,但是SLOG的设计与其有很大的差别。跨地域复制网络带来的延迟就会很大,所以跨地域复制的数据要支持低延迟的写操作,常见的操作就是,1. 完全使用异步复制的方式,2. 同步复制只会复制到最近的区域。在要低延迟又要强一执性所以难避开异步复制的情况下,SLOG这里的基本思路使用master-oriented的设计,引入了home的概念。SLOG中如果一个事务只访问了master都在一个region内的数据,一般就是一个数据中心之内,那么这个事务就是一个single home的事务,否则就是一个multi home的事务。 总体架构 在SLOG中,系统有多个Region。每个Region里面保存着整个数据库的多个副本,数据会被切分为多个partition,其中一个region里面的partition会是master。这个master也对应到SLOG中“home”的概念。同一个region中不同的partition的“home”之间是没有任何关系的。在一个region内,有一个基于Paxos实现的local input log,这个local input log中记录的操作只会是修改master在这个region里面的partition。SLOG也会使用批量的方式将这些local input log发送到其它的regions保存多个副本,每个batch会包含了一个sequence number,其它regions里面的副本可以通过这个sequence number来了解到是不是缺失了某些batch。这样的机制下面,一个region里面的最终会包含全部的input log,当然可以因为网络等的原因会有一些延迟。每个region内的SLOG通过deterministic transaction processing来重放input log。SLOG通过使用deterministic transaction processing机制来确保来以相同的顺序处理相同的input log,最终会得到完全一样的内部状态。在这种设计下面,single-home transactions就会是一个region内的操作,相对来说比较简单,而multi-home transactions就会比较复杂。另外在SLOG,事务执行会有两种模式:(a) after the region completes the transaction (SLOG-B) or (b) after the region completes the transaction AND it... Read more!

  • 24 Jan 2020
    BTrim – Hybrid In-Memory Database Architecture

    BTrim – Hybrid In-Memory Database Architecture for Extreme Transaction Processing in VLDBs 0x00 基本架构 这篇Paper描述的是一种传统的基于Page的B+ tree存储加上另外的一个In-Memory Row Store (IMRS)结合而来的存储引擎/数据库的设计。IMRS用于处理数据库运行的热点部分的数据。BTrim的基本结构如下图,Paper中提到Btrim的价格设计很能和现在已经存在的部分结合,这个部分就是Page Store Tables部分。在加上了IMRS之后,相当于在原来的基础之上加上了一个hot rows caches layer,另外原来的Page Store Tables的Buffer Cache也是存在的。Page Store部分的组件,比如disk-based store, page-formatted buffer cache, 和 the redo/undo transaction logging等,不用做什么改动。在IMRS部分中,只会有一部分的数据保存在这里。 这里的IMRS保存的是hot rows就需要一个机制来在IMRS和Page Store Tables中转移数据。Btrim这里引入的ILM– Row-level Data Ageing机制。另外IMRS部分的数据持久化有一个原来Page Store Tables之外的sysimtrslogs实现。IMRS是一个内存中的组件。数据保存到内存中就需要一个机制来高效管理内存,Btrim中了一种best-fit策略 memory allocation。这个内存分配器支持一些固定长度的分配。分配之外就是内存回收,IMRS-GC机制使用了基于MVCC的一些特点。 Btrim一条记录在Page Store... Read more!

  • 20 Jan 2020
    Managing Flash Streams

    FStream: Managing Flash Streams in the File System 0x00 引言 目前的一些SSM中提供了Multi-Stream的功能。Stream可以看作是SSD中一种存储空间管理的形式,主要用于优化SSD的写入放大、GC等的问题。一般在SSD中,写入的单位是Page,擦除的单位是Block,一个Block会有多个Pages。如果一个Block被擦除的时候,里面存在还在被使用的Page,就需要将其转移到其它的地方保存,形成拷贝写入的操作造成了写入放大,也会降低GC的性能。Muli-Stream的基本思路是将有相近生命周期的Page放到一起,这样Block被擦除的时候有更大的可能能够一起就回收了。这样就带来了一个问题就是如何识别出生命周期相近的数据呢。FStream使用的是在文件系统层面修改的方法,将文件系统不同类型的写入当做不同的生命周期来处理。Linux中已经有相关的支持特性。 0x01 基本思路 FStream的基本思路比较简单,就是根据文件系统的特性来进行数据不同的生命周期区分。ext4文件系统基本的disk layout还是来自于Unix FFS,FStream具体的划分和ext4文件系统中对于的部分如下。 Mount-option Stream journal-stream Separate journal writes inode-stream Separate inode writes dir-stream Separate directory blocks misc-stream Separate inode/block bitmap and group descriptor fname-stream Assign distinct stream to file(s) with specific name extn-stream File-extension based stream... Read more!

  • 06 Jan 2020
    Buffer, Dentry and Page Cache in File Systems

    Unioning of the Buffer Cache and Journaling Layers with Non-volatile Memory 0x00 基本思路 这篇Paper的思路是将FS的Buffer Cache和Journaling做到一起。Paper中提到的测试数据表明,现在的日志式文件系统为了实现更好的一执行使用Journaling机制会增大不少的Write Traffic。这里的思路就是如何利用NVM的特性来优化Journaling操作。这里实现的系统称之为UBJ,在UBJ中,buffer cache的存储位置和 journal area分配在同一个存储区域,存储介质使用NVM。在这些设计下面,NVM的一个Block(这里使用Block的管理方式)可能是cache block类型, 或者是log block类型, 还可能是 cache 和 log 共同使用的block。UBJ中,Block存在多种的类型以及状态,基本表示如下图, The frozen/normal state distinguishes whether the block is a (normal) cache block or a (frozen) log block. The dirty/clean state indicates whether the... Read more!

  • 02 Jan 2020
    Temporal DBMS in TDSQL and GC of Hyper

    A Lightweight and Efficient Temporal Database Management System in TDSQL 0x00 Temporal DBMS 这篇Paper挺有意思,其中描述的是一种Temporal/时态数据库系统的设计。Temporal数据库一个核心的一个地方是会保存一个数据记录多个版本。这个多个版本和MVCC中的多版本不是同一个大小,MVCC中的一个记录的多版本主要用于并发控制,逻辑上面一个记录就是一条记录,对数据库用户是透明的。而Temporal数据库中一条记录会保存一条记录随着时间变化形成的版本,对数据库用户是可见的。一个Temporal表的例子,这种常见的一个用途就是记录一个账号余额的变化, ID Player Bal Transaction Time r1.1 James 0 [2018-05-20 06:20:00,2018-10-21 00:30:00) r1.2 James 50 [2018-10-21 00:30:00,2018-11-01 09:01:41) r1.3 James 1000 [2018-11-01 09:01:41,2018-11-12 00:00:10) r1.4 James 2000 [2018-11-12 00:00:10,∞) r2.1 David 150 [2018-10-20 20:10:10,2018-10-20 20:40:00) r2.2 David... Read more!

  • 31 Dec 2019
    IO Stack Optimizations for New Hardware

    OS I/O Path Optimizations for Flash Solid-state Drives 0x00 基本思路 这篇Paper是为性能较好的SSD设计的IO Stack的优化,其基本思路是减少IO操作过程中的Context切换,简化IO Stack的结构,支持多种的IO策略来提高性能。在目前的IO Stack中,基本执行流程如下。在现在的IO Stack中, interrupt service handler routines (ISRs)被拆分为两个部分。目前的设计存在的可能导致一些情况的调度延迟,主要是下图所示的一些可能讲IO thread重新调度到其它的CPU Core的一些问题。 0x01 基本设计 这里设计的IO Stack如下,总体在FS层之下,结构上面比原来的IO Stack要简单很多。基本就是三层。 通过这三层的抽象,这里讲一个IO Path中的操作分为这样的一个过程。主要有两个阶段,一个是Issue Side的操作,另外一个是Completion Side的操作。Issue Silde的基本逻辑就是获取一个可用资源,然后发出请求。在Completion Side可以选择如果获取到结构,一般的选择就是中断 or 轮训的方式,估计还可以是hybrid的方式。根据这样抽象,这里讲IO Path执行分为这样一些测策略, Non-blocking I/O,在这种策略下面,没有代表IO请求的IO Contenxt回block在请求资源上面。在请求到达issue side的时候,会被push到一个fifo的queue里面。在资源可用的情况下吗(tag available),相关的请求从queue里面pop出来,发送到设备进行实际的IO操作。这里实际的IO请求的发出会被推迟到资源可用。从下面的图中看出来,这里和传统的Path相比,主要的优化是从那些工作安排方面。 Lazy I/O Processing,这里的区别是Post Process有H/W IRQ中转移到了IO线程中操作。另外IO线程这里回在发送请求和wakeup的这段时间内设置一个CPU亲和性,从而实现更好的缓存友好性。 Cooperative I/O Processing,这么策略引入了一个cooperative context,用于线程之间的工作协助处理,... Read more!

  • 27 Dec 2019
    Non-Volatile Main Memories File Systems(2)

    Better I/O Through Byte-Addressable, Persistent Memory 0x00 基本思路&设计 这篇Paper在PMEM / NVM上面的文件系统研究算是比较早的,发表在SOSP ‘09上面。这篇Paper主要是提出一种short-circuit shadow paging去解决基于PMEM的文件系统更新的原子性问题。文件系统更新的原子性常见的方法是使用CoW or journaling的方法。两种方式各有优劣。这里的BPFS提出的方法就是根据PMEM的特点,在数据更新可以是原子更新的时候,使用in-place更新的方式,一般这个大小是8 byte。在其它时候根据情况使用append的方式 or CoW的方式。BPFS将文件系统组织为一种树行的结构,这里实际上是一种基数树。如果每个Block的大小设置为4KB,指针大小为8byte,树高为5的时候,可以支持256TB大小的数据。回来的PMFS的结构基本和BPFS这里很类似。更新分为三种情况,如下图所示: in-place write。这种情况在写入的大小不超过8byte。这种情况下就直接执行in-place更新。比如在后面新append一个block的数据,将这个数据更新大元数据的时候。或者是更新一个文件不超过8byte的时候; in-place appends,这种情况利用元数据更新才实际反映了文件大小之类的特点。比如在文件最后一个block append数据的时候,即使append的数据超过了8byte。如果没有超出这个block,这个时候也可以直接append。在append完成之后再去更新file size的元数据信息。如果在append的过程中crash了,由于file size没有更新,append的数据相当于不存在。而file size为8byte大小,可以原子更新。 Partial copy-on-write。更新设计多个Block的时候,需要分配新的空间来处理写入。在写入的时候,向树的上面处理,如果不能原子更新的数据,一只使用CoW的方式。在能够原子更新的时候,就直接使用in-place更新即可。 这篇Paper核心的几个地方就是这里的更新机制,另外提到的关于BPFS的设计没有太多特别的地方[1]。BPFS的缺点在Paper中也有提到,这个提到缺点的比较少见,2333[1]. 0x01 评估 这里的具体信息可以参看[1]. Performance and Protection in the ZoFS User-space NVM File System 0x10 基本思路 NVM的文件系统设计上面,主要有这样的几种实现方式:一种是实现在Kernel中, 优点是容易实现原来的文件系统特性,比如同样的接口语言和一样的权限控制、隔离特性,缺点是不能很好地发挥出NVM的性能。另外的一种思路是实现在user space中,有点是能够更好地发挥NVM的性能,缺点是在权限控制、隔离性上面可能和传统的文件系统不一样。还有一些是Hyhrid的设计,这里的ZoFS也是提出来一种主要在User-Space实现文件系统逻辑,但是也结合Kernel实现的一些思路的方式。ZoFS的出发点是实际的文件系统,一个目录项目的文件、目录有相同的owner和permission。这里根据这个提出来一种新的抽象,称之为coffer。coffer本质上就是一组有相同的owner和permission权限的集合。是整个文件系统的一个部分,而一个coffer是这个文件系统整个文件系统树形结构的一个树形的一个部分。哟个coffer也有一个root节点,如下图所示, 0x11 基本设计... Read more!

  • 23 Dec 2019
    Non-Volatile Main Memories File Systems

    Ziggurat: A tiered File System for Non-Volatile Main Memories and Disks 0x00 基本思路 Ziggurat是在NOVA上面的分层存储的一个文件系统。对于这样的NVMM,SSD,或者还有HDD的设计,其中两个主要的问题就是,一个是决定将元数据、数据保存到哪里,比如将总是将元数据放在访问最快的地方,数据写入的时候也是总写入最快的地方;另外一个是目前保存的位置被认为不可理的时候,怎么将这些数据搬迁到合理的地方。Ziggurat在这些问题的解决方案上面的考虑如下,1. 不总是写入访问速度最快的地方,Ziggurat认为将较小的写入、同步的写入操作写入到NVMM中,而大块的、异步的数据写入可以写入更慢的地方。这里引入了一个synchronicity predictor来分析每个文件的写入行为,并预测未来写入到特点。2. Ziggurat迁移数据的时候,不是以整个文件为单位。而是只会迁移“冷文件”中冷的数据部分。迁移数据的时候,也尽可能地去批量迁移操作,小文件组织到一起顺序写入迁移目的,以获得更高的带宽。Ziggurat会通过应用的读-写操作的模式,动态地决定需要迁移数据的一个阈值。下图表示的一个分三次写入了24个块的例子, 写入操作的时候,Ziggurat通过synchronicity predictor判断这几个写入操作都是比较大,而且是同步的写入,就决定写入到DISK。写入会先缓存到Page Cache中。在fsync操作的时候,这三个块被合并为一个块写入到DISK上面; 之后是一个append的操作,而且认为写入的数据量很小,就将数据写入到NVMM中。之后这个问题被判断为边“冷”了,迁移操作将NVMM中append的数据合并为一个块,写入到了DISK中,NVMM中的数据被删除; 读取操作的时候,需要将数据从DISK读取到内存中,会使用到Page Cache。在应用使用mmap操作的时候,这里会使用reverse migration的机制,将数据迁移到NVMM,方便应用直接访问这些数据。 Ziggurat决定写入操作的模式主要包括了两个部分,1. synchronicity predictor,通过统计两次fsync操作之间的时间间隔,如果低于一个阈值则判断为同步写入,设置了O SYNC flag的时候直接认为为同步写入;2. write size predictor,write size predictor不仅仅是判断写入的大小,而且还要注意开始一些较大的写入之后是不是在之前较大写入大范围内有很多较小的覆盖写入,这些的操作写入到DISK上面会造成碎片化,影响性能。在重写之前的一个写入entry的数据部分的时候,write size predictor会判断是否覆盖了之前写入的一半以上的部分。如果是,则将相关的一个计数器由之前的写入entry转移到新的写入entry,并计数器+1操作,否则将计数器置0。计数器超过4(可调的一个参数)的时候认为是较大的写入。 0x01 数据迁移 从之前的一些相关的系统来看,数据迁移时很难弄的,最容易出现的时使得系统出现抖动。Ziggurat使用basic migration来将在读为主的workload中将数据从DISK中迁移到NVMM中,使用group migration来将NVMM中的数据合并数据转写到DISK中,实现更少的碎片。Ziggurat会维护每个CPU核心,每个存储层一个的cold list来确定一个文件的“温度”。这些lists通过average modification time(amtime)来排序,在更新文件的时候更新这些lists。为了知道一个文件中哪一个block最冷,这里会为一个文件的每个block维护一个mtime(这样估计会引入更多的元数据)。在迁移数据的时候,ziggurat从list中获去到最冷的数据,如果mtime较“旧”,超过了一个阈值,则将整个文件视为冷的。另外迁移操作的时候,ziggurat会考虑到文件不同块的冷热程度,可以将热的块继续保存到NVMM中。Ziggurat决定什么时候进行数据迁移由NVMM利用率的阈值决定,但是这个阈值会有workload的read-write ratio来动态调整,不是固定的。 Basic Migration,Basic Migration的操作基本分为在DISK上分配空间、然后拷贝数据,之后在inode-log添加一条记录标记了这些迁移写入的信息。之后更新NVMM中的log tail和DRAM中的radix tree,之后NVMM中的空间就可以释放了。由于Ziggurat从NOVA文件系统改进而来,这个的一些结构对应到NOVA文件系统的对应结构。这些操作中也有不少的细节优化,比如锁的粒度,顺便预热... Read more!

  • 16 Dec 2019
    Many Faces of Hash Table

    Split-Ordered Lists: Lock-Free Extensible Hash Tables 0x00 基本结构 Split-ordered是一种Extensible Hash Table。这种hash table包含两个主要的结构,一个是一个linked list,保存数据项,另外一个类似于一个索引结构,保存的是一个逻辑上面的bucket。初始化的时候,一般选择初始化长度为2,后面每次size超过size x L的时候,就进行扩容的操作。这个L就是hash table的load factor。初始的时候,每个bucket是一个uninitialized状态,而index 0初始的时候指向的是一个empty list。一般的hash table rehash操作的时候,需要对数据进行移动 or 逻辑上面的移动。但是这里可以避免数据的移动。在table的size为2^i的时候,一个bucket b包含所有的keys其 k mod 2^i = b的key。在size变为2^(i+1)的时候,这个bucket被分裂为2个bucket,对于k mod 2^(i+1) = b + 2^i的keys,被转移到第b + 2^i个bucket。为了避免一个bucket分裂的时候需要对数据进行重新整理的操作,最好就是一个bucket的分裂点处于这个bucket数据项的中间的一个值,前面的是还是在bucket b,后面的分裂之后成为b + 2^i的bucket的数据。所以这里最好就是在推进的时候就根据其hash进行一定的顺序整理。另外,为了处理删除由bucket指向的item的问题,这里引入了dummy node的方式, ... it is nontrivial to manage deletion of nodes... Read more!

  • 13 Dec 2019
    Ursa -- Hybrid Block Storage for Cloud-Scale Virtual Disks

    Ursa: Hybrid Block Storage for Cloud-Scale Virtual Disks 0x00 基本设计 这篇Paper很有意思,而且Paper中说的也比较完整。Paper中提到的Workload的基本特点是随机读取很多,局部性比较差,请求的大小一般不会很大。Ursa的基本思路是实现一个SSD-HDD混合的块存储,实现更低成本的同时还可以实现SSD一般的性能。其基本的架构如下。基本架构和很多的分布式存储系统一致,应用通过客户端和Ura的其它部分交互,存储一个中心话的Master节点来提供virtual disk/虚拟磁盘创建、打开、删除以及元数据保存、保存等的功能,还要负责集群的状态监控,处理故障恢复等。Chunk Server负责保存实际的数据,数据使用多副本保存。Ursa通过将主副本保存在SSD上面,其它的副本保存到HDD副本来实现SSD-HDD的混合存储。为了实现和SSD一样的性能,Ursa的基本思路是日志式写入,然后后台replay的策略。对于HDD,journal也会写入到SSD上面,然后repay到HDD上面。 对于读取请求,Ursa都是倾向于使用SSD。对于写入请求,主副本写入到SSD,然后复制到备节点上面,在给客户端返回成功。对于副本来说,由于HDD和SSD时间很大的性能差距,特别是随机的性能。这里就使用日志式的写入方式,写入到一个SSD的journal盘上面,在异步地repay到HDD上面。用于journal的SSD和backup的HDD在同一个机器上面,当一个SSD的journal空间被使用完之后,会转移写入到另外一个负载较低的。如果都满了则写入到HDD。HDD上面写入的journal只会在HDD空闲的时候进行replay。在HDD上面写入journal式类似于一个兜底的操作,实际上Paper中提高在线上两年的部署中都没有使用到过。 对于大块的写入操作,这样的思路也许不是最佳的选择,因为HDD的顺序性能也还可以。这种先写journal然后在repay到HDD上面的操作会造成额外的写入,小的写入操作更加合适。Ursa的思路是设置一个阈值(Tj == 64 KB),超过了这个阈值大小的写入会被直接写入到HDD。这样的可能导致的一个问题是journal上面的数据可能是过期的,处理的时候要注意。 另外一个的思路是优化很小的写入,小于一个阈值的写入称之为tiny writes(Tc == 8 KB)。对于这样的写入,Ursa的思路是直接同时发送到主副本和备副本。这样在复制和一致性处理上面,都要有对应的策略,在论文的后面部分有讲到。 Journal Index是Ursa用来处理journal和chunk之间的映射关系,即某个chunk的某个范围内的数据在journal上面作为journal保存。这个Index的Key是{offset,length},value为journal offset,用于查询一个访问内的数据在不在journal中。Ursa进行了一些优化,主要是为了提高访问查询和范围添加的性能:1. ({offset, length} → j_offset)只使用了8bytes,2. 使用一个两层的设计,第一层为红黑树,第二层为一个排序的数组,第一层添加性能更好,第二层查询性能更好。添加的时候先插入到红黑树中,然后异步合并到排序好的数组中。 为了提高性能,Ursa利用了多个层面的并行性,1. Disk内的并发性,SSD并发操作的性能远好于HDD。SSD内部的结构也决定了其可以进行并发的操作。所以Ursa在SSD上面运行多个chunk server。每个chunk server使用一个aio的线程来并发发送IO请求,而对于HDD就是使用单线程的非aio的操作。2. Inter-Disk的并发性,主要的思路是条带化,乱序执行以及乱序完成。Ursa中将一个虚拟的磁盘划分为固定的chunk,条带化将连续的chunk写入到不同的地方。3. 网络层面的并行,流水线处理请求。 0x01 一致性和复制 Ursa提供per-chunk linearizability的一致性保证。其复制协议也是基于 Replicated State Machine (RSM)。每个chunk会维护一个version,在每次写入操作的时候更新。另外chunk servers 和 master节点会维护一个persistent view number,新添加一个chunk... Read more!

  • 05 Dec 2019
    Blizzard and Isotope, Block Storage Systems

    Blizzard: Fast, Cloud-scale Block Storage for Cloud-oblivious Applications 0x00 基本设计 Blizzard是微软开发的一个块存储的系统,Blizzard对外表现就是一个SATA磁盘。Blizzard构建在Flat Datacenter Storage (FDS)上面。由FDS来实现基本的数据存储和副本机制等,这样Blizzard就会简单很多。FDS是一个Blob的存储系统,Blizzard也就构建在FDS的Blob的抽象之上。Blizzard在Paper中提到的第一个设计选择就是条带化,就是将一个虚拟磁盘中一个IO操作分散到多个tractsB上面(Blob的一个组成带为,一般大小为8MB)。这种将方式是很常见的,Paper中这里讲了许多这么做的好处,简单直观的好处就是跟大的带宽,类似于一个软件RAID,另外就是更好的延迟表现,形成热点的概率更低等。一个打散的Tract的集合在Blizzard中称之为一个Segment,基本示意如下图,这里打散的tracts的数量为2。这个数量是可以配置的,Paper中举例使用128的时候,可以提高的带宽超过了1000MB/s。 Blizzard提供了多种的写入语义,这里的语义主要和数据的持久化特性和写入操作的执行顺序相关。 Write-through,是最简单的一种,可以提供在crash时候最小的数据丢失。这种模式下面Blizzard只有在讲数据写入到FDS中,确认数据持久化之后才会发挥给Client ACK写入完成。很显然缺点就是性能会比较低; Flush epoch commits with fast acks,这种模式下面,用户的操作会被划分为一个个的flush epoch(以flush操作来划分)。当一个段时间内所有的请求都发送到FDS请求写入时,标志着这个flush epoch被issued,当所有的写入请求的数据都持久化时,标志这个flush epoch已经retired。为了实现这样的逻辑,Blizzard维护一个从0开始递增的epochToIssue计数器,另外还有一个从0开始计数计数器currEpoch。前者记录那些请求已经被发送到FDS进行写入操作,而后者表示客户端已经进行的flush请求的次数。一般情况下currEpoch都大于epochToIssue。写入 or flush操作的时候,Blizzard都会例子返回给客户端成功,然后将请求排队。向FDS请求写入的时候,队列中为epochToIssue的请求会被发送。在一个epoch中的请求都完成的时候,递增这个epochToIssue,然后处理新epoch的请求。这样的时候,flush操作维护的并不是一种持久化的语义,而是一种顺序的语义你,前一个flush的操作必须早后一个的前面完成。 Out-of-order commits with fast acks,在这种模式下面操作可以时乱序完成的。在这样情况下面为了实现prefix consistency语义,使用了两种机制,第一种就是使用log structure的方式来避免就地更新。以便于在故障发生的时候可以恢复在一个consistent version。另外的一个机制是使用一个确定性的permutation/顺序来决定哪一个log entry,即哪一个 <tract,offset>会接收到写入请求。这样的话在crash之后恢复到一个一致性状态的过程中,这个permutation加上checkpoint就可以起到作用。 0x01 一致性和容错 第三个语义Paper中花来比较长的时间来说明,这里详细一些地总结一下。假设Blizzard中的一个虚拟磁盘有V个Block,每个Block的大小是相等的,具体的大小可以根据业务来调整。这些Block对应到FDS中的P个physical block来保存(P > V)。Blizzard使用log structure的方式来管理这些physical blocks,另外使用一个blockMap来保存physical block到virtual block的映射关系,另外维护一个allocationBitMap来表示那些physical blocks这在被使用。在读取的时候,就需要根据blockMap中保存的映射关系来找到实际保存数据的physical block。处理写入的时候会复杂不少,原理如下,... Read more!

  • 28 Nov 2019
    EROFS, WAFL and XFS

    EROFS: A Compression-friendly Readonly File System for Resource-scarce Devices 0x00 基本思路 这篇Paper中描述的EROFS在很多相关产品上面已经得到了应用,宣传上面也挺有意思的。这篇Papper中描述的主要是EROFS的两个内容,1. 固定压缩后大小输出的压缩方式,2. 以及在资源受限的设备中(EROFS主要面向的是智能手机,不过感觉现在的智能手机也称不上资源受限了吧(。・ω・。)ノ),如何使用更少的资源,比如内存,来进行解压缩的操作。 固定压缩之后大小输出的策略。之前类似的系统采用的策略是固定大小的输出,这样导致的问题是压缩大小是不确定的,另外的一个问题是读取的时候读放大比较严重,而且会消耗的内存比较多。ERFOS使用滑动窗口的方式来压缩原始的数据,每次压缩一个chunk,chunk的大小不固定,但是压缩之后的大小得是固定的。这里要处理的一个问题就是找打这个chunk的大小,知道其压缩之后的大小为4K的大小。 压缩之后保存数据之后的文件系统要处理的另外一个问题就是在读取的时候的解压缩策略。EROFS使用了两种策略,cached I/O 和 in-place I/O,前者会将数据先解压缩到inode对应到的一个Page Cache中,在读取的时候直接将请求导向这个Cache的数据即可。而后者的策略是利用了读取请求带有的Buffer,在读取的时候,VFS会先分配一些内存Pages来作为Buffer,EROFS这里就直接利用这些Buffer来保存解压缩之后的数据,避免额外的内存分配。 EROFS在解压缩的处理上面也使用了不少优化策略,下图是EROFS,(a)中原始的数据被压缩为两个压缩块,D5在压缩的过程中被拆分。如果是为了读取D3 和 D4。这个操作的步骤如下,1. 读取C0,这里只要解压缩这个C0就可以了,2. EROFS会分配三个连续的Pages来保存D0-D2,而D3和D4会直接利用请求使用的Page Cache,3. 压缩算法要求连续的内存,这里就使用vmap将两段内存映射一段连续的内存,4. 这里在处理的时候,要拷贝C0一次,避免C0在这个过程中被修改,另外C0也是使用Page Cache的Page来保存的,5. 解压缩操作完成之后,就可以vunmap,D0-D2的数据也可以释放。这样的基本策略有两个问题,一个是仍然需要分配物理Pages,另外一个就是使用vmap机制并不十分高效,EROFS有使用了另外的一些优化策略, Per-CPU buffers,在解压缩后的数据不大于4个Page的时候,会将这些数据解压缩到per-CPU buffers中,然后在拷贝到Page Cache中,如下图中的(c)所示。通过重复利用这个per-CPU buffers来减少内存分配的动作; Rolling decompression,这里的基本思路分配一个64KB/16Pages的大小。一些情况下吗在解压缩了64KB之后,可以重新利用这段内存,即一种循环利用的方式, EROFS uses LZ4 as the compression algorithm, which needs to look backward... Read more!

  • 22 Nov 2019
    Ubiq, Trill and Drizzle

    Ubiq: A Scalable and Fault-tolerant Log Processing Infrastructure 0x00 基本架构 Ubiq是Google实现的一个Log Processing系统,这里的Log是一个应用被使用过程中产生的一系列的事件。这里也将这样连续产生的事件数据也称之为data stream。之前Google有过一个类似的Photon系统,Ubiq这篇Paper还特意比较了和Photon之间的不同。Ubiq的基本架构如下,Ubiq假设事务输入先被写入到一些文件中,这里保存事件的文件创建逻辑、写入逻辑等不在Ubiq的范围之类,Ubiq使用一个Log Data Tracker组件来监控这些文件上面的操作,在有新的创建 or 数据写入的时候可以开启处理数据的逻辑。 ​ 在Log Data Tracker探测到新数据到达的时候,相关的元数据filename 和 目前的offset等被作为元数据写入到State Server保存。State Server是一个基于Paxos的存储系统。持续进来的数据会被Work Unit Cretor打包为一系列的event bundles来处理,这个就是一个批量事件的抽象。之后这里event bundles被Work Unit Retriever拉取,进入业务处理逻辑,在这里数据被特定的业务逻辑处理,输入log数据,输出结果。在业务逻辑处理完成之后通过Work Unit Committer来提交处理的结果。Ubi实现的是exactly-once的语言,使用要在数据输入、业务逻辑结果输出等的地方都有重试和去重的逻辑。所以相关的业务结果如果不是确定性的话需要Work Unit Committer进行提交的操作,有Dispatcher使用两阶段提交的方式完成结果的写入。而如果业务逻辑处理的结果是确定性的,Local Application Processing可以直接将结果写入到Output Storage。 0x01 单数据中心和多数据中心 对于输入文件,Ubiq期望其不同的副本可以达到一个最终一致的状态,byte级别的一致。输入文件有多个副本的情况下,任意时刻这些文件可能是不同,如果两个副本S1、S2其中,S1 size < S2 size,前面S1 size的数据得是相同的。能实现这种保证是很有意思的,不过这篇Paper中没有提到。Ubiq处理的数据起始于输入文件,而Ubiq大部分的组件都是stateless,而存储数据的核心就是State Server,在这其中保存的一般是数据处理过程中的元数据。比如输入数据的哪些已经处理完成了,哪些还没有处理,很多的机制和exactly-once语义相关。对于一个输入文件和其一个offset,可能处理三种状态;1. 还没有作为一个work unit开始处理,2. 已经开始处理,3.... Read more!

  • 18 Nov 2019
    Machine Learning Systems

    Scaling Distributed Machine Learning with the Parameter Server 0x00 基本思路 Parameter Server(PS)是在很多的机器学习框架中会使用到的工具,这篇Paper发表在14年,在前面的出现过的类似Parameter Server服务上面的继续改进。机器学习的各种问题可以抽象为最小化一个损失函数,这里是称之为Risk Minimization。可以表示为, \(F(w) = \sum_{i=1}^n l(x_i, y_i,w) + \Omega(w).\\\) 处理这个常用的就是一些类似梯度下降之类的数值优化算法,Paper中这里就是将其拓展到分布式的情况下,称之为Distributed Subgradient Descent ,以便能够处理一台机器无法处理的参数的数量。基本的逻辑如下,其基本的逻辑就是将数据分发到多个worker上面,每个work分别计算各自数据部分的梯度。Worker在Load数据就是一个迭代的过程,每次计算处理此事的梯度,如何将其push到Server上面,然后在从Servers上面Pull下来更新之后的参数。对于PS中的Server角色,它要副本保存这个参数数据,并汇总Worker的更新,然后分发给Worker。 0x01 基本架构 PS的基本架构如下图,一个常见的分布式系统的设计。两个核心的角色Worker负责计算任务,一组的Servers负责保存参数的数据。PS同时可以运行多个机器学习的任务。一组的Servers使用一致性Hash来将参数数据进行分区,每个Server保存所有参数的一部分。一致性Hash使得在机器发生故障的时候可以减少数据的移动,这个也是PS容错机制的一部分。PS中参数都使用Key-Value对的形式来表示,这个和类似的一些系统是相同的。在基本的Key-Value抽象的基础之上,PS还提出了一些拓展的功能。PS将参数视为 sparse linear algebra objects,可以在其之上实现训练时常用的一些操作,比如计算向量加分w+u,乘法,计算2-范数以及其它的更加复杂的操作。 在上面的分布式梯度下降的基本逻辑中,存在Worker和Sevrer之间的数据Push和Pull操作。这种操作下面,批量地处理数据时一个很常见的优化,PS这里将这种优化称之为Range Push、Range Pull。Server节点处理可以执行汇聚Work节点的数据操作之外,用户还可以定义执行的逻辑,user-defined functions,以便用户在其之上实现更加灵活的逻辑。除了user-defined functions,PS中另外一个类似的东西时User-defined Filters,用于控制Worker和Server之间的数据同步。比如在一些情况下,Worker中计算出的结果可以知将会对参数有影响的部分推送到Sevrer,避免一些不必要的数据传输。 这种分布式的情况下, Worker和Server之间会有大量的数据交互。如何优化这个操作会对系统的性能有比较大的影响,这里PS提出的方法是异步迭代的方式。Worker在将上一步的结果Push、Pull操作的过程中,就开始计算下一步的梯度计算。这样的优点是将Push、Pull数据传输的过程和梯度计算的过程重叠,提高了性能,缺点就是参数会存在不一致。PS这里还可以定义execute-after-finished依赖逻辑,以便让一个任务的执行只有在其依赖的任务都完成之后才开始执行。 异步迭代带来的性能的提升,也带来了一致性的问题,PS这里提出了一些灵活的一执行的处理方式。一些算法对于在上次迭代的结果没有更新而使用旧的参数的时候,可能并没有很大的影响,这样就可以使用最终一致的模型,不同的任务可能同时开始,遇到的不一致的问题可能最严重,适用于一致性不敏感的算法。相反的是顺序一致性的模型,最终模式下面任务为顺序执行,性能差一些,不会有不一致的问题。两种算法之间的Bounded Delay模型,一个任务阻塞到其前t个迭代的任务完成。 0x02 评估 这里的具体信息可以参看[1]. MXNet: A Flexible and Efficient... Read more!

  • 11 Nov 2019
    Computation via Dataflow Graph

    Naiad: A Timely Dataflow System 0x00 Timely Dataflow Naiad这篇Paper是SOSP ‘13的一篇best paper,和很多微软发表的论文一样,看上去做了个很厉害的东西,但是没有啥关注。这里提出的主要是一种称之为Timely Dataflow的模型,一种基于常见的有向图执行的抽象。另外的的一些特点是Timely Dataflow中定点是有状态的,接受和发送的消息会带有逻辑时间戳,而且图中可以包含环,甚至还可以嵌套。Timely Dataflow中的时间戳表示了不同的输入epoch和迭代的周期,顶点还可以在一个特定时间戳标记的数据都处理完成之后受到通知。Timely Dataflow中的一些基本概念, 图的基本组成是顶点和顶点之间的联系。Timely Dataflow中输入顶点指的是从外界输入数据的顶点。输入数据会标记上epoch的消息,并且会要通知顶点某个epoch的数据输入完毕。输出顶点指的是输出数据到外部消费者的顶点,这些输出数据也会带有epoch的消息,也可以通知外部的消费者一个epoch的数据输出完毕。在一些情况下,比如所有epoch数据输入、输出完毕之后可以close顶点。 另外,Timely Dataflow是支持带循环的图的,这样更好地支持迭代计算。Timely Dataflow这里引入了loop contexts的概念,指的是Timely Dataflow的有向图中的循环相关的结构,循环还可以嵌套。进入loop contexts的通过ingress vertex,而输出得经过egress vertex,另外图中的环的至少包括一个不在内部嵌套循环loop context(s)的feed-back vertex。 Timely Dataflow中的时间戳是逻辑上的,它实际上包含了两个字段。第一个字段e表示epoch,而第二个字段c=<c1,…ck>是一个向量,表示了k的嵌套的loop contexts各自循环计数。在处理的时候,不同类似的顶点输入时间戳和输出时间戳的对应的逻辑如下,分别是append元素到c、删除c最后一个元素以及对应c的元素加1的逻辑, Vertex Input timestamp Output timestamp Ingress (e,⟨c1,...,ck⟩) (e,⟨c1,...,ck,0⟩) Egress (e,⟨c1,...,ck,ck+1⟩) (e,⟨c1,...,ck⟩) Feedback (e,⟨c1,...,ck⟩) (e,⟨c1,...,ck+1⟩) 而时间戳的大小比较逻辑是先比较e,再比较c。 对于顶点上面的计算。每个顶点会实现这样的两个callbacks,分别用于接收消息和用于通知这个顶点一个时间戳标记的消息已经处理完毕,不会再有。 v.OnRrev(e : Edge, m... Read more!

  • 08 Nov 2019
    Bookkeeper and Distributed Log

    Durability with BookKeeper 0x00 基本架构 BookKeeper就是一个分布式的journal,多使用顺序写顺序读的方式操作。BookKeeper中几个基本的概念,1. Bookie,即BookKeeper中的的一个存储服务器,在其上保存了ledger fragments;而Ledger 是一个log文件的抽象,保存了一个entry的序列。这里的entry的是BookKeeper的一个基本的数据单元,使用一个sequence id来标识。客户端则是作为应用和Bookie交互的中间角色。BookKeeper中一个Ledger在同一时刻是允许一个客户端写入,可以允许多个客户端读取。而且BookKeeper保证一旦一个Ledger被关闭,所有的客户端读取的entries的顺序都是一致的。在数据的存储上,这里有特点的一个地方是使用两个分离的设备分别保存Bookkeeper的Journal和Ledger,前者为同步写入,没有索引,而后者为异步写入,并添加了索引。 Bookkeeper提供的一些基本操作如下, • Create a ledger; • Add entries to a ledger; • Open a ledger for reading; • Read entries from a ledger; • Close a ledger to prevent further writes; • Delete a ledger. Create a ledger;Bookkeeper可以容忍在一个f+1副本中,f个副本失效。应用测试创建一个ledger的时候,客户端负责那些可用的Bookie来保存这个ledger。这些信息被当作ledger元数据的一部分被保存下来。元数据被保存在Zookeeper中; Add entries... Read more!

  • 04 Nov 2019
    Many Faces of Hash Function

    Many faces of Hash Function 总结一波各种各样的Hash Function。 0x01 Rolling Hash Rolling Hash是一个很有意思算法,其解决的问题是在知道了字符串hash知乎,快速地计算出其一些字串的hash值,可以避免重新计算这些字串的hash值。在一个常见的字符串匹配算法Rabin-Karp算法中就用到了一种Rolling Hash。这里的基本思路很简单,用三个式子就可以表示清楚。(1)表示一个字符串从0到i的字串的hash值的计算方式,(2)表示0到j的字串,假设j > i。(3)就表示i到j的字串的hash值的计算方式, \((1). hash[0:i] = s[0]*a^{i-1} + s[1]*a^{i-2} + \cdots + s[i-1]*a^{i-1}. \\ (2). hash[0:j] = s[0]*a^{j-1} + s[1]*a^{j-2} + \cdots + s[j-1]*a^{j-1}. \\ (3). hash[i:j] = hash[0:j]- hash[0:j]*a^{j-i}.\) 这样可以用一个数组记录0到i的hash值,就可以快速计算出其中任意字串的hash值了。这样如果是用于计算一个字符串上面一个固定窗口大小的字串的hash值,可以用如下的思路。w为窗口大小。 \(hash[k-w:k] = (\cdots)\mod m. 已经计算出。\\ hash[k-w+1:k+1]= [(hash[k-w:k]... Read more!

  • 31 Oct 2019
    Multi-GPU Communication in Training

    Horovod: fast and easy distributed deep learning in TensorFlow 0x00 基本思路 与其说这里的是deep learning中的内容,不如说这里解决的还是分布式计算中的一些问题。之前在天河一号上面跑过的MPI中的程序就有类似的内容。Horovod这篇Paper的内容比较简单,主要就是如何将ring-allreduce应用到TensorFlow中,用于分布式的深度学习训练。Ring-allreduce是百度的一片文章讲述了如何应用到深度学习的训练上去的,不够现在这篇文章的URL打不开了,在网上可以找到其它的描述[1]。在分布式的训练中,每个计算单元只会计算全部计算任务中的一部分,这样就只能得到一部分的结果。需要一种机制来将其它计算单元的计算结果来同步到本机上面,常见的一种方式是Parameter Server的方式,如下图所示。使用中心的一个 or 一组服务器来处理这个合并计算结果并将合并之后的结果分发到各个worker上的任务。这样的一个问题就是,随着系统中节点数据的增长通信成本会增长很快,下图右边就比左边的情况复杂了很多。 这里使用的一种方法就是Ring-allreduce,基本的思路如下图所示。节点组成逻辑上面的一个环,每个节点从其上一个收到数据,并向下一个节点发送数据。这样每个节点只和自己相邻的节点产生交互。工作的时候,每个节点上面的数据被划分为相等数量的chunk,在前面的几步的操作中,每个节点对应位置的chunk按照环的发送“流动”,这样在运行了N-1次之后(N为节点的数量),一个chunk由A流动到了B,在这个过程中,即每次向后流动的时候,会合并这个节点上面对应chunk的节点。当流动到B时,B对应的chunk就合并了所以节点的对应chunk的结果,而前面的节点对应的chunk分配缺失了一步。到这里的操作称之为scatter-reduce。 下一个阶段的操作称之为all-gather,目的是将节点没有缺失的部分补齐。基本的操作和前一步骤操作是一样的,不够由于这个时候已经保存了的数据和传输过来的时候可能会有重复的部分,这里需要处理一下。当操作N-1次之后,所有节点都可以获得全部的数据更新。另外[1]中有很详细的解释。 0x01 评估 这里的具体信息可以参考[2]. Blink: Fast and Generic Collectives for Distributed ML 0x10 基本思路 这篇Paper也是解决分布式训练中的通信的问题。前面的Ring-Allreduce没有考虑,在现实中,不同的线路是不一样的。也就是存储异构的情况,比如PCIe和NVLink,它们之间的传输特性相差比较大。这里则考虑优化这样的情况。Blink这篇先从广播的情况出发,即一个节点的数据发送到其它节点(这里表示一个GPU)。广播情况, Blink将目前系统中的节点和连接情况抽象为一个图,问题就转化了图论中的一个directed spanning trees的问题,即有向生成树的问题的一种变体。Blink要做的就是一个图G和一组的spanning trees中,找到通过使得传输速度能最大的一个,同时这样会带有每个边的capacity的限制,即传输连接速度的限制, ... finding the maximal packing of a number of directed spanning trees or arborescences... Read more!

  • 29 Oct 2019
    Net Work Session of SOSP-2019

    Snap: a Microkernel Approach to Host Networking 0x00 引言 Snap是Google开发的一个用户空间的Networking System。一般的使用网络的应用都是直接使用内核提供的网络栈。但是近年,由于直接使用内核网络栈的一些缺点,比如性能优化、开发新功能都比较麻烦、困难,出现了不少将网络栈从内核中移入用户空间实现的。Snap也是类似的这样一个系统,但是Snap被Google部署在生成环境中多年,其可行性肯定是更好的。和直接使用内核的网络栈相比,Snap能过实现更高的性能,而且提供RDMA的支持, Our evaluation demonstrates over 3x Gbps/core improvement compared to a kernel networking stack for RPC workloads, software-based RDMA-like performance of up to 5M IOPS/-core, and transparent upgrades that are largely imperceptible to user applications. 0x01 基本架构 Snap被实现为Linux的一个用户进程,并利用了微内核的一些思想。Snap这里更像是一个网络服务,和其它的用户空间网络栈相比,能过中心化地管理网络资源(其它的很多用户空间网络栈都是作为一个lib,和应用进程运行在一起,这样不同应用进程的网络栈是分开的)。另外Snap由实现避免在内核中开发的麻烦,以及由此带来的性能提升。操作系统授予Snap进程独占访问一些网络资源的权限,但是Snap进程并不运行在特权态。Snap进程和应用进程的通信通过共享内存 or Unix... Read more!

  • 25 Oct 2019
    KVell, Splinter and HyperDex, Key-Value Stores

    KVell: the Design and Implementation of a Fast Persistent Key-Value Store 0x00 引言 这篇Paper中在具体系统的实现上,感觉没有提出什么有新意的东西。Paper的核心内容其实就是一种观点,目前CPU性能的增长主要体现在核心数量的增长上,单核性能增产缓慢。现在的NVMe SSD以及NVM的发展,使得一些存储系统的瓶颈由硬盘转向CPU。这里的KVell主要是针对瓶颈为CPU的环境的一种KV Store的设计。 0x01 基本思路 针对CPU为瓶颈,而存储够用的环境下,KVell的主要的一些设计选择, Share Nothing,主要就是内存中的一些数据结构为每个线程独立一份。比如内存的B-tree索引、IO队列、保存磁盘Free Blocks的List以及Page Cache等; Do not sort on disk, but keep indexes in memory,数据直接按照写入的顺序写入磁盘,不对数据进行排序操作。索引都保存在内存中。这个实际上很常见,没什么特别的; Aim for fewer syscalls, not for sequential I/O,前调为了更少的系统调用,而不是为了实现顺序IO。主要就是batch请求; No commit log ,不使用Commit Log; 接口方面,KVell和一般的有序的KV Store提供的结构基本相同。磁盘上面的空间被划分为4KB大小的块,数据项按照4KB的单位被划分为slab,这个和现在很多内存分配器的设计思路一致。这里的划分的粒度更大一些。不同尺寸的数据项被保存在不同的文件中。这里用很多管理内存的思路来管理磁盘空间。磁盘空闲的空间在内存中维护。另外的在内存的主要结构就是索引,还有就是Page Cache,都没有特别的地方。IO方面主要使用了Linux AIO。这里主要就是Client和Worker通过队列来提交请求,设置callback。根据不同的请求以及Page... Read more!

  • 21 Oct 2019
    Data and Metadata Integrity in File Systems(2)

    ffsck: The Fast File System Checker 0x00 引言 ffsck是一个很有意思的File System Checker实现,通过比较小的改动就实现了非常好的性能提升。像ext2这样的非日志式的文件系统,难免在系统长时间运行之后由于某些异常情况产生数据/元数据不一致的情况,fsck用于发现系统中的这样的一些问题。日志式的文件系统一般情况下fsck的检查会简单一些,但是强制全部检查的话还是会耗费比较长的时间。以e2fsck为例子,e2fsck的检查过程分为这样的几个步骤, Superblock,超级快检查。一般检查的是文件系统大小,inode数量,空闲block以及空闲inode数量等。一般前面两个数值的检查能以确认其是否精确,只会大概判断是不是在一个正常的区间; Group Descriptor,Group Descriptor检查。Group Descriptor的设计来自于80年代的Unix Fast File System的设计,将磁盘磁道划分为不同的,每组里面包含bitmap之类的信息和数据block。这里会检查空闲的block是不是实际上被使用了,没有被标记为空闲的实际上没有被使用; Directory,检查一些这里保存inode是否是正常使用状态的,以及inode number的范围是不是在一个合理的范围; Inode,检查inode的类似和分配状态是否是一个正确的状态,以及其引用数是否正确。另外检查inode中指向的数据块号是否合法以及没有被其它的inode引用; Indirect Block,Indirect Block是inode用来寻址Data Block的block,fsck同样会检查在Indirect Block保存的block有没有被其它的inode引用,并inode number是合法的。 ffsck先是做了一个性能分析,发现fsck的大部分时间都花在了扫描inode和其对应的Indirect Block上面,而且在文件大小增大的情况下这个现象会变得更加明显。ffsck分析认为,ext2、3中Indirect Block和Data Block使用同样的分配策略,分配也都分配在同样的地方。这样的一个设计缺点是可能导致Indirect Block发布在磁盘的分散的地方,在文件系统“老化”的情况下这个会变得更严重。另外一个原因是ext3文件系统中,Indirect Block组成的是一个类似树形的结构,这样访问更低层的Block需要顺序访问树更高层的Block,在前一个原因下面,会造成比较差的数据局部性, 1. First, ext3 uses the same allocation strategies for data blocks and indirect blocks, storing them... Read more!

  • 14 Oct 2019
    Some Optimizations of Linux Network Stack

    Some Optimizations of Linux Network Stack 0x00 SO_REUSEPORT SO_REUSEPORT是Linux网络栈中一个很有效果,有应用得很广泛的一个应用,而且能够达成的效果非常好。SO_REUSEPORT基本的思路是改变在一个端口只能被一个端口监听(TCP)/recvfrom(UDP)的情况,提高性能。之前有个不少的研究就是为了改进Linux网络栈的Accept等的性能。mTCP是一个用户态TCP协议栈的实现,在Linux使用了SO_REUSEPORT之后,两者的性能差距明显缩小。Linux中相关的代码一部分如下,基本的思路是在使用了SO_REUSEPORT的选择之后,原来端口对应到的Socket会添加一个sk_reuseport_cb的字段,这个字段中保存一个socket的array,在处理通信的时候,根据源地址端口和目的地址端口计算 or 使用出一个hash值,来决定这个array那一个socket来实际处理。这个除了使用hash之外,还可以自己使用bpf来控制(通过这个功能想到一个有意思的玩法,有时间试试看), // /linux/net/core/sock_reuseport.c 253 /** 254 * reuseport_select_sock - Select a socket from an SO_REUSEPORT group. 255 * @sk: First socket in the group. 256 * @hash: When no BPF filter is available, use this hash to select. 257 *... Read more!

  • 11 Oct 2019
    F1 Query -- Declarative Querying at Scale

    F1 Query: Declarative Querying at Scale 0x00 引言 F1 Query是Google开发的F1的后续系统,可能是因为Spanner发展挤占了之前F1负责的工作。F1 Query就得想办法就拓展F1的功能。不过F1 Query和F1实际的差别还是非常大的,可以是不同的两个系统。F1 Query在这篇Paper中描述的是非常nubility的一个系统,既可以支持OLTP,又可以是指OLAP,还可以执行一些ETL之类的工作。另外在数据源方面,可以支持各种类型的存储系统,比如Bigtable, Spanner, Google Spreadsheets 等等。对不同workload类型,以及众多种类异构数据源的支持,所以Paper中说F1 Query可以支持所有数据处理的要求! 0x01 基本架构 F1 Query的基本架构如下图所示,F1 Query有点类似于给众多数据源提供统一SQL的前端。用户通过Client和F1 Server进行交互。F1 Master作为一个中性化的节点,负责处理监控查询的运行以及管理其它的组件。F1 Server负责处理事务和查询处理。对于较小的查询,直接就可以在F1 Sevrer中处理,对于较大的查询,会讲查询请求发送到多台的F1 Worker中进行处理,然后在F1 Sevrer中进行汇总。Server和Worker都是无状态的,方便容错和拓展。另外的几个组件事F1 Catalog Service,这个就是保存了下面的异构数据源的一些元数据,Batch Meta则似乎查询计划的一些信息,另外的UDF Server负责处理user defined scalar functions (UDFs)的一些工作。基本浴血工作流程, 客户端的请求会被发送到其中的一台F1 Sever的时候,F1 Sevrer会解析出里面涉及到的数据源。如果数据源不再本数据中心中,则返回给客户端可以数据所在数据中心的列表。这样客户端就可以通过这些信息重新发送请求, 查询会在F1 Query中被解析为一个DAG表示的一个执行计划。根据客户端不同的请求,F1 Query会选择事交互式的查询执行模式,还是批处理的执行模式。对于交互式的模式,查询优化器会根据一个启发式的算法选择事单机执行还是分布式执行。单机的情况下,F1 Sever自己就解析计划并直接执行,如果是分布式的执行,则将工作发送给若干的F1 Worker,F1 Server作为一个协调者和数据汇总处理者的角色。对于批处理的模式,还是基于Mapreduce的框架。 F1 Query支持的数据源保护了Google常用存储系统,比如Bigtable、Spanner等。另外还可以直接支持在一些文件上面的查询,比如CSV 、ColumnIO 文件等。F1... Read more!

  • 06 Oct 2019
    Data and Metadata Integrity in File Systems

    End-to-end Data Integrity for File Systems: A ZFS Case Study 0x00 引言 文件系统的数据完整性( Data Integrity)是一个比较难处理的问题,现在的很多文件系统不能保证数据完整性。这篇Paper分析ZFS的端到端的数据完整性。主要设计到几个方面,一个是文件系统持久化部分数据的数据完整性,主要涉及到文件系统的元数据以及文件数据本身,这里导致数据完整性问题的主要原因是存储硬件保存的数据随着时间发送了变化,以及Crash导致的系统的不一致的状态;另外一个就是数据在到达application过程中 or application到文件系统路径上面的数据完整性,这里导致数据完整性的原因是memory corruption,比如DRAM Bit Flip or 软件的Bug导致的内存踩踏。一般理论上硬件出现数据错误的可能性很低,但是实际应用中这个概率不能用理论的值来预测, In a recent study of 1.53 million disk drives over 41 months, Bairavasundaram et al. show that more than 400,000 blocks had checksum mismatches, 8% of which were... Read more!

  • 02 Oct 2019
    何必怀念

    何必怀念 看你走过扬起了阵风 吹起了落叶成全一场久别重逢 也让对面看着风景的我 捕捉到一个梦用铅笔在轻轻地诉说 每一个渺小的偶然举措无心风波 都不经意成就我们如今的生活 何必去怀念犯过的错 何必去遗憾那些如果 若从头来过 我也会依然做同样的选择 何必去怀念失去什么 何必去遗憾没说什么 故事不一定有美好的结果 看你走过扬起了阵风 让一只风筝成全了想飞的初衷 也让蓝天没有云也辽阔 也让夕阳缓缓地染红那些玫瑰色的梦 每一个渺小的偶然举措无心风波 都不经意成就我们如今的生活 何必去怀念犯过的错 何必去遗憾那些如果 若从头来过 我也会依然做同样的选择 何必去怀念失去什么 何必去遗憾没说什么 故事不一定有美好的结果 何必去怀念失去什么 何必去遗憾没说什么 故事不一定有美好的结果 Read more!

  • 30 Sep 2019
    DianNao, DaDianNao and PuDianNao, Machine Learning Accelerator

    DianNao: A Small-Footprint Accelerator for Large-Scale Neural Networks 0x00 引言 这篇Paper是著名的“电脑”系列论文的第一篇。常见的Neural Networks如CNN、DNN之类中,体现在CPU上面的运算的话,绝大部分的运算都是矩阵/向量彼此之间的运算,比如矩阵乘法,矩阵-向量相乘等等。一般高性能计算入门的就是一个矩阵乘法的运行,简单的串行版本在优化之后甚至可以获得上万倍的性能提升。虽然CPU目前有SIMD指令的加持,不过用CPU去计算这样类型的计算还是不是非常适合。这样就给了这样的Domain Specific的结构设计机会, We show that it is possible to design an accelerator with a high throughput, capable of performing 452 GOP/s (key NN operations such as synaptic weight multiplications and neurons outputs additions) in a small footprint of 3.02mm^2... Read more!

  • 28 Sep 2019
    SplitFS and Lessons from 10 Years of Ceph Evolution

    SplitFS: Reducing Software Overhead in File Systems for Persistent Memory 0x00 核心内容 这篇Paper是将要发表在SOSP ‘19上面的,关于NVMM上面文件系统设计的一篇文章。其核心思路是通过kernel的模块来管理一般的元数据,而数据不同的管理在用户空间完成。因为NVVM load/store操作只在8-byte的粒度上面能过保证原子性。这个给一些操作,特别是覆盖写操作带来了不少的麻烦,所以之前的一些文件采取的是Log-Stuctured的思路,比如NOVA。为了处理这个问题,提出了一个先写入数据然后在relink的思路。SplitFS的基本结构如下。读写操作被转为为在一个内存映射文件上面的load/store操作。Append操作会写将数据写到一个staging文件,然后在fsync的时候通过relink操作“提交”操作。一般的元数据管理在内核层面完成。 读操作和覆盖写操作使用mmap文件以大约2MB的粒度处理。读操作直接使用memcpy,而写通过non-temporal stores指令完成。SplitFS中,一个逻辑文件的数据可能保存在多个实际的文件中。比如append的文件会先写入staging文件中,这样数据就在staging文件中有,原来的文件中也有。这里通过多个的mmap操作完成文件映射。这里的操作要提一下SplitFS提供了不同的crash-consistency/崩溃一致性的保证: POSIX mode。POSIX mode中,SplitFS提供元数据一致性。这种Mode下面,覆盖写操作直接使用同步in-place更新。但是append则不是同步的,想要fsync来保证持久化,且SplitFS保证append操作原子性。但是和POSIX语义不同的一点就是一个文件被访问 or 更新,其元数据不一定立即能过反映处理。这里看起来覆盖写也是不保证原子性的,和一般文件系统覆盖写不保证原子性的区别的地方是,一般的部分写入为Block粒度,而这里应该是8-byte粒度。 Sync mode。Sync mode为在POSIX Model上面,增加不需要fsync操作的保证而来。这种Mode下面一些操作的原子性不能保证。 Strict mode。在Sync Mode上面,保证操作的原子性。这里的原子性只能保证单个syscall操作的原子性。 下面是SplitFS操作的基本思路。Append操作和Strict Mode下面的覆盖写操作都是先将数据写到一个staging文件,然后通过relink操作完成最终的写入操作。这里为了避免在relink操作的时候,使用将原来的数据拷贝一份的方式,提出了一个操作relink(file1, offset1, file2, offset2, size)。这里只会涉及到文件元数据的操作。Strict Mode下面,为了保证所有操作的原子性,这里使用了一个Operation Log/OpLog。这里OpLog涉及到一些优化主要就是然后将水clflush操作。 Unix系统中的fork和execve操作给SplitFS的实现也带来了一些麻烦。execve操作由于要求原来的文件描述符可以访问,这里的处理方式是先将相关的数据拷贝到/dev/shm下面的一个文件,以PID命名。execve执行之后在拷贝回来。 // More… File Systems Unfit as Distributed Storage Backends: Lessons from 10... Read more!

  • 25 Sep 2019
    Automatic Database Tuning with Deep Reinforcement Learning

    An End-to-End Automatic Cloud Database Tuning System Using Deep Reinforcement Learning 0x00 核心内容 这篇Paper总体很长,但是又具体关于如何利用Deep Reinforcement Learning来进行数据调优的内容只有很少的一点。只是基本讲了利用Reinforcement Learning中的其中一种Deep deterministic policy gradient (DDPG)来进行自动化数据库调优的思路。在环境E下面的t时刻,tuning agent可以获取到一些数据内部的metrics,计为s_t。然后产生一个knobs集合的值,就是一个对性能影响比较明显的集合,其中的参数对应到一个值。根据这个参数调整数据库,然后根据数据的性能表现得到一个奖励,计为r_t。DDPG结合了DQN和actor-critic,这些在网上和相关书籍可以找到很多的接受,Paper中也花了很大的篇幅去介绍,23333。actor-critic中actor的policy function和critic function如下, \(a_t = \mu(s_t|\theta^Q), \\ Q(s_t,a_t|\theta^Q).\\\) 然后就是Q(s,a),得出下面的式子, \(Q^u(s, a) = E_{r_t,s_{t+1}∼E}[r(s_t, a_t), γQ^\mu(s_{t+1}, \mu(s_{t+1}))]\\\) μ(s)为policy,s_{t+1}为下一个状态,r_t =r(s_t,a_t)为奖励函数,γ为折扣因子(discount factor)。之后变成了这样的一个数值优化问题, \(\min L(\theta^Q)=E[(Q(s, a|\theta^Q)-y)^2], \\ where\ y=r(s_t, a_t)+γQ^\mu(s_{t+1}, \mu(s_{t+1}|\theta^Q).\\\) 然后还提了奖励函数,这里的r有延迟和吞吐两方面的建立组成。这两个步伐的奖励函数都是根据调整前后的性能变化值和之前的值的比得到。 \(r... Read more!

  • 19 Sep 2019
    Dremel, PoweDril, Mesa and Goods

    Dremel: Interactive Analysis of Web-Scale Datasets 0x00 核心内容 Google的这篇Paper描述了其使用的Dremel的数据分析系统,据说目前Google Cloud上面提供的BigQuery也以此为基础。不过这篇Paper中没有很多有价值的内容,Paper中主要就是2点:1. nested data model,一种挺特别的数据存储模型。nested data model看起来与Proto Buffer结构非常类似。而Proto Buffer在Google被大量使用,估计使用这样的数据模型也有Proto Buffer的原因。2. 另外一个就是其查询语言和查询引擎,Paper中这里只是简单地描述了一下。 Nested Data Model 下图是一个nested记录和其scheme的一个实例,和Proto Buffer还是很想的。Dreml用列存的方式保存数据,这样就需要有一种方式将Neated Data Model用列存的方式表示,基本的思路如下图。直接使用一般的普通scheme的方式将列之间拆开不能很好地表示Dremel的Nested Data Model,还需要一些额外的东西。这里Dremel定义了一个Repetition Levels和一个Definition Levels。Repetition Levels表示at what repeated field in the field’s path the value has repeated。比如下图的记录的例子r1中,第一个Name中Language出现了两次, Name.Language.Code一列中,en-us 为第一次出现,Name.Language.Code三层都是没有出现过的,所以r字段为0,下面一个值 en为Language的重复记录,所以r字段为2 。二接下来的 NULL和en-gb值都是Name的重复,在Name.Language.Code定义r 为 1。这样实际上就表示出了Nested Data... Read more!

  • 16 Sep 2019
    MillWheel and Dataflow, Stream Processing

    MillWheel: Fault-Tolerant Stream Processing at Internet Scale 0x00 核心内容 这篇Paper是Google的关于Stream Processing系统的一篇文章。估计Google内部早已经有相关的替代系统。MillWheel这里提出的几个核心的东西:exactly one delivery(注意exactly one delivery和exactly one procssing还是区别很大的),Low Watermarks等。 MillWheel每条记录用一个key来标识。MillWheel中,系统的运行可以看作是一些computations组成的DAG图,数据在DAG的边中运行。数据的流动抽象为Stream,其中的每条数据是一个三元组<key, value, timestamp>。MillWheel可以做到exactly one delivery,并且实现了数据之间的乱序处理,这些依赖于MillWheel的Persistent State、Low Watermarks和Timers等机制。 Persistent State,要实现exactly one delivery,主要就是要处理两件时间,1. 对于丢失的信息要有重发的逻辑,2. 对于错误重发实际已经被处理的消息要有去重的逻辑。MillWheel会将一个数据的处理状态信息持久化到分布式存储系统上面。Google有着强大的Bigtable和Spanner之类的系统,在这里就直接将State保存到这些系统上面,而不是向Flink之类的得利用其它的机制来实现类似的功能。 在exactly one delivery语义下面,所以处理记录的时候,一般使用这些的逻辑,1. 查询这条记录是否已经重复了,对于重复的数据,丢弃处理;2. 运行用户的处理数据的逻辑;3. 将处理之后的状态持久化到存储系统;4. ack给发送端/上游;5. 将生成的数据发送给下游。Paper中给出了一段代码: // Upon receipt of a record, update the running // total... Read more!

  • 12 Sep 2019
    Individualized Buffer Tuning, and Automatic Configuration Tuning

    iBTune: Individualized Buffer Tuning for Large-scale Cloud Databases 0x00 引言 这篇Paper是入里利用现在机器学习的一个方法在线调整MySQL Buffer Pool Size的一篇Paper。最近利用机器学习来调优数据库的Paper有不少,这篇Paper聚焦面小一些,主要就是Buffer Pool Size的大小问题。之前看过的微软的一篇Paper是如何自动建立次级索引的,这篇则是关于如何调整Buffer Pool Size。在实际的Large-scale Cloud Databases环境中用的时候,它们会有很多要处理的相同的问题, ... The successful deployment on a production environment, which safely reduces the memory footprint by more than 17% compared to the original system that relies on manual configurations, demonstrates the... Read more!

  • 09 Sep 2019
    SkyBridge and XPC, Secure and Efficient Inter-Process Communication

    SkyBridge: Fast and Secure Inter-Process Communication for Microkernels 0x00 核心思路 这篇Paper是上交一篇优化微内核的IPC性能的一篇Paper。SkyBridge的思路是利用x86处理器的一些虚拟化的功能来实现高性能的IPC,同时还能实现传统的不同的进程隔离在不同的地址空间之内。Paper中先分析了IPC的性能开心的来源,主要有这样的几个部分:1. Mode Switch,即内核态和用户态的转变, 比如涉及到的SYSCALL, SWAPGS 和 SYSRET指令一般的开心分别是82, 26 和 75左右;2,微内核的情况下,IPC的client和server一般在不同的地址空间之内,这样就涉及到一个地址空间的切换,这里的性能开销在开启PCID (process ID)功能的情况下在186 cycles,如果使用了一些缓解Meltdown attack攻击的方法,开心上升到372 cycles;3. 另外的一些事Software IPC logic的开销。以上的几个部分是直接的开心,另外的几个部分是间接的开心,比如flush TLB和cache带来的开销。intel提供的VMFUNC指令可以在no-root的内核和用户模式下调用VM functions,这些由hypervisor管理,比如可以用来处理GPA和HPA之间的转化, EPTP (the pointer to an EPT) switching is one of these VM functions, which allows the guest to load a... Read more!

  • 04 Sep 2019
    A Cache/Storage Subsystem for Modern Hardware

    LLAMA: A Cache/Storage Subsystem for Modern Hardware 0x00 引言 ˙这篇Paper是微软发布的一系列Paper的一部分。这些Paper主要涉及到为新型硬件(SSD)设计的数据结构BwTree,以及这里的 Cache/Storage Subsystem,还有就是下面的事务子系统。LLAMA还是一个基于Page的系统,主要是两个部分,Cache Layer主要负责管理在内存中的操作,而Storage Layer则负责处理在磁盘上面的数据和结构。两者都是以Page为单位对数据进行操作管理,而且两层都是使用同一个Mapping Table,这个Mapping Table和BwTree中的Mapping Table设计对应。 0x01 基本架构 LLAMA的基本架构入下图所示。LLAMA提高的是基于Page的操作结构,Page即可能保存在内存中,也可能保存在磁盘上面。而都是用同一个Mapping Table指向。用指针的最高的一个bit来表示这个Page在内存中还是在磁盘上面。在LLAMA中,如果一个Page的位置发生变化,这里通过一个8byte的CAS操作就可以更新Mapping Table中保存的位置信息。LLAMA提供的Page核心的操作结构也和BwTree中的一些设计,其更新操作分为 1. Update-D(PID, in-ptr, out-ptr, data),delta更新,2. Update-R(PID, in-ptr, out-ptr, data),replacement更新。读取操作Read(PID, out-ptr)可能改变一个page的位置,并更新mapping table。 Cache Layer 在LLAMA执行更新操作的时候,通过CAS更改Mapping Table对应PID的page state pointer完成,添加的可能是delta chain的一个节点,也可能就是一个新的Page。基本的思路如下图。在持久化一个Page的时候,由于Delta Chain和Page是分离的,一个Page State可以有几个不连续的部分组成。其中可能一部分以及存在磁盘上面了,比如下面的page可能只有Delta Chain没有持久化,而Page P部分已经在内存中来,这要只要保存Delta Chain部分持久化就可以了,减少了一些的数据写入量。新写入的部分会保存前面的部分的位置信息。这样的缺点就是可能造成一个Page的数据在LSS上面由好几个分离的部分组成,这里可以选择在合适的情况下将一个Page一次写到一起,虽然可能造成一些额外的写入。为了解决在flush操作的时候其它的操作不去更新这个page,最简单的方式就是加锁,但是这里追求的是latch-free。 如果不加锁而使用CAS的方式。一个方法就是使用CAS的方式更新Mappint Table的内容。如果在Flush之中这个值发生了变化,这个Flush操作就是失败的。这里就是要满足下面的要求, A page that... Read more!

  • 02 Sep 2019
    Procella and AnalyticDB, OLAP Database Systems

    AnalyticDB: Real-time OLAP Database System at Alibaba Cloud 0x00 引言 这篇Paper是阿里在VLDB ’19上面发表的关于其Real-time OLAP数据系统AnalyticDB的一篇。因为这篇Paper是国内的有名的企业发表的Paper,相关的产品也在阿里云上面有提供,相关的资料还是很丰富。无论是网上的信息还是这篇paper中,都好吃AnalyticDB实现了非常nubility的效果。这篇Paper讲的很“概要”吧。 ... It is capable of holding 100 trillion rows of records, i.e., 10PB+ in size. At the same time, it is able to serve 10m+ writes and 100k+ queries per second, while completing complex queries within hundreds... Read more!

  • 27 Aug 2019
    Fast Architecture Sensitive Tree and Semi-order Skip-List

    FAST: Fast Architecture Sensitive Tree Search on Modern CPUs and GPUs 0x00 引言 这篇Paper是SIGMOD ’10的best paper。Fast Architecture Sensitive Tree(FAST)的出发点是利用现在CPU、OS的一些基本特点来构建一个更加快速的Tree结构。这里的提出的Fast Architecture Sensitive Tree不能说是一种通用的Tree数据结构,因为它的构建是一种在一组排序好的数据上面构建的。而这里主要讨论的是在一个已经排序好的数据集合之上,如何安排数据,达到更好的性能。一些符号: E : Key size (in bytes). K : SIMD width (in bytes). L : Cache line size (in bytes). C : Last level cache size (in bytes). P... Read more!

  • 23 Aug 2019
    SocksDirect -- Datacenter Sockets can be Fast and Compatible

    SocksDirect: Datacenter Sockets can be Fast and Compatible 0x00 引言 在网络编程中,RDMA和传统的Socket的差别是非常大,这两者就是完全不同的两种东西。RDMA的编程使用很麻烦,要处理非常多的问题,受的各种的限制也比较多。而直接裸写Socket也有一些麻烦,还是简单了很多。加上成熟的习惯的库,使用起来很方便。Socket受限制很少。之前也出现过一些用RDMA实现兼容的Socket接口,但是或多或少存在一些问题。这篇Paper的主要内容也是利用RDAM实现兼容Socket接口,从Paper中的描述来看,SocketDirect实现的很不错, On the latency side, SocksDirect achieves 0.3μs RTT for intrahost socket, 1/35 of Linux and only 0.05μs higher than a bare-metal SHM queue. For inter-host socket, SocksDirect achieves 1.7μs RTT between RDMA hosts, almost the same as raw RDMA... Read more!

  • 13 Jul 2019
    Optimizations of LSM-Tree, ElasticBF and Preventing Latency Spikes

    SILK: Preventing Latency Spikes in Log-Structured Merge Key-Value Stores 0x00 引言 以LSM-tree结构为基础的Key-Value存储中,一个很麻烦的问题就是延迟尖刺的问题。这个问题的出现和LSM-tree Compaction和Memtable Flush密切相关。即使是想RocksDB这样被广泛使用的Key-Value Store,里面关于这个参数的调整也是一个比较麻烦的问题。这篇Paper提出解决这个问题的节点思路:1. 在系统负载低的时候可以考虑给KVS内部的操作更多的IO带宽,2. Flush和Compaction操作的时候根据不同的Level划分优先级,3. 可抢占的Compaction, ... We use both a production workload at Nutanix and synthetic benchmarks to demonstrate that SILK achieves up to two orders of magnitude lower 99th percentile latencies than RocksDB and TRIAD, without... Read more!

  • 04 Jul 2019
    Scalable Logging and Wait-Free Logging for Multi-Cores

    Scalable Database Logging for Multicores 0x00 引言 这篇Paper讨论的也是早多核环境下面的WAL的优化策略。这里的优化的思路主要是消除中心化的日志方式中,为了保存日志顺序写入和Log Buffer中没有空洞而采用的锁。这些锁在多核的情况下面对性能造成了较大的影响。之前的一些系统提出优化策略有非中心化的思路,比如SiloR那样,每个工作线程只会将自己产生的日志写入到自己本地的Log Buffer中,消除这里不同线程之间的差距。这里的思路还是在原来的方式上面优化, Our efficient implementation of ELEDA is enabled by a highly concurrent data structure, GRASSHOPPER, that eliminates a multicore scalability problem of centralized logging ... Our evaluation showed that ELEDA-based transaction systems improve performance up to 71ˆ, thus showing the applicability... Read more!

  • 28 Jun 2019
    Automatically Indexing in Database and the Largest In-memory Search Tree

    ##Hyperion: Building the Largest In-memory Search Tree 0x10 引言 这篇Paper也是SIGMOD ‘19上面的一篇关于索引的一篇Paper。这篇Paper的关注点在Trie类型的索引如何节省内存方面。在去年的SIGMOD上面就有一篇类似的Paper,HOT。利用将多个BiNode压缩保存在一个节点内的方式实现了很低的一个内存使用。这篇Paper提出的Hyperion,通过紧凑的节点设计和定制的内存分配方式实现了更低的内存占用,不过在性能方面也做出了也妥协, Hyperion can significantly reduce the index memory footprint and its performance-to-memory ratio is more than two times better than the best implemented alternative strategy for randomized string data sets. 0x11 基本思路 Hyperion第一个设计就是使用了更大的partial key来减少节点的overhead,每个节点会表示一个Key中16bit的内容。但是如果是最朴素的trie的设计的话,使用16bit的partial key会造成的结果就是一个节点比较大,而且空间的利用率很低。这里核心的问题是一个可以表示65536个partial key的节点实际使用的时候,里面被真正使用的是比较小的一部分,优化的基本思路就是如果只在需要的时候才去分配这些空间,而不是一开始就将65536个partial key的空间全部分配。之前的ART的设计就是使用8bit的partial key,将节点的大小分为几种,根据节点里面实际保存数据数量选择合适大小的节点。这里的思路则有些不同, Hyperion这里用Container来保存16bit的partial key的数据。Hyperion将其16bit的partial... Read more!

  • 22 Jun 2019
    Fast and Constant Time Recovery in Database

    Fast Database Restarts at Facebook 0x00 引言 这篇Paper将的是Facebook使用的在线分析型的数据库Scuba的快速重启机制。之前的一些数据库系统比如RAMCloud和SiloR这类in-memory的存储系统快速重启的方式基于使用大量的磁盘提供很大的带宽。Scuba也将数据保存在内存之重,它快速重启的思路主要是利用共享内存, ... We can therefore use shared memory to preserve memory state from the old server process to the new process. Our solution does not increase the server memory footprint and allows recovery at memory speeds, about 2-3 minutes per server. 0x01 基本思路... Read more!

  • 15 Jun 2019
    Failure Detector and Membership Protocol

    The φ Accrual Failure Detector 0x00 引言 这篇Paper提出的算法被后面不少的分布式系统使用。一般故障探测的思路是给出一个节点(or 进程)是否已经故障的bool型的判断。而这篇Paper的思路则从故障探测不是完全可靠的出发,给出的是一个是否故障的概率值。 0x01 基本概念 故障探测中,实际的环境中时很难区分真正的故障还是low process。有这样的两个性质, Property 1 (Strong completeness) There is a time after which every process that crashes is permanently suspected by all correct processes. Property 2 (Eventual strong accuracy) There is a time after which correct processes are not suspected... Read more!

  • 07 Jun 2019
    The Log-Structured Merge-Bush & the Wacky Continuum

    The Log-Structured Merge-Bush & the Wacky Continuum 0x00 引言 这篇Paper也是要发表在SIGMOD ‘19上面的一篇关于LSM-tree设计优化的文章。这篇Paper的风格延续了在作者之前Paper的风格,整篇Paper中尽是大量的数据公示和推导。在这篇Paper中使用的一些符号的意思有这样的一个table, Term Definition Unit N total data size blocks F buffer size blocks B block size entries L number of levels levels M average bits per entry across all Bloom filters bits p sum of FPRs across all Bloom filters... Read more!

  • 06 Jun 2019
    X-Engine -- An Optimized Storage Engine

    X-Engine: An Optimized Storage Engine for Large-scale E-commerce Transaction Processing 0x00 引言 这篇Paper是SIGMOD ‘19上面已经可以下载到的一篇Paper。X-Engine是阿里为其X-DB开发的一个存储引擎,基于LSM-tree,引入了FPGA、NVMe等新型的硬件来优化性能, ... which utilizes a tiered storage architecture with the LSM-tree to leverage hardware acceleration such as FPGA-accelerated compactions, and a suite of optimizations including asynchronous writes in transactions, multi-staged pipelines and incremental cache replacement during compactions.... Read more!

  • 01 Jun 2019
    Socrates -- The New SQL Server in the Cloud

    Socrates: The New SQL Server in the Cloud 0x00 引言 这篇Paper是将发表在SIGMOD ‘19上面的关于微软开发的一个New SQL Server的论文(个人感觉这篇Paper题目中的New SQL Server双关,表示是一个新的SQL Server,也可以表示一个New SQL的Server)。在Amazon提出了Aurora的架构之后,类似Aurora架构的数据库出现了不少。这篇Paper总体上是一个类似Aurora的架构,不过也存在存在很多不同的地方。 Socrates本质上是构建在SQL Server之上New SQL。所以SQL Server的一些功能也会影响到Socrates的设计。Paper中先总结了对于Socrates来说比较重要的几个功能,1. Page Version Store,快照隔离级别实现的基础之一,2. Accelerated Database Recovery,优化undo节点的一些设计,3. Resilient Buffer Pool拓展,利用SSD作为BufferPool功能在Scrates上面的拓展,4. 远程IO协议。以及5. 快照备份/恢复和6. IO栈虚拟化等功能。 0x02 基本架构 Socrates是一个存储计算分离、Shared-disk的架构,构建在SQL Server之上。在这样的基本架构之上,将Log分开处理,以及将一些功能下推到存储层等来优化性能。总结说,Scorates的设计原则和目标分为这样的几点, a) separation of Compute and Storage, b) tiered and scaled-out storage, c)... Read more!

  • 25 May 2019
    Faster Key-Value Store and Concurrent Prefix Recovery

    Faster: A Concurrent Key-Value Store with In-Place Updates 0x00 引言 Faster是微软开发的一个KV Store,其设计上有不少可圈可点的地方。特别是Hash Table的实现,Faster中Lock-Free Hash Table的实现的水平很高,也助Faster实现了一个超高的性能, ... Faster achieves orders-of-magnitude better throughput – up to 160M operations per second on a single machine – than alternative systems deployed widely today, and exceeds the performance of pure in-memory data structures when the... Read more!

  • 17 May 2019
    KV-Store/Storage with Erasure Coding

    EC-Cache: Load-Balanced, Low-Latency Cluster Caching with Online Erasure Coding 0x00 引言 EC-Cache是在Alluxio上面实现的一个关于在线EC的一个实现。总的来说,EC-Cache还是作为一个内存Cache的存在,并不是一种支持持久化的对象存储的在线EC的方式,所以这样避免了很多问题。EC-Cache总体的思路是,在写入的时候就讲对象拆分并做EC处理,在读取的时候只需要读取足够恢复数据的部分即可,这样的方式在一些情况下可以减少一些延迟。这篇Paper的内容很长,但是实际上核心的内容就是一节¯_(ツ)_/¯, As compared to selective replication, EC-Cache improves load balancing by more than 3× and reduces the median and tail read latencies by more than 2×, while using the same amount of memory. EC-Cache does so using 10% additional... Read more!

  • 12 May 2019
    Efficient IO with io_uring

    Efficient IO with io_uring 0x00 引言 io uring是Linux上面新的异步IO机制。在io uring之前,Linux下面的异步IO机制是aio,不过aio存在不少的问题。io uring一出现就受到了比较大的关注,这也可能多亏了aio衬托地好吧¯_(ツ)_/¯。io uring的核心是三个系统调用,直接使用这三个系统调用的话会比较麻烦。所以作者还额外添加了一个库liburing,方便使用。 0x01 liburing liburing是为了简化io uring的使用的一个库,估计后面使用io uring的话,使用到这个库的机会还是很大的。liburing中,一个核心的结构是struct io_uring, struct io_uring { struct io_uring_sq sq; struct io_uring_cq cq; unsigned flags; int ring_fd; }; // 其中的两个struct结构如下 struct io_uring_sq { unsigned *khead; unsigned *ktail; unsigned *kring_mask; unsigned *kring_entries; unsigned *kflags; unsigned *kdropped; unsigned *array;... Read more!

  • 04 May 2019
    Sharding the Shards with Akkio, and Auto-Sharding with Slicer

    Sharding the Shards: Managing Datastore Locality at Scale with Akkio 0x00 引言 这两篇关于Sharding的Paper出自两个著名科技公司的实际系统,和一般的Sharding讲的是数据分区不同,Akkio实际是关于利用数据访问的Locality,将数据搬到离访问提更近的位置。大型的互联网公司为了系统的容灾,存储系统的数据很多是使用多个副本分别保存到不同数据中心的策略。这些公司一般又有多个数据中心,数据访问很多时候会有一些地域特性,如果将数据 or 数据的主副本保存离用户更近的位置,访问的性能也会提高。 0x01 基本架构 Sharding是数据存储系统为了实现可拓展常用的一种策略,Sharding the Shards的含义就是Data Store中的Shards继续分成更新的Shard。这里使用的Data Store是Facebook内部的一个系统ZippyDB。这里Sharding the Shards就设计到Akkio中一个核心的概念u-shard,通常的Shared这里ZippyDB中是几个GB的大小,但是对于为了实现访问的Locality而迁移数据来说,几个GB的大小还是太大了,这里就使用了一个再次发片的u-shard,它的大小在几百KB的级别。另外的,这里将一个Shard的副本称之为shard replica set,这些副本的数量,和这些副本保存的位置的配置称之为replication configuration。然后,这里有将有系统replication configuration的shard replica set称之为replica set collection。对于这样的一个集合,会有一个location handle,Akkio就负责将u-shard在不同的replica set collection之间进行迁移。 Akkio的基本思路和实现的架构还是比较简单的,不过这个真正在实际系统中实现的时候,估计要考虑非常多的问题,实现的难度也不会小。Paper中的架构以构建在ZippyDB上面为例,为了支持Akkio,一般的read(key)接口被更改为read(μ-shard-id,key),第一个参数就是一个u-shard的ID。者这里的架构中,包含了这样的几个核心组件, Akkio Location Service (ALS),这个就是维护每个u-shard副本的位置信息,Akkio的客户端可以通过getLocation(μ-shard-id)来获取这个信息,这个接口返回一个location handle。这个返回的信息可以被ZippyDB的客户端使用,知道如何访问合适的服务器。 Access Counter Service (ACS),ACS就是一个访问记录,用于记录不同区域在最近的一段时间内数据的访问信息。 Data Placement Service (DPS),在知道了u-shard不同区域的访问信息之后,DPS就可以根据这些信息来就定一个u-shard是否需要进行迁移,怎么样迁移能够取得更加好的效果。在给u-shard决定一个保存的位置的时候,主要是通过计算一个score。这个score通过对目前可用的replica set... Read more!

  • 02 May 2019
    eRPC and RPCValet, Speeding RPC with New Ideas

    Datacenter RPCs can be General and Fast 0x00 引言 这篇Paper是NSDI ‘19的一篇Best Paper。eRPC在一般的硬件上面实现了高效的RPC。和一般的RPC实现使用TCP甚至是HTTP之类的协议,eRPC更像是直接实现在IP上面的一个协议,自己处理包丢失、拥塞等传输层协议处理的问题。这里虽说是一个RPC系统的设计,不过感觉这里说成一个新的的特殊的传输层协议更加好, eRPC performs well in three key metrics: message rate for small messages; bandwidth for large messages; and scalability to a large number of nodes and CPU cores. It handles packet loss, congestion, and background request execution. In microbenchmarks,... Read more!

  • 21 Apr 2019
    Cold Filter, HeavyGuardian, HeavyKeeper and Pyramid Sketch

    Cold Filter: A Meta-Framework for Faster and More Accurate Stream Processing 0x00 引言 这里一次性看了PKU的几篇类似的Paper,不得不佩服其发paper的效率。而且这些Paper和前面的几篇在SIGCOMM中方便的几篇讲Sketch用在网络策略中的存在一些联系。Cold Filter就是一种Sketch的设计,利用一种Sketch来做Filter。与一般的Count Sketch和Count-min Sketch的设计不同。Cold Filter这里主要的idea就是引入一个两层的设计。Coun Sketch这样的存在几个缺点,一个就是内存效率不高,为了能计数到比较大的值,这里就要使用更多的bit来作为一个计数的单位。但是实际的数据大部分出现的次数都是比较小的,而且访问不均衡的现象很常见。这个就是引入两层计数方式的基本出发点, ... Our filter can accurately estimate both cold and hot items, giving it a genericity that makes it applicable to many stream processing tasks. To illustrate the benefits of our filter,... Read more!

  • 20 Apr 2019
    Storage with SMR Disk

    Skylight – A Window on Shingled Disk Operation 0x00 引言 这篇Paper是一篇了解SMR磁盘一篇很好的一篇Paper。这篇Paper主要的内容就是7个探究SMR磁盘性质的几个实验,设计到SMR的辨别,持久型Cache的类型、大小和位置等的信息,以及SMR的垃圾回收策略等。另外还有SMR的Block映射的方式,zone结果等的内容, 0x01 背景 SMR磁盘的基本架构如下图所示。基本的结构是track,这个和一般的磁盘一样,部分在SMR磁盘上面,磁道之间是有重叠的,提供了存储密度的同时也使得它直接顺序写入。为了缓解这个问题,这里引入了以Guard Regions分割的多个Band,不同Band之间的写入不会相互影响。不过这样随机写入的能力依然十分差,这里又引入了Persistent Cache来继续缓解这个问题,这个Persitent Cache相对于使用DRAM之类的易失存储介质而言。这个CMR的Persistent Cache作为容纳一些随机写操作。 一般的SMR就靠文件系统只使用顺序写入来优化,Driver-Managed的在驱动层面优化了SMR,而另外的Host-Managed的则提供接口给主机来优化。在Driver-Managed的SMR中 SMR引入了类似于SSD中FTL的结构,SMR区域的Band会映射到Persistent Cache中的一个区域。开始写入的时候先写入到这个映射到区域,在写入到一定量的时候,这些数据会被移动到应该在的SMR的区域,这个操作被称之为cleaning。这个映射方法可能是一种静态的映射,也可能是使用一些FTL中使用的组相联 or 全相联的方式。Paper中使用了模拟的方式来构造一个测试环境, 0x02 结构相关 这里是SMR结构特性的几个测试方法, 磁盘类型和Persisten Cache类型。判断磁盘类型的方式是在开始的1GB进行随机写入,一般的CMR磁盘写入的延迟是一个比较平稳的,而SMR磁盘在过了一个写入一些数据之后,SMR会有一个突然的延迟显著增加。这个延迟的增加如下图所示,一个突然的延迟增加是一个数量级的增加。而在发生这个写入延迟的突然增加之前,这个写入的特性和一般的CMR写入特性类似,从而判断其Persistent Cache类型就是一般的CMR磁盘, Cache位置和布局。这里探测Cache的位置使用了一种叫做fregmented read的现象。当从一个SMR顺序读取的时候,如果Cache包含了一个block的新的版本,这样的话磁盘读取的时候磁头必须重新seek到Cache坐在的位置。 这个算法如下,通过写入一个block,跳过一个block的方式,选择不同的offset重复以上的实验, Starting at a given offset, write a block and skip a block, and so on, writing 512 blocks... Read more!

  • 14 Apr 2019
    New Lock free, scalable WAL design of MySQL 8

    New Lock free, scalable WAL design of MySQL 8 0x00 引言 这里并不是一篇Paper,而是来自MySQL的一篇Blog,主要讨论了在MySQL中WAL的一些改进,主要是为了去除为了保存log中LSN严格有序和没有空洞的要求而引入的两个mutex。这个优化在多核和高速存储硬件的环境下多性能的提升比较大。前面的文章[2]也有关系优化WAL的一些思路。在MySQL中,日志的产生和写入磁盘可以看作是一个生产者、消费者模型。工作线程处理事务的时候产生日志数据,在系统Crash的情况下,这些日志会被使用用于恢复到Crash之前到状态。这里的优化点就是优化多个生产者情况下处理的性能。这里由于一般数据库系统和MySQL自己设计中,写入日志必须有这样的一些要求, 在MysQL中,被修改过的Page为dirty page,这些Page保存在一个flush list中,且必须按照LSN递增的方式排列。 在MySQL中,MTR是一个最小的事务处理单元,但不并不是只会包含一条日志。MySQL在这里的时候,为了保证一个MTR的日志作为一个整体被持久化,这里先将日志写入到线程本地的Cache中,然后拷贝到全局的Log Buffer中。这里持久化日志的日志,日志必须按照LSN的顺序排列。 MySQL 8之前的设计这里利用了log_sys_t::mutex 和log_sys_t::flush_order_mutex两个mutex来保证这些要求。基本的操作如下,在MTR将dirty page添加到flush list中的时候,会持有log_sys_t::flush_order_mutex的锁。其它准备添加dirty page到flush list中的线程会等待这个mutex,这个线程会持有log_sys_t::mutex的锁,所以另外的准备写Log Buffer的线程必须等待这个log_sys_t::mutex。基本的思路如下,下面的flush list不只一个,但是都会在一个mutex的保护下面。移除这两个mutex带来的第一个问题就是flush list中diry page的顺序得不到保证,另外的一个问题是线程可以并发写Log Buffer的话,会存在Log Buffer中有空洞的问题。这个在前面的[2]中也讨论过。 0x01 空洞问题处理 这里先谈了第二个问题如何处理。MySQL 8中新引入了一种叫做Link_buf的无锁数据结构,第二个问题的解决就利用了这个数据结构。这个数据结构可以看作是一个环形的数组。这个数组中的元素称之为slot,每个slot的更新都是原子的,环形的结构会循环使用。一个单独的线程遍历这个数据处理其中的元素,在遇到一个空的slot的时候会定下来等待。这里使用了两个这样的结构来处理,recent_written用于记录日志写入到Log Buffer中的完成状态,其维护的一个值M,表示来LSN小于这个M的日志记录都已经写入到了Log Buffer中。这里的处理和刷日志到磁盘的工作由一个线程来处理。在处理slot的数据的时候需要设置合适的内存屏障。 如下图所示,Log Buffer中的空洞数据被写入完成之后,线程可以根据下面第二个图中绿色框表示的那样已经知道的写入到Log Buffer的LSN向前推进, 上图5后面中有2个为空洞的位置,导致buf_ready_for_write_lsn无法向前推进。在写完成之后,下面的数据结构更新,可以根据这个结果的信息更新buf_ready_for_write_lsn, 0x02 Flush List顺序问题处理 recent_closed则用来解决移除log_sys_t::flush_order_mutex会导致的问题。这里为例保证系统的正确性,flush list相关的两个要求如下:1. Checkpoint,为了保证Checkpoint的正确性,加入dirty page P1的上面的LSN小于P2,则必须保证P2不能在P1之前刷盘。2. FLushing,刷盘的时候最旧的dirty page必须先落盘。这两个要求感觉实际上就是同一个要求。recent_closed用来追踪最大的LSN(maximum... Read more!

  • 11 Apr 2019
    Wormhole -- A Fast Ordered Index for In-memory Data Management

    Wormhole: A Fast Ordered Index for In-memory Data Management 0x00 引言 这篇Paper提出的思路很新颖。它用一种新思路设计了一种支持范围查找数据结构。Wormhole可以支持最坏在O(logL)的时间复杂度下面查找一个Key。一般的平衡树or Skiplist结构点查询的复杂度都是O(logN),这里N是Key的数量,基于trie的数据结构的复杂度一般为O(L),这里的L为Key的长度,而Wormhole点查询的复杂度是O(logL),而且其它方面的表现也很不错, ... Wormhole’s index space is comparable to those of B+ tree and skip list. Experiment results show that Wormhole outperforms skip list, B+ tree, ART, and Masstree by up to 8.4×, 4.9×, 4.3×, and 6.6× in terms... Read more!

  • 05 Apr 2019
    Flat Datacenter Storage

    Flat Datacenter Storage 0x00 引言 这篇也是分布式存储方向一片很有名的Paper。Flat Datacenter Storage的目标是设计一个高性能、容错、大规模以及locality-oblivious的分布式存储系统。Flat在FDS中的一个含义就是所有的所有的节点都能以同样的带宽和延迟访问数据,这样的话在FDS中不需要考虑数据局部性的问题,以解决一些系统在考虑局部性的时候反而带来的效率降低的问题, FDS applications achieve single-process read and write performance of more than 2 GB/s. We measure recovery of 92GB data lost to disk failure in 6.2s and recovery from a total machine failure with 655GB of data in 33.7s. 0x01 基本架构 在FDS中,数据的存储都是一个blob为抽象,一个blob使用一个128bit的GUID来表示。这个GUID可以是客户端指定的,也可以是系统自己生成的。Blob的大小限制只取决于系统的存储空间大小。FDS的一个设计目标是可以让应用使用系统的能够通过的所有的带宽,这里FDS的一个设计就是将blob划分为tract,这个tract的大小一般为8MB,在一些Flash存储上可以设置得更加小一些,比如64KB。FDS中的每个磁盘有一个tractserver进程来管理,它处理来自客户端的读写请求。tractserver这里不会使用文件系统,而是直接使用裸的存储设备来管理数据,它一般将tract的元数据都Cache在内存中。 //Getting... Read more!

  • 30 Mar 2019
    KVS, WAL, Log-Structured Allocator witn NVM

    NVWAL: Exploiting NVRAM in Write-Ahead Logging 0x00 引言 这篇Paper讲的是在SQLite的WAL在NVRAM下面的一个优化。这篇Paper讲的核心的优化点可以总结为四点, Byte-granularity differential logging,之前常见的日志是以Page写为单位的,这里的differential类型的日志只会每次记录B-treePage的改变,而不是整个Page。这里利用的是NVRAM可字节寻址的特性; Transaction-aware memory persistency guarantee,优化NVRAM中使用Cacline Flush; User-level NVRAM management for WAL,直接在用户空间管理NVRAM空间; Effect of NVRAM latency on application performance, 0x01 基本思路 NVMAL优化对象是SQLite,这里主要讨论的是它的WAL的优化, 字节粒度的differential logging,这个优化是很有意思的一个优化。不过利用NVRAM的可字节寻址的特性来优化WAL之前的研究也不少,differential logging式的日志页游研究,总的思想来也没有很多特别的地方。如下图所示,图a中几次对一个page的操作造成了一个Btree Page被写入多次,这个也是在这样的环境中常见的写入放大的问题。而图b的思路就只会记录Page变化的信息。它的基本结构也是一个WAL Frame拖部分组成,后面的payload则和前面的方式不同,它的大小是不确定的。Payload就是记录变化的信息,header里面会记录一些元数据和next_frame,即执行下一个WAL-Frame的指针。 用户空间的NVRAM Headp管理。这里NVRAM资源管理利用前面的一篇Paper,Heapo。这里是一个类似二维数字的结构。可以理解为这里会一次性分配一个比较大的块。这些块用另外的一个数字来管理。分配的块中会写入多个WAL Frame,不同的WAL Frame中会通过指针相互连接,这个就是前面提到的WAL Header中存在的next frame指针。这个block会存在三种状态,free, in-use, 和 pending。Free表示一个block为空闲的block,可以以后被使用,pedding的还有就是这个内存块中的空间已经被使用,in-use即使目前被使用的block。这里又有一些slab的意思,不过这里保存的对象会是不定长的。 Transaction-Aware Memory Persistency Guarantee... Read more!

  • 24 Mar 2019
    Key-Value Caching with Flash

    Flashield: a Hybrid Key-value Cache that Controls Flash Write Amplification 0x00 引言 这篇Paper是关于在Flash上面实现Key-Value Cache时候写入放大的问题。它的主要的对比对象就是前面的RIPQ。 Flashield通过结合多种方式来优化写入放大的表现。Flashield将DRAM做3个方面的用途,1. 作为一个Filter来决定一个对象是否最终被写入到Flash上面,2. 保存对象的元数据,用于对象的查找和驱逐,3. 作为Flash的Cache层, Compared to state-of-the-art systems that suffer a write amplification of 2.5× or more, Flashield maintains a median write amplification of 0.5× (since many filtered objects are never written to flash at all),... Read more!

  • 22 Mar 2019
    Frequency-Counts/Quantile-Sketch over Data Stream

    Approximate Frequency Counts over Data Streams 0x00 引言 这里总结的是这样的一类问题:给定两个用户指定的参数s和e,两者的取值范围都在(0,1)之间,且e远小于s。N表示一个流中目前经过的tuple的数量,这里的算法要满足/解决这个的几个条件/问题,1. 所有在itemset中的,出现频率高于sN被输出,且没有假阴性,也就是说达到了这个条件的必须被输出,2. 实际出现频率在(s-e)N之下的不会被输出,也就是说有假阳性,但是出现假阳性的item的频率会限制在一个范围之内,3. 估计的频率最大能够小于真实频率的值不能超过eN。注意这里并不需要计算实际的频率,只要超过一个阈值的即可,更加不需要实际出现的次数了。 0x01 Sticky Sampling Algorithm Sticky Sampling算法中多了一个参数,这里用u表示。这里使用一个S集合,元素为(entry, f),其中entry为元素,f为其出现频率的估计。算法中另外一个参数为r,表示采样率。在一个元素到达的时候,如果已经存在在S中,则对其f加1操作。否则,对到来的元素进行采样操作,采样率就是r。如果这个元素被选中,则添加到S中,f设置为1。初试的时候r 为 1,后面根据 $t = 1/e\log(s^{-1}u^{-1})$,开始的2t个元素设置r为1,接下来的2t个设置为2,在接下来的4t个设置为4,一次类推。Sticky Sampling算法最终选择其f不小于(s-e)N的元素进行输出。Sticky Sampling算法满足上面提到了3个条件。且最多会保存$2/e\log(s^{-1}u^{-1})$个元素 0x02 Lossy Counting Algorithm Lossy Counting算法也是一个很简单的算法。基本思路是将流划分为窗口,这里使用w表示,w设置为1/e向上取整。算法维护一个数据结构D,保存的entry为(entry,f,delta),前面两个的含义和前面的算法一致,delta表示最大可能的error。初始化的时候,D为空,在达到一个元素的时候,如果不存在D中,则添加一个(entry, 1, Bcurrent-1),Bcurrent设置为N/w向上取整。如果已经存在D中,增加频率计数。在跨越窗口的时候,如果f + delta的值小于 Bcurrent,则删除。输出f不小于(s-e)N的元素。 0x03 其它一些 Misra-Gries(MG)算法也是一个很简单容易理解的算法。在数据处理中经常会用到,用于发掘出现频率最高的一些项。一个数据结构D,初始化为空。在一个元素到达的时候,如果已经存在D中。则将其计数值+1。如果不存在,且这个D中的原属数量小于预定义的最大值K,则将其计数值初始化为1加入D中。如果D中的元素数量已经达到了阈值K,则将其中的元素计数值-1,并移除其中计数值为0的情况。一些算法问题中长出现的一个问题就是如何在O(N)的时间内找出一个数组内出现次数超过一半的那个元素,其使用的算法可以看作为Misra-Gries(MG)算法的一种特殊情况。 Space Saving Algorithm,Space Saving算法也是一个很简答的算法。一个数据结构D,初始化为空,在一个元素达到是,会带有一个权重w。如果这个元素已经存在D中时,将其权重加上w,如果不存在其中,则将其权重加上D中最小权重元素的权重,并将这个最小权重的元素删除。 Space-Efficient Online Computation of Quantile Summaries... Read more!

  • 20 Mar 2019
    RIPQ -- Advanced Photo Caching on Flash for Facebook

    RIPQ: Advanced Photo Caching on Flash for Facebook 0x00 引言 这篇Paper是关于Facebook利用Flash来作为图片Cache的方法。Facebook关于图片存储后段为Haystack 和 F4。利用Flash作为Cache可以有比内存大得多的存储空间,而RIPQ的出现是为了解决之前Facebook使用Flash作为Cache方法的一些问题。博客文章[1]是一个很好的总结。这篇Paper提出了一个RIPQ,即Restricted Insertion Priority Queue这样一个框架,用于在此基础上实现多种缓存算法, ... Our evaluation on Facebook’s photo trace shows that these algorithms running on RIPQ increase hit ratios up to ~20% over the current FIFO system, incur low overhead, and achieve high throughput. 0x01 发展过程... Read more!

  • 17 Mar 2019
    Key-Value Stores on SSD(2)

    FAWN: A Fast Array of Wimpy Nodes 0x00 引言 这篇Paper是SOSP ‘09的best paper。FAWN设计为一个使用Flash的存储系统,使用处理能力很弱的单个节点,所以称之为Wimpy Nodes。在FAWN的价格上面实现了一个称为FAWN-KV的KVS。除了提供高性能的表现外,它还实现了远比其它类似系统的高效率, ... Our evaluation demonstrates that FAWN clusters can handle roughly 350 key-value queries per Joule of energy—two orders of magnitude more than a disk-based system. 0x01 基本架构 emmm,在FAWN中使用的是500MHz的嵌入式的CPU,在21个节点的系统中,每个节点能够处理1300的QPS。这个性能看来不是很高。但是在能效方面FAWN表现突出。在总体的架构设计上面,FAWN还是一种类似于Dynamo的设计, 客户端直接请求的是系统的Front-end。这个Front-end将客户端的请求转发给正确的back-end的存储节点。后端的存储节点使用一致性hash来管理,形成一个逻辑上的环形结构。Key会被映射到这个环上面的某个位置。这里实际上和Dynamo的架构基本上是一样的。 The FAWN Data Store 存储层这里FAWN就是一个log-structured的Key-Value Store。这里实际上也就是一个类似一个bitcask的存储模型。一个Hash索引保存在内存之中。数据以append-only的形式保存在Flash上面。这里使用一个160bit的值来作为key-value的可以(估计就是sha1),但是将这样的一整个key保存在内存中的话,内存使用效率会不高。所以这里只会保存key一部分的内容。如下图所示,FAWN这里使用key最低的i个bit作为内存中hash表的寻址。接下来的15bit和一个validbit,加上4byte的在flash上面的位置信息,作为Hash索引的Value。在查找一个key-value的时候,使用key的最低的k个bit在hash索引中查找,并比较KeyFrag,valid用于标记这个key-value是否已经被删除。这里对于可能存在的hash冲突,需要将所有的冲突的key-value都从flash上面取出来,比较完整的key,才能最终确定这个key是否存在,是哪一个?这里加上了一个KeyFrag的思路也被用在了后面的一些系统用,用于减少hash冲突的概率。 /* KEY... Read more!

  • 16 Mar 2019
    Cardinality Estimation Algorithms

    A linear-time probabilistic counting algorithm for database applications 0x00 引言 这里总结了一些Cardinality Estimation算法的思路。这类算法处理的问题是非精确的统计一堆数据中,里面不同对象的数量。在数据量不大的时候,使用Set(Based Hash or Tree)是一个不错的方式,但是在数据量非常大的时候,比如几百亿甚至是更多的时候,这些精确的统计算法显得不是很必要,极少有场景需要在数据在几百亿的量级上还要精确地统计到底有多少个。这个时候非精确的统计会是一个更加好的方法。这里最常用的算法就是Hyper Log Log,在Redis中也有提供,消耗的内存低到惊人,一般是10KB级别的消耗,误差也很低,简直就是一个几乎完美的算法。 0x01 基本思路 这篇Paper不是Hyper Log Log,而是一种叫做Linear Counting的算法。它的基本思路还是利用bitmap,先将对象计算一个hash值,然后在这个bitmap上面,将对应的bit为设置为1,然后通过这个bitmap中bit为0的位数来统计元素的数量。设 N*为估计的对象的数量,u为bit位为0的数量,Vn = u / m,m为bitmap的长度。 \(N^* = -m \ln V_n = -m\ln\frac{U_n}{m}\) 每次设置之后,一个bit不被设置的概率位1 - 1/m,n次的话就是 (1 - 1/m)^n,这里稍微改变一下这个式子,在m,n足够大的时候,这个式子可以变为, \((1-\frac{1}{m})^n = (1-\frac{1}{m})^{-m\frac{n}{-m}} = e^{-\frac{n}{m}}\) 这个是高数中求极限会常用到的一种方法。n个求和就是, \(E(U_n) = \sum_{i-1}^{m}... Read more!

  • 14 Mar 2019
    Parallel Join Algorithms (Hashing)

    Design and Evaluation of Main Memory Hash Join Algorithms for Multi-core CPUs 0x00 引言 Hash Join是几个Join算法中被运用很多的一种,虽然到现在某著名的开源数据库都不支持Hash Join。Hash Join一般范围两个阶段,第一个阶段是建立Hash Table,用于在后面的阶段使用,第二个节点是探测阶段。当然可以存在可选的分区阶段。通过多种的优化措施的测试结果分析,简单的的方式反而更加好, ... a very simple hash join algorithm is very competitive to the other more complex methods. This simple join algorithm builds a shared hash table and does not partition the input... Read more!

  • 11 Mar 2019
    Partition in Database

    E-Store: Fine-Grained Elastic Partitioning for Distributed Transaction Processing Systems 0x00 引言 这几篇的Paper主要讲的是一个Partition数据库中如何做Partition的一个问题,都是在H-Store这样的一个系统下面的一个研究。H-Store是一个Partition的内存数据库。Partition可以是以一定的规则来讲数据划分到不同的Partition,而E-Store这里关注的是热点数据的问题。这个问题在很多OLTP的场景中存在。而E-Store解决这个问题的基本思路是采用一种two-tier的分区方式。E-Store会从一个初试的分区方式开始,数据项会被划分为大小为B的Blocks(E-Store选择B = 100, 000)。在系统运行的过程中,E-Store会选择访问频率最好的K个Keys(比如前1%)来单独处理,决定它们存放的位置, 0x01 基本思路 常见的分区方式比如基于Hash 或者 范围的方式都是一种单层的分区。而E-Store采用的是一种“双层”分区的策略,兼而有之就是对于一般的数据就使用常见的策略,而一个小范围的热点的数据则采用单独分配的方式,分配到一个单独的节点。E-Store的基本架构如下图, E-Store要解决的问题可以分为三个主要的部分:1. 如何发现负载的不均衡,需要进行数据迁移,2. 如何选择迁移的数据,以及迁移到哪里,3. 如何执行数据迁移的操作。这三个部分对应到上面架构图中的的就是:E-Monitor负责收集数据库系统执行过程中的一些统计信息,比如资源的使用率和数据项的服务情况。这些这些会交给E-Planer作出决策的依据,E-Planer产出迁移哪些数据,迁移到哪里的决定。另外实际去迁移数据的就是Squall,也就是下面的一篇Paper。Squall的Paper虽然发表在E-Store之后,不过Paper中提到,E-Store还是基于更新版本的Squall。 Monitoring E-Store这里使用了一种自适应的统计信息收集方式。开始的时候E-Store使用一个DBMS之外的进程来收集一些OS层面的统计信息,这里应该就是这个节点资源利用率的一些信息,在这个统计数据中的一些数据指标达到一个阈值之后,会出发DBMS中元组基本的信息统计,这部分只能在DBMS内部进行。这样做的一个好处就是可以降低在正常情况下的一个访问信息统计造成的开销。 在OS层面,E-Store会对一项资源设置两个threshold,分别为高水位和低水位。超出这个水位的范围之后会触发元组基本的信息统计。 触发了元组层面的统计之后,DBMS中的每个分区都会统计一个时间窗口内的一个Top-K的一个信息。经过了这个时间窗口之后,每个分区的信息会被放松到E-Monitor。E-Monitor会根据这个信息得出一个Top-K的列表 Planer 在获取到了Top-K的列表之后。E-Planer会首先尝试移动热点数据来使得集群的负载达到一个均衡的状态。如何只靠处理热点的数据无法使其达到,则会考虑移动一些“冷”些的Block。热点数据数量比较少,能够在较短的时间内完成使用的网络带宽也小得多。如何整个集群的资源利用率都大于高水位的阈值,在一定条件下,E-Store就会将集群的机器数量扩大。当整个集群的资源利用率小于低水位时,则会考虑将集群的规模缩小。在决定将数据放置到哪里的问题上面,E-Store这里使用一种理想的策略和一种近似的策略, Optimal,理想策略的一个目标就是每个节点的负载在靠近集群平均负载epsilon的一个范围之内。每一个热点数据和一个冷的Block都只会被分配到一个Partition,x(i, j)为1表示第i个热点数据分配给了第j的Partition,同理y(i,j)表示冷的数据块 \(\\ 则有L(p_j) = \sum_{i=1}^{n}(x_{i,j}) * L(r_i) + \sum_{k=1}^{d}(y_{k,j}) * L(b_k)) \ge A - \epsilon \\ 同样有 L(p_j) \le... Read more!

  • 09 Mar 2019
    Confluo and Chronix

    BTrDB: Optimizing Storage System Design for Timeseries Processing 0x00 引言 这篇Paper是关于专门为存储时序数据设计的一个树形的数据结构。这里举的一个例子就是电网中一类传感器的例子,这种传感器产生12个以120hz为频率的一个数据信息。时间精度比较高又100ns。这样的数据一般这样的一些特点,一个检测的数据称之为时间线,这类数据的时间线比较稳定,而且生命周期很长。而且数据频率和时间精度很高,另外数据传输的过程中,数据乱序经常出现, ... demonstrating a throughput of 53 million inserted values per second and 119 million queried values per second on a four-node cluster. The system achieves a 2.9x compression ratio and satisfies statistical queries spanning a year of data in... Read more!

  • 08 Mar 2019
    Shinjuku and Shenango, New Network Stack and Optimizations

    Shenango: Achieving High CPU Efficiency for Latency-sensitive Datacenter Workloads 0x00 引言 Shenango是Arachne这样的系统的继续优化,实际上都是网络栈Dataplane的一个优化。Shenango聚焦于实现高的CPU效率方面。为了实现高的CPU效率,Shenango会在一个很小的时间粒度-5us-内决策CPU核心的重新分配。实现高效的重新分配主要基于两点,1. 一个高兴的算法用于实现需要进行重新CPU核心分配,2. 一个IOKernel的特权组件,运行在指定的CPU核心之上,编排CPU核心, Shenango achieves tail latency and throughput comparable to ZygOS, a state-of-the-art, kernel-bypass network stack, but can linearly trade latency-sensitive application throughput for batch processing application throughput, vastly increasing CPU efficiency. 0x01 基本思路 Shenango核心的重新分配的目的是为了给应用尽可能分配少的CPU核心,但是有不至于导致compute congestion的现象。类似的系统有之前的Arachne,Arachne是一个完全用户态的线程库。Arachne重新分配一个核心需要29us的时间。而IX要求更多的时间。之前的系统使用通常使用延迟、吞吐和核心利用率来估计应用需要CPU核心的数量。但是这些指标都不能在微妙的级别的interval内应用。Shenango同时考虑线程和packet来探测compute congestion的信号,另外引入一个congestion detection... Read more!

  • 07 Mar 2019
    Redundancy Does Not Imply Fault Tolerance

    Redundancy Does Not Imply Fault Tolerance: Analysis of Distributed Storage Reactions to Single Errors and Corruptions 0x00 引言 这是一篇很有意思的Paper,研究的是在分布式存储系统中,很常用的一个策略就是使用数据保存多份的情况。这篇Papers中使用了一个基于FUSE的用户空间的文件系统errfs来进行错误注入,发现了很多系统虽然使用了副本冗余来实现更高的可用性,但是在文件系统故障 or 存储介质出毛病的时候,这些系统不同程度的出现了各种毛病, ... We find that modern distributed systems do not consistently use redundancy to recover from file-system faults: a single file-system fault can cause catastrophic outcomes such as data loss,... Read more!

  • 06 Mar 2019
    Counter, Beyond Atomic-Long

    Pay Migration Tax to Homeland: Anchor-based Scalable Reference Counting for Multicores 0x00 引言 计数器在一些基于应用技术对象/内存回收的场景中是一个很常用的结构,这篇Paper讨论的是Linux Kernel中refcount的计数器算法的优化。这里提出的PaygGo总体上来说,还是Paper[3]中提出的RefCache的优化。这里认为,计数器的主要的4个方面的overhead为Counting overhead、Query overhead、Space overhead和Time overhead,即从更新、读取、空间和时间上面分析一个计数器算法的好坏程度, PAYGO, a reference counting technique that combines per-core hash of local reference counters with an anchor counter. PAYGO imposes the restriction that decrement must be performed on the original local counter... Read more!

  • 05 Mar 2019
    IndexFS and LocoFS

    IndexFS: Scaling File System Metadata Performance with Stateless Caching and Bulk Insertion 0x00 引言 这Paper是关于利用KVS作为分布式文件系统的元数据存储的。之前就有一些Paper设计了利用类似LevelDB的Key-Value来实现单机的文件系统。比如TableFS[2]是利用LevelDB实现的一个用户空间文件系统,TableFS的论文里面只是简单的介绍了一些FS层次结构到KV的映射,但是没有谈到解决重命名以及文件夹移动等的问题,这个问题比较难处理。后面的BetrFS则将类似的思路般到了内核空间,相关的几篇Papers也重点讨论了重命名、移动文件文件夹等操作的实现。这里的IndexFS则是将环境放到了分布式文件系统下面,主要是用KVS存储分布式文件系统的元数据。 0x01 基本架构 IndexFS的基本架构如上图,整体上还是类似于GFS的架构。主要的变化就是元数据保存到了Key Value存储系统中, 对于元数据保存到KV存储系统中,Key为Parent directory ID, Hash(Name),Value为Name, Attributes, Mapping|File Data|File Link。Value的后面三种可以的情况根据这个文件是文件夹、小文件还是大文件来确定。另外常见的一个优化一样,如果是小文件,IndexFS就会直接将这些数据内联到元数据中。对于大的目录,IndexFS会使用动态分区的方式,分区的方法和GIGA+的一样(可以参看其论文),基本思路就是先将目录项映射到一个大的hash空间内,然后根据每个分区内的负载的情况在对其进行合适的分区。 处理基本的Key-Value映射之外,IndexFS将一部分更加常用的原属分离出来,保存到另外一个小的Table中,其它的数据保存到一个大的Table中。IndexFS将其称之为Column-Style Table。这个也是一个优化,主要的考虑就是文件的元数据并不少,但是里面常用的并不多,而且不同的文件操作常常用的是不同的元数据。 IndexFS在创建文件上面的一个优化是一次“攒”其多个文件创建的操作,然后一次性批量处理。在分区分裂时候的优化利用了SSTable的一些特点[1]。 另外,IndexFS针对这样的环境下面设计了对应的缓存策略。 0x02 评估 这里的具体的信息可以参看[1], LocoFS: A Loosely-Coupled Metadata Service for Distributed File Systems 0x10 引言 LocoFS是在IndexFS上面的一个优化操作。LocoFS发现IndexFS的设计能够获得的吞吐和原始的Key-Value操作相差很大。它的主要思路有,1. 目录的元数据和文件的元数据分开保存,2. 文件的不同的元数据访问模式存在很大的区别,这里LocoFS将文件元数据根据访问模式分开保存,3. 另外,前面的IndexFS没有提到rename之类的操作怎么优化,而LocoFS利用赋予一个UUID来优化这个问题, Evaluations... Read more!

  • 04 Mar 2019
    Exploiting Commutativity For Practical Fast Replication

    Exploiting Commutativity For Practical Fast Replication 0x00 引言 这篇Paper是NSDI ’19最有意思的一篇文章之一。以Paxos为代表的分布式一致性的算法,很大的一部分就是要处理网络的丢包和乱序的问题。而在对这样的算法优化的方向,有对算法工作流程进行优化的,比如Fast Paxos。另外就是从另外的方面着手,但是直接对网络丢包改进的几乎没有,一般都不能加上网络是可靠的。而多从顺序这里出发,比如NOPaxos,利用网络来对发出的消息进行定序。而这篇Paper中提出的思路是开发操作之间的可交换性,比如对于以Key-Value Store来说,如果一组的更新Key的操作,如果操作的都是不同的Key,那么只要这要操作最终都被执行了,系统最终的状态是和操作的顺序是没有关系的。通过让操作“乱序执行”,去除了1个RTT,提高系统的性能, In RAMCloud, CURP improved write latency by ∼2x (14 μs → 7.1 μs) and write throughput by 4x. Compared to unreplicated RAMCloud, CURP’s latency overhead for 3-way replication is just 1 μs (6.1 μs vs 7.1 μs). CURP... Read more!

  • 03 Mar 2019
    Key-Value Stores on SSD

    FlashKV: Accelerating KV Performance with Open-Channel SSDs 0x00 引言 这篇Paper是一篇关于在Open-Channel的SSD上面LevelDB优化的一篇文章。FlaskKV主要还是要解决这类存储系统在SSD上面运行的时候Log-on-Log的问题。另外一个就是利用好现在的一些SSD的并行性。FlashKV选择直接管理裸设备的方式,绕开操作系统的文件系统层和SSD固件上面的FTL层。在得知了硬件更多的细节的情况下,FlashKV引入Parallel Data Layout、Parallelism Compaction以及其它的一些方式提高了LevelDB在Open-Channel SSD上面的性能表现, ... FlashKV employs a parallel data layout to exploit the internal parallelism of the flash device, and optimizes the compaction, caching and I/O scheduling mechanisms specifically... improves system performance by 1.5× to 4.5× and decreases up... Read more!

  • 02 Mar 2019
    Key-Value Stores with mmap(2)

    Efficient Memory-Mapped I/O on Fast Storage Device 0x00 引言 这篇Paper是关于Memory-Mapped I/O 即使用mmap来实现IO操作的早快速存储设备上面的优化。mmio的一些特别的地方就是虚拟地址空间和io之间的关系。mmio中在需要的时候需要进行释放一些memory page的操作,or 将dirty page写入磁盘。这个和Database的Buffer Pool有一些类似。这篇Paper主要设计到这两个的操作的优化, Experimental results show that our optimized mmio has up to 7x better performance than the original mmio. We also compare our system to a system that has enough memory to keep all data in... Read more!

  • 01 Mar 2019
    The eXpress Data Path

    The eXpress Data Path: Fast Programmable Packet Processing in the Operating System Kernel 0x00 引言 eXpress Data Path(XDP)是Linux的一个新功能。现在一些类似于netmap、DPDK之类框架得到了大量的使用。类似于DPDK这样的bypass内核的方式在提高了性能的同时也带来的另外的一些问题,比如隔离性、安全机制,还有就是可移植性等。XDP就是直接在Linux内核中实现的一个可编程的包处理机制。XDP也提高了很高的性能,而且可以弥补之前bypass内核的一些系统存在的问题。现在Facebook已经有一个利用XDP做负载均衡的项目开源了,XDP之后的应用前景应该会很好, XDP achieves single-core packet processing performance as high as 24 million packets per second, and illustrate the flexibility of the programming model through three example use cases: layer-3 routing, inline DDoS protection... Read more!

  • 28 Feb 2019
    Kyber IO Scheduler of Linux

    Kyber IO Scheduler of Linux 0x00 引言 Kyber IO调度器是Linux上面针对高速存储设备设计的一个新的IO调度器,配和多队列的Block层使用。在Linux 4.12的时候和BFQ调度器一起成为内核中的一个可选项(emmmm,BFQ的系统复杂程度远高于这个Kyber)。另外,关于Kyber更方面都没有详细的信息,只能在一些[1]地方找到几句简单的介绍。这里完全是根据这几句话和内核中的源代码来推测它的实现,所以可能会存在不少的不准确的地方。 0x01 基本思路 Kyber调度器的基本思路是会为每一个的硬件的队列维护一个不同类型IO请求的队列,这些请求主要根据IO操作的方式来进行区分。Kyber按照读、同步写以及其它的(异步写等)将IO请求分为了3类。在Kyber的设计中,更加倾向于让读有些,这个策略也和其它的一些调度器的设计类似, 34 /* Scheduling domains. */ 35 enum { 36 KYBER_READ, 37 KYBER_SYNC_WRITE, 38 KYBER_OTHER, /* Async writes, discard, etc. */ 39 KYBER_NUM_DOMAINS, 40 }; Kyber在一个Kyber上下文中维护了关于这几类请求的队列。它通过限制每一个队列的长度来对在这里产生的请求的延迟进行控制。Kyber只有在这些队列里面的请求被处理了之后才会收集新的请求。这里限制的方式采用了基于Token的方式。另外这里的策略和一些交换机中控制内部缓冲区的思路相似。在下面的一些常量的定义中,可以看出对于读IO请求的偏好, 53 /* 54 * Initial device-wide depths for each scheduling domain. 55... Read more!

  • 27 Feb 2019
    Several Papers about Load Balancing

    Join-Idle-Queue: A Novel Load Balancing Algorithm for Dynamically Scalable Web Services 0x00 引言 Join-Idle-Queue算法很简单,设计地也很巧妙。JIQ面向的主要就是Web Servers的环境,不过应该也可能应用到其它的很多环境。它的一个基本思路是尽量减少Dispatcher(即负责分发任务的机器)和Processor(即处理任务的机器)之间的交互,JIQ通过另外的一个Idle Queue将两者之间的交互解耦。Processor在处理完任务之后将自身的信息添加到某些DIspatcher对应的Idle Queue中,表明自己可以接受新的任务,所以算法称之为Join-Idle-Queue。 0x01 算法 JIQ算法的基本示意如下图,Dispatches和后端的服务器之间通过中间的I-queues来通信。每一个Dispatchers会对应一个I-queues。JIQ的负责均衡主要有两个部分, Primary load balancing,Dispatcher在有任务需要分发的时候,询问其对应的I-queue,这个queue如果存在数据,则移除其中的第一个Processor。然后将其分发给对应的Processor。如果这个queue里面没有数据,则选择一个随机的Processor分发。在一个Processor处理完它的任务的或者是接近处理完之后,它将其它的信息添加到一个I-queue中。 Secondary load balancing,这里主要就是处理一个Processor变成空闲的之后,它如何选择I-queue的方法。这里就使用之前的一些方法,比如随机选择一个后者是挑选几个选择其中队列最短的。 0x02 评估 这里的具体信息可以参看[1], DistCache: Provable Load Balancing for Large-Scale Storage Systems with Distributed Caching 0x10 引言 DistCache是一种为存储系统设计的一种缓存方式。它的基本方式是使用一个两层的Cache结构,不同的层使用不同的Hash函数,用于将热点的数据尽可能的分散到不同机器上面, 0x11 基本思路 在之前的一些解决方案中,常见的两种方式是Cache分区和Cache复制。对于前者的缺点就是处理热点Key的时候不能很好地分散这些请求,而后者的缺点在于Cache一致性的处理比较困难,整体系统的复杂度也更加大。而DistCache则采用了上图中的设计,在不同的层使用不同的Hash函数尽可能的去分开热点数据的查询。另外,在选择那个缓存节点处理查询的时候,就采用了简单有效的 power-of-two-choices的方法。就是随机找两个选择其中load更加小的。另外文中还有一大堆对这个方法具体情况的分析[2]。 Paper中实现了类似于NetCache的一个基于交换机的DistCache的一个实现。上面架构是在一个two-layer leaf-spine架构中的数据中心网络中的一个实现。在这个实现中,会有一个Cache Controller管理处理缓存交换机、处理设备故障。Cache交换机负责缓存热点数据,同时负责分发它的load的信息,这个load的状态会用于如何路由这个查询。于客户端相连的ToR交换机负责处理查询路由的问题(使用power-of-two-choices的测量)。后端的存储节点可以就是一个一般的KVS。下图是一个处理流程的例子。S6与客户端相连,S6使用power-of-two-choices选择了S1... Read more!

  • 26 Feb 2019
    GearDB and SLM-DB

    GearDB: A GC-free Key-Value Store on HM-SMR Drives with Gear Compaction 0x00 引言 这篇Paper是关于在SMR(叠瓦是磁记录)磁盘上面的优化。SMR磁盘的特点虽然容量更大,但是几乎没有什么随机写的性能,个人用户非常不推荐购买这类磁盘。之前FAST上面有篇Paper就是消除ext4文件系统上面的一个更新文件元数据的随机写操作来提高性能。而GearDB则提出针对LSM-Tree在SMR的环境下面的几个优化策略, We implement and evaluate GearDB with LevelDB on a real HM-SMR drive. Our extensive experiments have shown that GearDB achieves both good performance and space efficiency, i.e., on average 1.71× faster than LevelDB in random write... Read more!

  • 25 Feb 2019
    Write-Optimized Dynamic Hashing, and uDepot

    Write-Optimized Dynamic Hashing for Persistent Memory 0x00 引言 这篇Paper中的idea可以说是旧idea在新的环境中的一个应用。在NVM上提出了一种针对这个环境优化的Cacheline-Conscious Extendible Hashing(CCEH),它的主要的对比对象是之前的Path Hashing和Level Hashing, CCEH effectively adapts its size as needed while guaranteeing failure-atomicity and that the tail latency of CCEH is up to 3.4× and 8× shorter than that of the state-of-the-art Level Hashing and Path Hashing, respectively. 0x01 基本思路... Read more!

  • 24 Feb 2019
    Rocksteady and Arachne, Components of RAMCloud

    Rocksteady: Fast Migration for Low-latency In-memory Storage 0x00 引言 RAMCloud是有名的一个内存存储系统。围绕着RAMCloud的论文有很多。Rocksteady是关于如何实现RAMCloud快速数据迁移的,Arachne是使用在RAMCloud上的一个用户空间的线程库。Rocksteady是一种Zephyr风格的live migration方式,在RAMCloud的实现中,可以实现758MB/s的迁移速率, Rocksteady migrates 758 MB/s between servers under high load while maintaining a median and 99.9th percentile latency of less than 40 and 250 μs, respectively, for concurrent operations without pauses, downtime, or risk to durability (compared to 6 and... Read more!

  • 22 Feb 2019
    Buffer Pool of Database

    BP-Wrapper: A System Framework Making Any Replacement Algorithms (Almost) Lock Contention Free 0x00 基本思路 这篇Paper的思路还是比较简单的。在java著名的本地缓存库caffeine中也得到了应用。这里不是提出一种新的缓存替换算法,而是在Buffer Pool替换Page的操作中如何降低锁冲突。一些数据的系统中的思路是将其拆分为多个Buffer Pool实例,这里的思路是引入Queue,将需要对Buffer Pool内部数据结构更新的操作先累积在线程局部的FIFO Queue中,然后再处理啊。通过这样的方式实现操作的批量处理,加上预取的机制,来优化性能, In BP-Wrapper, we use batching and prefetching techniques to reduce lock contention and to retain high hit ratio. The implementation of BP-Wrapper in PostgreSQL version 8.2 adds only about 300 lines... Read more!

  • 20 Feb 2019
    Managing Non-Volatile&Large-Scale Persisten Memory in Database Systems

    Memory Management Techniques for Large-Scale Persistent-Main-Memory Systems 0x00 引言 这篇Paper是关于SAP在其数据库系统中为Storage Class Memory (SCM),即一种非易失性内存,设计的内存分配器。这里设计的PAllocator是目前少数在实际系统中使用为非易失性内存分配器。这SCM的内存分配器设计中,主要要解决这样的几个问题, 数据一致性,这个原因在很多的NVMM系统中都是要考虑的问题,主要的原因是可能最新的数据还没有达到SCM中,还只会存在CPU的缓存中,如果这个时候发生系统Crash,就会导致系统一致性的问题。在interl的CPU中,也提交了如CLFLUSH这样的之类来解决这个问题。 Data recovery,数据恢复是一般的内存分配器不用考虑的事情,很显然一般的DRAM在断电之后数据全部丢失,不存在Data recovery的问题。但是SCM作为非易失性的内存,则希望系统重启之后还可以恢复到重启之前的状态。 Persistent内存泄露,SCM持久化保存数据的另外一个问题是可能导致永久性的内存泄露。 Partial writes,不如一般的块存储设置,这些块存储设备一般可以支持一个block的原子写入。而SCM只支持8byte的原子写入or读取。如果需要原子写入超过了8byte的数据,则可能存在不会写入的问题。 内存碎片,Persistent内存里面的数据保存时间一般都会超过DRAM中数据保存的时间,这样的情况下吗其内存碎片的问题会变得更加严重。地址空间碎片。目前Linux 支持的用户空间的最大空间为128TB,但是可能无法满足之后要求。但是这里由于Linux新版本支持了5级的页表。这个问题问题不大。 0x01 基本设计 首先,PAllocator基于文件系统的DAX,即直接范围存储介质的空间。这样这些SCM实际上还会对应到文件。PAllocator还有这样的一些设计:1. 使用多个文件而不是单个,方便增加和减少资源。但是为了避免使用太多的问题,这里使用大文件来限制文件的数量。2. 对于small、big和huge等不同尺寸的内存块分配,使用不同的分配策略。3. 不着急释放空闲的文件,用于加速可能的未来的分配,这个策略在一些通用的内存分配器上面也使用了。4. 不实用线程局部资源池的方式,而是每个CPU物理核心一个allocator的方式。还有另外一些设计等等[1]。PAllocator不是一个通用的内存分配器,由于SCM实际上还是文件系统管理的,这里使用一种persistent pointers来寻址。PAllocator也使用下面的两个基本class,一个PPtrBase表示一个没有类型信息的地址信息,PPtr则会带有类型信息。 class alignas(16) PPtrBase { uint64_t fileID; ptrdiff_t offset; void* toPtrBase(); // Swizzling function }; template<typename T> class PPtr : PPtrBase... Read more!

  • 19 Feb 2019
    Reducing DRAM Footprint with NVM in Facebook

    Reducing DRAM Footprint with NVM in Facebook 0x00 引言 这篇Paper是关于Facebook在自己的数据库中使用NVM的做法,一个叫做MyNVM的系统。虽然整体上和现在很多的在NVM上面的数据库的研究有很大的不同,Facebook这里主要利用NVM来减少数据库中DRAM的使用。基本的思路就是引入部分的Buffer Pool的数据放到NVM上面,形成了一个两层的Buffer Pool的设计。 ... Our implementation reduces the size of the DRAM cache from 96 GB to 16 GB, and incurs a negligible impact on latency and queries-per-second compared to MyRocks. Finally, to the best of our knowledge, this is the... Read more!

  • 17 Feb 2019
    Scalability of Write-ahead Logging on Multicore and Multisocket Hardware

    ##Scalability of Write-ahead Logging on Multicore and Multisocket Hardware 0x00 引言 这篇Paper总结了不少Write-ahead Logging设计上面的优化思路。一般数据的WAL设计中,日志会按序写入到日志中,这样的操作中。这样的设计主要有几点影响性能的地方,如下图所示,1. IO相关的延迟,为了保证日志持久化带来的延迟,2. Log处理中锁带来的开销,写入日志数据的时候为了保存有序和日志中没有空洞使用了锁,由此带来的开销,3. 在等待IO完成的时候,工作线程会让出CPU,从而导致线程切换,由此带来的开销,4. Log-induced锁竞争带来的开销,为了提交一个事务,事务会一致持有锁到操作完成,包括日志持久化,由此带来的开销。这篇Paper在这合理提出多种策略来有些这些问题。 0x01 Early Lock Release Early Lock Release的思路看起来挺简单的,但是在具体的数据库实现的时候会是一个很麻烦的事情。Early Lock Release的基本思路是在一个事务提交之前,就将其持有的锁释放。不过在这个事务提交之前,其执行的结果不能返回给客户端。另外,依赖于这个事务产生数据的其它事务会对这个事务形成一个依赖关系,同样地,在一个事务依赖的事务提交之前,这个事务也不能提交。在严格按序保存日志的系统中,实现这个简单一些,因为后面的事务的日志肯定不会早于前面事务的日志持久化。总而言之,Early Lock Release要满足两个条件, 每个依赖于其它事务的事务的日志必须不早于其依赖的事务的日志持久化; 一个被依赖的事务abort了,依赖于这个事务的其它事务也必须abort。 Early Lock Release带来的性能影响可以参看[1]. 0x02 Flush Pipelining 由于持久化日志带来的延迟主要体现在两个方面,1. 实际等待IO完成的时间,2. 线程等待和解除等待的时候上下文切换带来的开销。前面的Early Lock Release是一种优化第一种延迟的方式,其它的一些方式比如组提交也是优化这些延迟的一种方式。Flush Pipelining是一种已经在一些MySQL版本中采用的优化方式,其基本思路就是工作线程在等待一个事务产生的日志持久化的时候,工作线程可以去继续执行其它的事务。这样的话,工作线程可以一直保持忙碌的状态,减少上下文切换。其基本的支持方式如下, 工作线程在发出IO请求的时候,不会等待起完成,当然也不能立即返回给客户端结果。工作线程这个时候就可以去执行其它的事务了。 IO线程在受到工作线程的IO请求的时候,负责将相关的日志数据持久化。这里就可以使用一些组提交之类的优化方式。在IO操作完成的时候,通知对应的工作线程。工作线程在收到通知之后,继续处理这个事务接下来的事务,完成最终的提交,返回结果给客户端。 在提交了IO请求的事务abort之后,事务回滚也必须等到日志被持久化。 Flush Pipelining带来的性能影响可以参看[1]. 0x03 Scalable Log... Read more!

  • 14 Feb 2019
    Database Live Migration, Zephyr and “Cut Me Some Slack”

    Zephyr: Live Migration in Shared Nothing Databases for Elastic Cloud Platforms 0x00 引言 Zephyr是数据库Live Migration的一个经典的设计。Zephyr的基本思路就是从集合on-demand主动拉取数据和异步数据推送相结合的方式来实现Live Migration。Zephyr在实现数据Live迁移的同时,降低事务abort的概率,最小化数据迁移的负载,同时保证数库ACID的要求, ... We outline a prototype implementation .. . Zephyr’s efficiency is evident from the few tens of failed operations, 10-20% change in average transaction latency, minimal messaging, and no overhead during normal operation when... Read more!

  • 13 Feb 2019
    Several Papers about KVS

    Scaling Memcached at Facebook 0x00 引言 这篇Paper是很值得读的一篇关于KVS的Paper。它的关注点不是KVS具体的实现,而是Memcached在Facebook中的应用。主要设计到Facebook关于通信协议、负载优化、复制以及一致性方面的内容,这些可能比具体的KVS的技术更加有用, ... Facebook leverages memcached as a building block to construct and scale a distributed key-value store that supports the world’s largest social network. Our system handles billions of requests per second and holds trillions of items to deliver a rich experience for over... Read more!

  • 12 Feb 2019
    Variants of LSM-Tree, SifrDB, cLSM and TRIAD

    SifrDB: A Unified Solution for Write-Optimized Key-Value Stores in Large Datacenter 0x00 引言 这篇是很有意思的一篇Paper。SifrDB本质上还是一种在LSM-tree的优化,优化的重点在Compaction的方式上面。之前在LSM-tree上面存在多种的Compaction的方式,最常见的方式是Level-Style的方式,在LelvelDB和RocksDB中使用,这种方式的优化点事读取性能相对好一些。这种方式下面LSM-tree的每层的SST文件彼此Key不重叠,而对应的Tier的方式在每层的SST文件的Key事可能重叠的,Tier的方式写入性能更好一些,而读取性能更差一些,因为在一层读取的时候,每个SST文件都可能存在想要的Key。而SifrDB这里时提出了一种新的Compaction的思路。 0x01 基本思路 这里将Level-Style的方式称之为Tree-Model,而将Tier的方式称之为Forest-Model。Forst Model中,一个Key可能存在这一层的任意的SST文件中,这样的缺点就是很低的读取的性能。LSM-tree的设计本身就是针对写优化的一种,Forest-Model的设计更是加剧了读性能的恶化。针对这个缺点,这里的一种优化如PebblesDB一样,PebblesDB的优化实际上就是避免了一个Key可以存在一层的任意的SST文件中,而是限制在其中的一个范围内。这里的SifrDB实际上也是一种优化Tier Compaction方式的思路,只是优化的思路和前面的方式有些区别。 在SifrDB中Compaction思路可以从上图中看出来,可以看出来SifrDB归类到Forest-Model下面。这里将其称之为Split Forest Model。PebblesDB在这里被称之为Partitioned Forest Model。这里可以看作为在Forst Model中一层的一个部分有重新被划分了,方便更快的速度查找。在SifrDB中,每个Tree由一组没有重叠的固定大小的subtree组成,subtree的元数据信息保存到另外的一个全局的索引中。这样实际上就是组成了一个forest,也就是为什么称之为Foest Model的原因,PebblesDB和SifrDB的区别类似于一个事冲纵向上划分,而SifrDB是从横向上划分的。在这样的Model下面,Compaction操作思路如下图, 除了基本的思路之外,这里还提出了其它的一些优化思路, early-cleaning优化思路,在Compaction的时候,常见的优化方式是在一个Compaction完成的时候才将原来的数据删除。这里的一个优化的思路是如何实现在一个数据Merge到新的Tree的时候,就马上将原来的数据删除。这样可以减少一些存储空间的消耗。这里的方式有带来两个问题要解决,1. 这样的方式在Compaction过程中的时候Crash了如何恢复,2. 这个过程中读取操作的时候如何处理读取的数据,因为一个Tree的数据可能位于新旧不同的位置。 上面的两个问题中,对于第一个问题,这里使用解决方式是Compaction Journal方式。在Merge操作的时候,会周期性地删除以及合并的数据。这个进度的信息会被写入到Compaction Journal中,在Crash恢复的时候可以根据这些信息恢复,根据Crash之前的记录的进度继续进行Compaction的操作, In the recovery process, SifrDB reads the latest merge state information from the compaction journal and continues... Read more!

  • 10 Feb 2019
    Several Papers about LSM-Tree

    Accordion: Better Memory Organization for LSM Key-Value Stores 0x00 基本思路 Accordion对LSM-Tree的改进思路与前面的[2]的思路很相似,也是将内存中主要的数据结构分为可变的部分和不可变的部分,可变的部分和一般的LSM-Tree的实现没有什么不同。在一般的LSM-Tree中,一个Memtable转变为immutable的时候不会对这个memtable的结构做什么样的变化,而在Accordion中,会将其转变为一种更加节省内存的结构,称之为flat segemnt。一个Active Segment在达到一定的大小之后转变为Flat Segment,这个操作称之为in-memory flush。内存中的Flat Segment也会做合并的操作,称之为in-memory compaction。这个思路应用到Rocksdb上面也可能是一个很好的优化。 这个的in-memory的合并操作也和常见的LSM-Tree Compaction操作一样,Basic操作不会去除冗余的数据,比如一个Key的旧的版本的数据,Overhead比较低,而Eager合并则会去除器中的冗余的数据,Overhead比较高。 Accordion使用自适应的方法,会根据系统的情况选择合适的合并方式。 Splaying LSM-Tree 0x10 基本思路 Splaying LSM-Tree的基本思路是将下层的Key-Value通过一定机制可以转移到上层中来,处理的问题是一个下层中的Key-Value变得比较Hot,这个时候处理这个Key-Value旧不如将其直接放入到内存中的L0中。可以通过类似Count Sketch的数据结构统计Key的热度,在合适的时候重新执行统计操作即可。 0x11 另外一个 ​ Splaying LSM-Tree的思路可以很简单地拓展一下,当一个memtable被flush到磁盘上面的时候,其中如果存在比较Hot的Key-Value,这个操作是对处理这个Key-Value不利的。这个时候旧可以将这些Key-Value Pairs不要Flush到磁盘上去,而是继续保留到memtable中。这里以及上面Splaying的做法也会带来一些Overehad,只在一些情况下有比较好的效果。 SlimDB: A Space-Efficient Key-Value Storage Engine For Semi-Sorted Data 0x20 引言 SlimDB也是基于LSM-Tree的一个设计,它的设计有两个特点: 数据在Block中是不完全排序的,结合使用ECT压缩数据,还结合使用Three-level Block索引; SlimDB only needs... Read more!

  • 03 Feb 2019
    Clokc-SI and Write-Snapshot Isolation

    Clock-SI: Snapshot Isolation for Partitioned Data Stores Using Loosely Synchronized Clocks 0x00 引言 Clock-SI是为分区数据库设计的一种Snapshot Isolation的方法。Clock-SI作为一个非中心话的SI算法,主要要解决的事在分布式的环境下面时钟偏斜带来的问题,主要体现它的读协议和提交协议上面, We show that Clock-SI has significant performance advantages. In particular, for short read-only transactions, Clock-SI improves latency and throughput by up to 50% over conventional SI. This performance improvement comes with higher availability as well.... Read more!

  • 28 Jan 2019
    Overload Control for Scaling WeChat Microservices

    Overload Control for Scaling WeChat Microservices 0x00 引言 这篇Paper是微信的关于其后台过载控制系统。在微信这样复制的系统,错综复杂的系统依赖关系、难以准确估计的动态的实际负载水平。DAGOR系统使得微信的过载控制和服务逻辑分开。这个系统在微信后台中已经运行了5年, ... It manages overload at the microservice granule such that each microservice monitors its load status in real time and triggers load shedding in a collaborative manner among its relevant services when overload is detected. DAGOR has been used in the... Read more!

  • 27 Jan 2019
    Building Consistent Transactions with Inconsistent Replication

    Building Consistent Transactions with Inconsistent Replication 0x00 引言 分布式系统中,多副本的策略是一个实现高可用的基本的策略。一旦有副本,就会设计到数据一致性的问题。常见的解决方式有例如主从复制的方式,比如MySQL、Redis中的主从复制。另外的一些复杂一些的例如Paxos、Raft等,也在很多系统中采用。这篇Paper提出了一种在Inconsistent Replication上构建Consistent Transaction系统的方式。基本的思路是提出了一种Inconsistent Replication(IR)协议,这种协议可以满足1. Fault tolerance,2. Visibility,3. Consensus results等的基本保障。在IR协议的基础之上,还需要使用方解决一些执行冲突的策略,实现最终的分布式系统。Paper中构建了一个KVS原型tapir-kv, Our experiments found that tapir-kv had: (1) 50% lower commit latency, (2) more than 3× better throughput compared to systems using conventional transaction protocols, including an implementation of Spanner’s transaction protocol, and (3)... Read more!

  • 26 Jan 2019
    Canopy -- An End-to-End Performance Tracing And Analysis System

    Canopy: An End-to-End Performance Tracing And Analysis System 0x00 引言 Canopy是Facebook使用的一个分布式追踪的基础设施。这篇Paper发表在SOSP ‘17上面。在前面的OSDI ‘14上面,Facebook也发表了The Mystery Machine的论文,也是类似的分布式追踪系统。这个Canopy应该就是The Mystery Machine系统的继续演进,Canopy实现了更加丰富强大的功能, Canopy addresses three challenges we have encountered in scaling performance analysis: supporting the range of execution and performance models used by different components of the Facebook stack; supporting interactive ad-hoc analysis of performance... Read more!

  • 24 Jan 2019
    Calvin and CalvinFS

    Calvin: Fast Distributed Transactions for Partitioned Database Systems 0x00 引言 Calvin是分布式数据库的一种设计,发表的年份和Spanner的相同。Calcin也有一个开源的实现。Calvin和Spanner是一种完全不同的设计。Calvin是一种的确定性的数据库(deterministic database)。在传统的数据库实现中,简单地复制事务的输入并不能保证不同的副本最终达到一个完全一致的状态(可能由于操作系统、网络以及硬件等带来的不确定性)。而类似Calvin的数据库通过在并发控制中达成一个一致的请求锁的顺序,则可以保证副本之间达到一个一致的状态, ... if the concur- rency control layer of the database is modified to acquire locks in the order of the agreed upon transactional input (and several other minor modifications to the database are made ), all replicas can... Read more!

  • 23 Jan 2019
    FaSST -- Fast, Scalable and Simple Distributed Transactions

    FaSST: Fast, Scalable and Simple Distributed Transactions with Two-sided (RDMA) Datagram RPCs 0x00 引言 FaSST也是一个利用RDMA实现的支持In-Memory事务的系统。FaSST的对比的对象比前面额度DrTM,与DrTM使用One-sided的RDMA操作加HTM实现的不同,FaSST认为,在类似这样的系统中,使用Two-sided Datagram来实现其中的一些操作能够获得更加好的性能, ... FaSST outperforms FaRM on the TATP benchmark by almost 2x while using close to half the hardware resources, and it outperforms DrTM+R on the SmallBank benchmark by around 1.7x without making data locality... Read more!

  • 22 Jan 2019
    Several Papers about RDMA KVS

    Using One-Sided RDMA Reads to Build a Fast, CPU-Efficient Key-Value Store 0x00 引言 Pilaf是一个基于RDMA的KVS,它的基本的设计思路就是get操作使用bypass的方式,直接访问serber的内存,而对于put操作,则交给server来处理。由于get操作和put操作实际上是不同的机器在处理,这里就还要处理get数据的时候数据被修改的问题, Our experiments show that Pilaf achieves low latency and high throughput while consuming few CPU resources. Specifically, Pilaf can surpass 1.3 million ops/sec (90% gets) using a single CPU core compared with 55K for Memcached and... Read more!

  • 21 Jan 2019
    Fast In-Memory Transaction Processing Using RDMA and HTM

    Fast In-Memory Transaction Processing Using RDMA and HTM 0x00 引言 DrTM是上海交大开发的一个基于RDMA和HTM的一个支持分布式内存事务的系统(不过由于DrTM使用的是RDMA,这里的发布和Calvin的分布可能存在比较大的差别,虽然DrTM在这篇paper中性能在和Calvin对比)。这里的事务只的是内存中的一种类型的事务,和一般数据库中事务的概念还是存在一些差别的。 ... Evaluation using typical OLTP workloads including TPC-C and SmallBank show that DrTM scales well on a 6-node cluster and achieves over 5.52 and 138 million transactions per second for TPC-C and Small- Bank respectively. This number outperforms a... Read more!

  • 20 Jan 2019
    Sparrow -- Distributed, Low Latency Scheduling

    Sparrow: Distributed, Low Latency Scheduling 0x00 引言 Sparrow的一个最大的特点就是她是一个分布式的集群调度器,采用了去中心化的设计。Sparrow的目标是实现毫秒级的调度延迟。Sparrow架构和Borg这类的中心化的调度器差别是很大的,它里面的Scheduler会发布在多个集群中的节点上面,独立执行调度任务,关于调度器的架构,Firmament的作者有一篇很好的介绍的文章。这样的设计有可能操作一些问题,比如调度冲突的问题等等。Sparrow解决分布式调度器存在的这些问题主要采用的是基于取样的方法以及延迟绑定技术。另外,Sparrow一个prototype在Github上面有开源,总体上来说这个开源的实现还是比较简单的, We demonstrate that a decentralized, randomized sampling approach provides near-optimal performance while avoiding the throughput and availability limitations of a centralized design. We implement and deploy our scheduler, Sparrow, on a 110-machine cluster and demonstrate that Sparrow performs within 12% of an... Read more!

  • 18 Jan 2019
    Firmament -- Fast, Centralized Cluster Scheduling at Scale

    Firmament: Fast, Centralized Cluster Scheduling at Scale 0x00 引言 Firmament也是一个集群调度器的设计,FIrmament的基本思路是对集群的情况进行图建模。在这个图上使用基于最小费用最大流的策略来计算调度方案。中心化的调度器一般能够取得更加好的资源利用率,不过代价就是调度的延迟一般也会相对大一些。基于最小费用最大流的调度思想在SOSP ‘09上面就有一篇Paper,不过这篇SOSP Paper中的实现延迟比较高。这篇Paper提出的Firmament调度器在基本的最小费用最大流的基础之上做了不少的改进,实现了比Quincy高几十倍性能(延迟效果)的效果, ... Experiments with a Google workload trace from a 12,500-machine cluster show that Firmament improves placement latency by 20× over Quincy [22], a prior centralized scheduler using the same MCMF optimization. Moreover, even though Firmament is centralized, it... Read more!

  • 16 Jan 2019
    Page-level Flash Translation Layers

    DFTL: A Flash Translation Layer Employing Demand-based Selective Caching of Page-level Address Mappings 0x00 引言 前面看过的一些关于FTL的Paper都是Hybrid模式。基本的思路就是使用Block和Page两个层面的映射,这么做的原因是随着SSD容量的不断增长,FTL占用的空越来越多,Block/Page的设计就类似于Page Table的多层的设计。而Hybrif的方法也有一些缺点。一般认为Page-Level的能够实现更加好的性能,容易区分冷热数据以及没有Merge操作。Demand-Based FTL (DFTL) 就是这样的一个Pagel-Level的FTL的设计, For example, a predominantly random-write dominant I/O trace from an OLTP application running at a large financial institution shows a 78% improvement in average response time (due to a 3-fold... Read more!

  • 13 Jan 2019
    Ananta, Duet and SilkRoad Load Balancer

    Ananta: Cloud Scale Load Balancing 0x00 引言 Ananta是一个Layer-4负载均衡器的设计, ... Multiple instances of Ananta have been deployed in the Windows Azure public cloud with combined bandwidth capacity exceeding 1Tbps. It is serving traffic needs of a diverse set of tenants, including the blob, table and relational storage services. With its scale-out... Read more!

  • 12 Jan 2019
    Large-Scale Cluster Management at Google with Borg

    Large-Scale Cluster Management at Google with Borg 0x00 引言 Google的Borg是很有名的集群调度系统。Borg在Google内部应用应该是有很长的一段时间了,而这篇Paper发表在2015年。Borg虽然是一个很著名的集群调度系统,本身也是十分出色,但是这篇文章看起是平平无奇的,Borg中估计还有很多关键的东西没有写出来,这里只是一个总体上面的表述而已, It supports high-availability applications with runtime features that minimize fault-recovery time, and scheduling policies that reduce the probability of correlated failures. Borg simplifies life for its users by offering a declarative job specification language, name service integration, real-time job monitoring,... Read more!

  • 11 Jan 2019
    CONGA, Presto, HULA and DRIL Load Balancer

    CONGA: Distributed Congestion-Aware Load Balancing for Datacenters 0x00 引言 CONGA是数据中心内的一个负载均衡方法。CONGA基于去中心化的设计,也不基于主机的一些操作,而是完全在网络中完成。CONGA任务基于每个流后者是每个数据包都存在不少的问题,前者灵活性太差,后者可能导致一些包重拍序二降低传输的性能,因此CONGA使用了基于Flowlet的方式, ... In testbed experiments, CONGA has 5× better flow completion times than ECMP even with a single link failure and achieves 2–8× better throughput than MPTCP in Incast scenarios. 0x01 基本思路 CONGA的设计思路体现在下面的这张图中, 使用分布式的架构师CONGA任务中心化的设计难以快速响应数据中心网络内流量的快速变化,另外数据中心网络的拓扑是很规整的,分布式的决策就能获取非常好的效果。 In-Network。在使用了分布式的架构后,CONGA选择在网络中实现这个负载均衡的逻辑,CONGA认为网络中心内主机系统的多样性给在Host上面实现带来不便。 Global Congestion Awareness,意识到全局的拥塞信息能够带来更好的负载均衡的效果。只利用局部的信息,加上局部贪心的算法在一些情况下做作出不合理的决策。 Leaf-to-Leaf Feedback,Lead-to-Leaf指的就是一个Leaf的交换机另外一个交换机反馈网络的一些信息。 Flowlet的设计,是在Flow和Packet中间的一个折中的设计,能够避免一些包重拍序的情况下能够比较好的灵活性。... Read more!

  • 07 Jan 2019
    Count Quotient Filter, Persistent Bloom Filter and Morton Filters

    A General-Purpose Counting Filter: Making Every Bit Count 0x00 引言 这篇Paper描述了一种Quotient Filter的优化思路。Quotient Filter是一种功能类似于Bloom Filter但是思路存在很大差别的Approximate Membership Query (AMQ)数据结构。Quotient Filter的基本思路如下, 在Quotient Filter中,使用一个hash函数的计算一个元素一个hash值,使用这个值的一部分的bits定位一个slot,剩下的部分称之为商,保存到这个slot中。slot中除了这个商之外,还保存另外三个bit: 1. is occupied,如果这个slot就是保存的商根据hash值应该保存的位置时设置为1。因为在这里slot中保存的值可能被移动。2. is_continuation,添加元素的时候如果slot已经被占用,则根据商的大小决定移动元素,形成从小到大的余数排列,这个bit用来记录这些记录是否连续。这些元素称之为run or cluster。3. slot中保存的商时被移动过来的设置为1。 在查询的时候根据hash值找到对应的slot,如果这个slot不是对应的元素,且存在run/cluster,则往后查找,直到达到run/cluster末尾 or 商更大。Quotient Filter类似于linear probing的hash。其优点是缓存友好性优于Bloom Filter,但是可能在占用率高的时候性能比较差。 0x01 基本思路 Rank-And-Select-Based是Succinct数据结构中使用的一种策略,这里提出了Rank-And-Select-Based Quotient Filter使用了类似的策略来优化Quotient Filter。其基本的思路如下,这里不是使用3个标记为,而是两个,第一个occupieds标记是否有一个值定位到了这里,另外一个为runneds,用来标记一个run的结尾。这里定义了两个运算,第一个Rank(B, i)返回bit vector B中到i位置为止的bit为1的数量,Select(B, i)返回第i个bit为1的index。这样在其中查找一个元素是否存在可以用如下的方式:第一个先查询occupieds是否存在,没有就是返回0。存在则根据RANK定位在slot中能够到达的最大的位置,用 t ← RANK(Q.occupieds, b) 、 l ←... Read more!

  • 06 Jan 2019
    Several Congestion Control Algorithms

    一些TCP拥塞控制算法的基本思路 TCP Vegas: New Techniques for Congestion Detection and Avoidance 0x00 基本思路 TCP Vegas也是一个很有名的TCP拥塞控制的算法。它和常见的NewReno,Cubic之类的基于丢包的算法不同,Vegas是一种基于延迟的算法。Vegas的一个主要的缺点就是在和这些基于丢包的算法一起运行的时候,它显得太过于“君子”,往往比这些算法提前推出窗口增长的阶段。 在Vegas中,有下面几个基本的概念,1. BaseRTT,Vegas算法中认为链路上面的基本的RTT时间,一般使用测量到的最小值(考虑到链路随时可能变化),这里可能选选取一段时间内的最小值。然后根据当前的WindowSize,计算出Expected = WindowSize / BaseRTT,Expected即目标的吞吐。 另外,Vegas会测量Actual,即某一个时间的实际的吞吐的值。设Diff = Expected - Actual。如果有 Actual > Expected,则表明Vegas需要对BaseRTT进行更新。Diff这里只会是不小于0的数。另外,Vegas定义了两个值a、b,其中a < b。如果 Diff < a,则表明实际的吞吐和期望的差不多,则在下一个RTT中增加窗口大小。如何Diff > b,则表明实际的明显小于期望,则认为可以出现了拥塞,则尝试减小窗口的大小。在这两个值中间的时候保持当前的窗口大小。 另外Vegas也使用了在其它的一些算法中使用的快速重传的策略。 BIC Congestion Control Algorithm 0x10 基本思路 BIC算法是一种为长肥网络优化的TCP拥塞控制的算法。它处于这样的一个基本思路:在慢启动之后,之前的算法是进入一个加性增的过程(AIMD中的AI)。这个过程时间上就是在慢启动中最大的窗口和慢启动结束之后的窗口大小之间的一个搜索的过程。BIC的思路就是在这里使用二分查找的方法。由于长肥网络下面加性增的过程可能很长,BIC的这个思路能够让发送窗口的大小更加块地拟合到实际需要的大小。下面的伪代码是维基百科上面对BIC简单地描述, //Smax: the maximum increment //Smin: the minimum... Read more!

  • 05 Jan 2019
    Flexible Paxos and Paxos Quorum Leases

    Flexible Paxos: Quorum Intersection Revisited 0x00 引言 再来看一篇关于Paxos变体的论文,这篇讲的是Flexible Paxos这样的一个变体。与前面的EPaxos侧重点在消除稳定/指定的Leader/Master的设计不同,Flexible Paxos(FPaxos)的问题聚焦在了Quorum这个问题上面。基本的Paxos算法总结为, Phase 1 - Prepare & Promise * i. A proposer selects a unique proposal number p and sends prepare(p) to the acceptors. * ii. Each acceptor receives prepare(p). If p is the highest proposal number promised, then p is written... Read more!

  • 04 Jan 2019
    Copa -- Practical Delay-Based Congestion Control for the Internet

    Copa: Practical Delay-Based Congestion Control for the Internet 0x00 引言 Copa也是一个基于delay的拥塞控制的算法,它有3个基本的idea, 在 Markovian(马尔可夫) packet arrival 模型下面,最优化的吞吐和延迟的目标发送速率为1 / (δ*dq),这里的dq为测量到的排队延迟; Copa根据目标发送速率来调整窗口,即使在系统中存在诸多不稳定的因素下,它也能快速收敛到一个正确的公平的速率; 第3个idea使用用来解决基于delay的算法在基于丢包的算法目前太“君子”的问题,比如Vegas就存在这个问题。Copa的解决方法是根据delay的变化来对参数δ进行additive-increase/multiplicative decrease(AIMD)的变化; Copa能和Cubic在一个环境下比较好的共同存在,这个比BBR、PCC做的好(也应该包括Vegas)。 0x01 基本思路 Copa这里的目标发送速率是1 / (δ*dq),dq的含义如前面所言,这样1 / δ的含义就是MTU尺寸包的量。Copa中cwnd的含义和一般的含义相同。在每个ACK达到的时候,发送方使用λ = cwnd/RTTstanding来估计目前的发送速率,这里的RTTstanding是在最近的一个时间窗口 τ(τ=srtt/2, srtt就是rtt的估计,和一般的方法一致,选择这样一个时间段内是为了反之ACK compression或者是网络抖动带来的影响)内观察到的最小的值。Copa使用dq =RTTstanding−RTTmin来计算dq,RTTmin是在一段比较长时间内观察到的最小值(在Copa中使用了一个小于10s的值)。如何利用前面计算目标速率的方式,在超过了目标速率之后,就减少cwnd,反之增加cwnd。Copa发送方的在ACK达到之后的处理逻辑, 更新dq的计算方法更新dq的值,同时更新srtt的估计; 根据目标速率的计算公式计算出此时的目标速率λt; 如果当前使用的目标速率λ = cwnd/RTTstanding小于等于λt,更新cwnd的值为cwnd = cwnd + v/(δ*cwnd),这里的v是一个速率参数。反之为cwnd = cwnd - v/(δ*cwnd),也就是说一次变化的delta为v/(δ*cwnd); 参数v在开始的时候初始化为1,这里的思路和前面的PCC,PCC-Vivace的思路相似。都是加速收敛的方法,在一个发送上面多走了几次,就加大v的值(每次double),方向变化了重新设置为1。在开始的时候要特殊处理,只有在保持了同一方向的变化3RTTs时才应用这个方法, However,... Read more!

  • 03 Jan 2019
    PCC and PCC-Vivace Congestion Control Algorithms

    PCC: Re-architecting Congestion Control for Consistent High Performance 0x00 引言 PCC发表在BBR算法之前,虽然两者之间存在着很多的差异,但也在很多方面的思路是类似的。一个基本的想法就是不能简单地认为丢包了就是一定发生了阻塞。BBR使用的方法是测量线路这个“管子”的容量来实现拥塞控制。而PCC则是通过改变发送速率之后出现的时间来判断线路目前的情况。Paper中的PCC算法的数据很不错,而且能够适应的环境非常广泛,这个也是一个很大的优点, PCC achieves consistent high performance and significantly beats specially engineered TCPs in various network environments: (a.) in the wild on the global commercial Internet (often more than 10× the throughput of TCP CUBIC); (b.) inter-data center networks (5.23× vs.... Read more!

  • 02 Jan 2019
    Restructuring Endpoint Congestion Control

    Restructuring Endpoint Congestion Control 0x00 引言 这也是一篇比较有意思的Paper,主要讨论的是提出了Congestion Control Plane (CCP)的概念,希望能够实现Wirte-once,run-anywhere,以及可以容易在此的基础之上实现新的拥塞控制算法。CCP的设计中按照下面的设计原则, 数据面和拥塞控制隔离; 拥塞控制和ACK-clock分离,以一个周期报告ACK的信息,而不是每一个ACK报告一次; 可以数据面内实现对每一个ACK的逻辑。 CCP一个基本的架构如下, 0x01 使用CCP实现一个算法 CCP中主要使用的是onCreate和onReport两个回调处理函数。在一个流建立的时候数据面会调用这个onCreate的函数。这个函数会初始化一个数据面的程序。这个数据面的函数会计算出一些关于每个数据包的一些信息,这些信息会汇报给CCP agent。在report的时候,CCP agent调用onReport函数,这个函数根据这个函数计算出新的发送窗口的大小 or 发送速率。CCP的数据面程序使用一个简单的领域特定语言写成,根据每一个ACK来计算一些统计信息(control actions),一个简单的数据面程序, (def (Report (volatile acked 0) (volatile lost 0))) (when true (:= Report.acked (+ Report.acked Ack.bytes_acked)) (:= Report.lost (+ Report.lost Ack.lost_pkts_sample)) (fallthrough)) (when (> Report.lost 0) (report)) 这个DSL中包含的一些ACK的信息、一些Flow的信息, CCP中的onReport()提供了在用户空间处理来自数据面数据的方法,一个简单的AIMD的算法实现的逻辑在onReport中实现如下,... Read more!

  • 01 Jan 2019
    EPaxos and SDPaxos

    There Is More Consensus in Egalitarian Parliaments 0x00 引言 这篇Paper是关于Paxos算法的一个优化策略。这篇提出了一个Paxos的一种变体EPaxos。EPaxos侧重点在消除稳定/指定的Leader/Master的设计。EPaxos的基本思路就是为每一个客户端提交的Command指定一个Leader,同时处理好这样设计的冲突和依赖的关系,并加上了一些设计和实现上面的优化, 0x01 基本设计 EPaxos的设定和一般的Paxos没有很大的区别,在副本数量为2F+1的情况下,能够容忍F个副本的故障。在EPaxos中,存在两种不同的动作,一个是Committing另外一个是Executing,且它们的顺序不一定要相同(可以乱序提交)。另外在EPaxos中的一个重要的概念是Command Interference,两个Commands存在Command Interference即当两个的顺序必须按照一定的顺序进行,负责会得到不同的结果。EPaxos可以保证存在Command Interference的两个Commands C1 C2在客户端有着怎么样的顺序关系,在每个副本上面的执行的顺序也一定会是这样的顺序关系。deps是一个副本的列表,它(们)包含了与一个Command存在Interference的Command(s),而seq则是序列号,用于打破循环依赖。 EPaxos中每个副本有一个唯一的ID,和常见的算法一样,为了处理新配置,EPaxos中也使用了epoch。所以在EPaxos中Ballot Number的格式是epoch.b.R,b是一个递增的自然数,R为副本ID。 在上面的图1是一个例子。两个并发的更新操作更新不同的对象,不存在Interference,且各自选择了不同的Command Leader,按照EPaxos的Fast Path执行完毕。而两个并发的更新操作更新相同的对象,存在Interference,也选择了不同的Command Leader,则会产生冲突,则执行的是EPaxos中Slow Path。 基本的EPaxos中,一个Fast Path的Quorum为2F个副本,可以优化为$F + \lfloor (F+1)/2 \rfloor$。在Slow Path的处理中,一个Quorum的大小总是为F+1。 正常操作的时候一个Command Leader接受到它为Leader的操作之后,向至少为一个Fast Path的Quorum发送PreAccept消息。副本在接受到这个消息之后,更新这个Command的deps和seq属性,然后回复Command Leader。Command Leader在收到了足够数量的回复,且更新之后的属性相同(另外的副本回复的属性可能已经被更新),则可以提交这个操作。如果收到的属性存在不同,则选择一个有相同属性的多数副本的Quorum的属性,然后通知多数的副本接受这个属性,这一步操作也要等待多数副本的回复。之后Command Leader就可以回复客户端并发送异步的Commit的消息。 执行算法,执行的时候主要就要构建一个依赖关系拓扑,提交一个Command依赖中的没有提交的(EPaxos需要的依赖的处理在实际应用的时候估计会很困难,估计也会造成比较大的Overhead), 1. Wait for R.i to be committed(or run Explicit Prepare to... Read more!

  • 31 Dec 2018
    Several Papers about Time and Timestamp

    祝2019好运🍀 Globally Synchronized Time via Datacenter Networks 0x00 引言 2018年最后一天,时光匆匆,来看几篇关于时间的Papers。这篇Paper是在数据中心内时间同步的一个设计。Paper中认为目前使用NTP 和 PTP都存在一些问题。这篇Paper中提出了一种叫做Datacenter Time Protocol(DTP)的时钟同步协议。在Paper中的测试环境的测试数据表明,在直接连接的情况下可以实现小雨25.6ns的误差,在6跳的时候这个数字是153.6ns, ... is bounded by 4TD where D is the longest distance between any two servers in a network in terms of number of hops and T is the period of the fastest clock (≈ 6.4ns). Moreover,... Read more!

  • 30 Dec 2018
    Maglev and Beamer Load Balancer

    Maglev: A Fast and Reliable Software Network Load Balancer 0x00 引言 Maglev是Google的网络负载均衡器。Maglev 2008年开始在Google中得到应用,然后这篇论文发表在2016年(Google的风格)。不仅如此,国内的一些厂商在Google的这篇论文之上开发了类似于Maglev的系统。 0x01 概览 Google的每个服务器会被赋予一个or多个的VIP,这个VIP不同与实际的IP地址,这些VIP的背后是Maglev在处理。Maglev 会将一个VIP和一组的服务入口关联,这些信息会交给路由器(使用BGP路由协议)。之后这些VIP的信息时在互联网可见的,主要是用户的DNS请求之后,Google授权的DNS服务器会更具用户的位置和目前的负载均衡情况给用户返回一个VIP地址,之后就可以和这里VIP地址建立连接。路由器收到一个VIP的数据包是,使用ECMP的方式来决定将这个包发送给哪一个Maglev机器。之后就是Maglev收到这个包,它会使用它的方法从与这个VIP关联的服务器中选择其中的一个,之后这个数据包会被封装为Generic Routing Encapsulation(GRE)包(with the outer IP header destined to the endpoint)。服务器在处理请求给用户回复的时候,就可以直接将数据包递交给用户(原地址为VIP,并不使用服务器实际的IP地址),这样回复的数据包就可以不经过Maglev,又由于回复的数据一般都大于请求的数据,这个对提高Maglev实际的处理能力还是很有好处理的。这种处理的方式被称为Direct Server Return (DSR) ,具体的实现的内容在Paper中没有说明。 配置 在一台Maglev的机器中,主要就是两个部分,一个转发器和一个控制器。Maglev使用的VIP的相关的信息都来源于配置对象,这个最终来源于其它外部系统,Maglev使用RPC的方式去获取。在转发器中,一个VIP会配置一个or多个的后端(服务器)的资源池。一个池子里面包含的可能是后端服务器的实际的IP地址,也可能是递归包含另外的池子。这些池子会有对应的健康检查的方法。转发器的config manager负责来处理和验证配置信息。另外,对于一个集群来说,它可以配置多个的maglev,每一个负载处理不同的VIPs的部分。 0x02 转发器设计与实现 为了提高处理的性能,转发器的数据包处理是Kernel Bypass的。Maglev Kernel Bypass的技术采用的是Google自己开发的技术,没有采用现在的一些解决方案的原因可能是Maglev实际开发的很早。在Magev之中,数据被网卡接受到之后,Maglevc的steering模块会根据header中的5元祖使用 5-tuple hash算法来计算出一个hash值。然后根据这个hash值陪分配到不同的接受队列。这些队列中的包会被一个Header Rewriter的线程进行操作,这个线程首先会判断这个数据包是不是发给一个VIP的,在上面的Packet Flow的图中也有表示这两种包的处理路径有所不同。之后就是根据5元组hash去查找connection tracking table。这里为了避免跨线程的同步,这个第二次使用的hash值是重新计算的。 这个connection tracking table包含的是最近使用的一些后端的服务器的一些信息,在这个表中存在表明这个服务器在目前应该还是可以使用的,这个结果就可以继续使用。如果没有发现,那么就要使用一致性hash的方法选在一个性的后端服务器来使用,并添加到这个table中,以便于后面重用这个结果。在没有可以使用的后端服务器的时候,这个数据包就会被drop。另外,这个table是每一个处理的线程一个,避免了同步带来的开销。之后数据包被封装合适GRE/IP Header,转交给transmission... Read more!

  • 29 Dec 2018
    Understanding PCIe Performance for End Host Networking

    Understanding PCIe Performance for End Host Networking 0x00 引言 这篇Paper从PCIe的角度讨论了PCIe性能对终端网络的影响。Paper中指出,随着网络带宽的增长,在40Gb和100Gb的网卡面前,PCIe也会成为网络性能的一个瓶颈。Paper中提出了一个pcie-bench工具,用来测量PCIe在多种环境下的一些性能指标。更重要的是通过对这些测量的数据来对以后的系统设计提出指导。 0x01 背景 PCIe对网络延迟的影响。PCIe的传输会增加延迟,特别是网络数据包很小的时候,这个延迟占到(终端部分?)的90%。另外,对着多种的技术操作对PCIe的性能测量是比较困难的,比如intel的DIDO技术,还有就是NUMA也增加测量的复杂度。还有就是IOMMU的影响。PCIe的一些特点: PCIe是通过几条串行链路连接的串行连接,它的协议有3层:物理层,数据链路层和传输层。 现在一般的40Gb的网卡使用的是第3代的PCIe,使用8路,每路提供8GT/s的带宽。使用128b/130b编码下实现的带宽是8 × 7.87 Gb/s = 62.96 Gb/s。这个理论上的最大带宽,算上数据链路层加入overhead,这个带宽大约在 57.88 Gb/s。另外在传输层又会增加开支。 读取一定的数据量sz情况下,实际需要传输的数据量: \(\\ B_{tx} = \lceil sz / MRRS \rceil \cdot MRdHdr + sz \\ B_{rx} = \lceil sz / MPS \rceil \cdot CplHdr + sz\\ 其中MRRS,MPS每次最大能传输的量;MRdHdr,CplHdr,头部的大小;\) 上面的一些事基本的情况,另外考虑到诸多的优化技术情况下会更加复杂。... Read more!

  • 28 Dec 2018
    The QUIC Transport Protocol

    The QUIC Transport Protocol: Design and Internet-Scale Deploymen 0x00 引言 QUIC是Google开发的一个基于UDP的可靠传输协议。由于是Google开发的,又在Google的支持下得到了很多的应用,QUIC还是很有名的。QUIC的几个特点: 避免了TCP繁琐的三次握手操作,加上TLS握手就就更加麻烦了。QUIC改进了连接建立的操作; QUIC的拥塞控制是可拔插的,开始or配置新的拥塞控制算法更加方便; 改进的多路复用; 一开始就为加密传输设计; 支持连接的迁移; 0x01 设计与实现 连接的建立 与TLS连接的建立不同,QUIC能够实现在0RTT建立传输层的连接的同时0RTT建立加密层的连接。如下的所示,一个连接的建立要主要的操作: Initial handshake,初始握手。开始是客户端发送一个 inchoate client hello (CHLO)信息,这个时候服务端会回复一个reject (REJ) 消息。这个reject (REJ) 信息里面包含了不少的信息: (i) a server config that includes the server’s long-term Diffie-Hellman public value, (ii) a certificate chain authenticating the server, (iii)... Read more!

  • 26 Dec 2018
    NDP Transport Protocol

    Re-architecting datacenter networks and stacks for low latency and high performance 0x00 引言 这篇Paper中推出的NDP传输协议是为数据中心网络环境设计一种新的传输协议。NDP的想要实现的几个目标: 0-RTT连接建立,主要就是要避免类似TCP的三次握手的方式; 快速启动,不用向TCP一样的带宽的探测的过程; Per-packet ECMP,更加细粒度的负载均衡; 可以容忍乱序的握手,因为要实现0-RTT的连接建立,就得容忍第一个包就乱序了; 优化incast的情况。 对于短流有低完成时间延迟,对于长流有预测的高吞吐; 0x01 基本设计 NDP为了实现上面的这些目标,它的设计涉及到了交换机的操作、路由以及一个全新的传输协议。NDP为了实现对于短流的低完成时间延迟,就要求一开始就全速发送数据包,而不能有类似带宽探测这样的行为。这里NDP假设在数据中心网络中,带宽一般是充足的。同样地,要想实现低延迟,交换机的排队也必须是很少的,这里NDP使用了Packet trimming的方式和接受端拉取的方法。 在交换机上面,NDP使用的方法不是在发送拥塞的静默地就把包丢弃,而是丢弃payload,但是包header部分继续转发,对于这类包,接收方回复NACK,普通包回复ACK。加上NDP客户端拉取的工作方式,这个可以是的快速地重传操作而不用等到超市重传。为了把这些header很好地转发到接受端,交换机一般会将这些header包的优先级提高。另外,NDP在交换机的行为上面做了这样的一些优化: NDP在交换机中维持了两个队列,一个是数据包的优先级较低的队列,一个是被裁减了的只有header的包的队列,优先级较高。Paper中认为这种方法能够在实际上获得很好的效果; 交换机在转发的方式上在不同的队列上面选择了加权的RR的转发方式; 当数据包到达且低优先级队列,但此时队列已满时, 交换机决定是修剪新到达的数据包, 还是修剪低优先级队列尾部的数据包的概率都为50%。这个可以处理Cut Payload存在的collapse问题,也可以处理strong phase的效应。 路由 NDP在路由的设计上主要的考虑就是如何利用数据中心网络中大量的可行的等价的线路。NDP使用了发送者决定路线的方式。NDP认为,在数据中心网络中,发送者是知道我了的拓扑的结构的,它可以可以直接作出决策。另外,由于数据中心网络的拓扑一般比较简单,这个增加的成本并不大。 0x02 传输协议 基本的工作流程 NDP使用接收方驱动的方式,可以实现更好地利用多可行路线、包裁减和降低交换机排队。基本的工作流程: 发送方一开始就发送一个完整窗口的数据,不等待回复。每一个数据会有一个序列号; 接收方对于接收到的每一个header包,回复一个NACK,通知发送方准备重传,但是不是立即就重传; 对于每一个数据包,接收方回复一个ACK; 对于接收到的header包和数据包,接收方都添加一个pull包到自己的pull队列,一个接收方志友一个这样的队列,所有的连接共享;pull包上包含了连接的ID; 接收方发送pull包,这里要注意速率。另外还有考虑到优先级; 当接收方接收到pull 数据包时,就回去尝试发送更多的数据包,要求重传的数据包优先发送; 当发送方发送完数据时,会在数据包上面做一个标记。接收方在接受到之后做一些清理工作; NDP要处理另外的几个问题: Coping with... Read more!

  • 05 Dec 2018
    BBR -- Congestion-Based Congestion Control

    BBR: Congestion-Based Congestion Control 0x00 引言 这次来看一个重量级的拥塞控制的算法:Google开发的BBR算法,在Linux 4.9之后在基于Linux内核的系统上面变得可用。这个算法在一诞生的时候就收到了很大的关注,算法本身没有发表论文,而是一篇ACM杂志的文章[1,而且这篇文章感觉写得挺迷的]。BBR算法和前面看到的TIMELY算法不同,BBR是为正常情况下都存在一定的丢包可能性的网络设计的算法,最常见的就是长肥网络。而TIMELY算法面向的数据中心网络一般不具有这些特点。另外一个区别就是BBR是一个已经实用了的算法,而TIMELY应该只呆在实验室里面(⁎⁍̴̛ᴗ⁍̴̛⁎)。不明白BBR公平性如何?? 0x01 基本思路 BBR主要基于以下的现在的一些拥塞控制算法在一些网络特别是广域网上面存在的一些问题: 目前Linux默认使用Cubic算法以及经典的TCP的拥塞控制算法如New Reno都是基于丢包的,而这些基于丢包的算法的一个缺点就是当线路越“长肥“时,为了充分利用带宽对丢包率的要求就越高,但是矛盾的是越是“长肥”得网络,出现丢包的可能性就越高。这样这样的算法就存在不少的问题。 另外一个问题可以理解为基于丢包的一些算法对拥塞的发生反应太迟(联系前面的TIMELY算法,使用变化率的方式,在数据中心网络中已经有不少的Paper讨论处理了这类情况,但是广域网情况太复杂,不好直接处理),如果这里将网络想象称为有一定容量的管子,原来的一些算法就是直接“灌”到这个管子溢出时才开始处理,但是这个时候并不是最佳的处理拥塞的时候,因为太迟了。下面的图表现了这个现象[1], 显而易见的一点就是在一个TCP流中,决定最大带宽的时线路上面最小的带宽瓶颈的地方。一个要实现最大化带宽和最小化延时的拥塞控制算法有这样两点要求:1. 发送的速率要和这个线路上面带宽瓶颈的地方的带宽一致;2. 总共的在传输过程中的数据的量要等于瓶颈带宽(BtlBw) *RTprop(round-trip propagation time)。第一个条件保证了最大化带宽的利用,第二点保证了有足够的数据利用线路但是又不至于过度占据路线上面的buffer。BBR的一个核心就是测量BtlBw和RTprop的值。BtlBw和RTprop在一个连接中时随着时间变化的,所以这两个值的测量会在连接的生命周期内一直测量。另外的一个问题这两个是不能同时测量的,因为测量其中的一个会影响到另外的一个值:为了测量BtlBw就是尽量多发送数据以探测最大的带宽,而这样的话就会影响到RTprop的值;而为了测量RTprop,输送的数据越少就越精确。所以这里这两个值的测量逻辑上是分开的, RTprop,实际的连接的RTT来自于RTprop和其它的一些岩石,为了更精确的测量RTprop,BBR使用下面的公式 \(\\ RTT_{t} = RTprop + \eta_{t}, 这里的\eta_{t}为> 0的一个值,会随着时间变化,\\ 令 \widehat{RTprop} = RTprop + \min(\eta_{t}) = \min(RTT_{t}), \forall t \in [T-W_{B}, T]\\\) 这里的W-B为一个时间窗口,一班为数十秒or几分钟,也就是说RTprop就是测量到的RTT-t的最小值。 BtlBw与此相反BtlBw则是这个时间窗口内测量到的带宽的最大值。这里的测量的带宽使用一个段时间内发送的数据量定义, \(\\ \widehat{BtlBw} = \max(delivaryRate), \forall t... Read more!

  • 30 Nov 2018
    TIMELY -- RTT-based Congestion Control for the Datacenter

    TIMELY: RTT-based Congestion Control for the Datacenter 0x00 引言 这篇文章是发表在 SIGCOMM ’15一篇关于为Datacenter设计的基于RTT的Congestion Control算法的Paper。基于RTT的Congestion Control算法在很多年前就已经出现了,这篇Paper推出的算法在数据中心网络的环境下面实现了更加好的效果, We show using experiments with up to hundreds of machines on a Clos network topology that it provides excellent performance: turning on TIMELY for OS-bypass messaging over a fabric with PFC lowers 99 percentile tail latency... Read more!

  • 09 Nov 2018
    Jupiter Rising -- A Decade of Clos Topologies and Centralized Control

    Jupiter Rising: A Decade of Clos Topologies and Centralized Control in Google’s Datacenter Network 0x00 引言 这篇Paper Google数据中心网络发展的一个综述性的文章,这篇文章不是具体讨论一个数据中心网络的设计,而是讨论了Google的数据中心网络的发展变化, Our datacenter networks run at dozens of sites across the planet, scaling in capacity by 100x over ten years to more than 1Pbps of bisection bandwidth. 0x01 动机与设计理念 Google发展它自己的网络的动机很简单:使用其它厂商的解决方案不仅仅是价格的问题,而且是很难区满足Google的要求。Google建设自己的网络的时候遵循下面的设计原则: Clos topologies,Clos是数据中心网络中最常见的网络拓扑技术,在很多的数据中心网络架构中得到了应用; Merchant... Read more!

  • 06 Nov 2018
    Three Data Center Network Architectures

    VL2: A Scalable and Flexible Data Center Network 0x00 引言 VL2是微软设计的一个数据中心网络的架构。它的设计由下面的几个特点: (1) flat addressing to allow service instances to be placed anywhere in the network, (2) Valiant Load Balancing to spread traffic uniformly across network paths, and (3) end-system based address resolution to scale to large server 0x01 分析 在讨论VL2的具体设计之前,Paper先总结了几个数据中心网络的几个特点(Paper中的观点以及数据):... Read more!

  • 03 Nov 2018
    A Scalable, Commodity Data Center Network Architecture

    A Scalable, Commodity Data Center Network Architecture 0x00 引言 这篇Paper是数据中心网络设计上很重要的一篇。这里一个核心的概念就是Clos Networks和Fat-Trees。 Specifically, one instance of our architecture employs 48-port Ethernet switches capable of providing full bandwidth to up 27,648 hosts. By leveraging strictly commodity switches, we achieve lower cost than existing solutions while simultaneously delivering more bandwidth. Our solution requires... Read more!

  • 30 Oct 2018
    The FuzzyLog -- A Partially Ordered Shared Log

    The FuzzyLog: A Partially Ordered Shared Log 0x00 引言 这篇Paper是关于Shared Log优化的一个文章,前面的Corfu就是一个典型的Shared Log的系统。FuzzyLog的基本思路是放宽Shared Log中的Log之间的顺序关系,使用偏序而不是全序。再次的基础之上,FuzzyLog认为大部分的操作都只会设计到一个数据分区,FuzzyLog就使用每一个数据分区维护自己分区的方法,这样可以增加操作的并行性;另外,在跨地理区域部署是,通过降低一致性来避免在关键路径上面的同步跨区域协调,因此FuzzyLog也可以实现并发访问不同的区域,即使是对同一个逻辑的数据分区。偏序而非全序的设计使得FuzzyLog可以提供更加好的拓展性(在不牺牲原子性的同时实现容量和吞吐的线性拓展),可以通过更弱的一致性以及容忍网络分区, ... retain the simplicity (100s of lines of code) and strong semantics (durability and failure atomicity) of a shared log design while exploiting the partial order of the FuzzyLog for linear scalability, flexible consistency guarantees (e.g., causal+... Read more!

  • 28 Oct 2018
    Tango and vCorfu -- Tow Papers about Shared Log

    Tango: Distributed Data Structures over a Shared Log 0x00 引言 Tango这篇Paper是利用Shared Log实现分布式数据结构的一篇文章。 Tango可以实现类似于C++ STL / Java Collections中的数据结构。这些数据结构的抽象就类似于一般的内存中的数据结构,但是会备份到Shared Log中, ... a single Tango object running on 18 clients provides 180K linearizable reads/sec against a 10K/sec write load... In our evaluation, a set of Tango objects runs at over 100K txes/sec when... Read more!

  • 26 Oct 2018
    CORFU -- A Shared Log Design for Flash Clusters

    CORFU: A Shared Log Design for Flash Clusters 0x00 引言 Shared Log是一些分布式系统的一种的实现思路。CORFU是一个 Shared Log的实现,它主要是面向SSD设计。CORFU可以被视为一个分布式的SSD,同时提供普通的SSD不能支持的功能,包括容错、可拓展性和垮地理区域复制等。 A single CORFU instance can support up to 200K appends/sec, while reads scale linearly with cluster size. Importantly, CORFU is designed to work directly over network-attached flash devices, slashing cost, power consumption and latency by eliminating... Read more!

  • 23 Oct 2018
    Omid, Reloaded -- Scalable and Highly-Available Transaction Processing

    Omid, Reloaded: Scalable and Highly-Available Transaction Processing 0x00 引言 Omid是yahoo开发的基于Hbase设计的支持跨行设计的系统,有点像Goole的Percolator。出现的时间晚了不少,架构的设计上也有很多不同的地方。 Omid can serve hundreds of thousands of transactions per second on standard mid-range hardware, while incurring minimal impact on the speed of data access in the underlying key-value store. Additionally, as expected from always-on production services, Omid is highly available.... Read more!

  • 20 Oct 2018
    BAST, FAST and Superblock-Based Hybrid FTLs

    A Space-efficient Flash Translation Layer for Compactflash Systems, Transactions on Consumer Electronics ### 0x00 引言 这篇是关于FTL Hybrid模式的一篇比较早的Paper。在这篇Paper中,作者提出了一种叫做log block的模式。在这种模式下面,大部分的数据都以Block为粒度来管理,另外的一小部分以Page为粒度来管理。后者称之为Log Blocks,用于临时保存小数据量的写。 0x01 基本思路 在这种模式下,到达一个数据Block中的一个Page的更新操作的时候,一个提前擦除了的日志Block被分配,之后每次这个数据Block的写入操作,就是写入到这个对应的日志Block中。同时,这个逻辑Page和这个物理Page的映射关系会被保存到另外的一个区域。这样的模式下,一个读请求达到的时候,如果请求的Page在日志Block中,就选择返回这个日志Block中的Page,否则返回数据Block中对应的Page。 随着日志Block的写入,当这个日志的Blok被写满时,这个之后就要进行Merge操作,即将日志Block的数据写入到数据Block中。这里的操作很直观,首先从空闲的Block中选择一块,将数据Block和日志Block里面的数据选择每个Page最新的写入到新的Block中,而原来的日志Block和数据Block就会归还到空闲Block池子中。之后这些Block会被擦除。这里如果刚好是一个Block里面顺序写入Page,那么这里合并的操作是不需要的,直接用日志Block代替数据Block即可,这样的操作在这里称之为switch操作。这里有些类似于日志式文件系统的一些垃圾回收的操作,不同点在于这里的Block是有限定的等。 在Merge操作或者是Switch操作之后,都需要去更新一些映射关系。在之前的一些系统中,这些映射关系需要全部保存到SRAM里面。而在这里,Mapping Table保存在指定的一些Blocks中,在需要的时候取出来,这些Blocks称之为Map Blocks。Map Blocks的组织类似于日志Blocks,这些Mapping Tables的映射称之为Map Directory,保存在SRAM中。这样看起来就类似于两级的Page-Table。上图表示了一次Merge操作之后,Mapping Table之前和之后的情况。一个Merge操作实际上会有三个Blocks参与操作,需要更新三个Blocks的映射关系。同样地,Mapping Table使用的数据也要被回收,这里使用了RR的方式来管理, ... In our approach, the mapping table is fragmented into a unit of a half of a page so... Read more!

  • 17 Oct 2018
    Pocket -- Elastic Ephemeral Storage for Serverless Analytics

    Pocket: Elastic Ephemeral Storage for Serverless Analytics 0x00 引言 Pocket是应对Serverless架构出现的一种Ephemeral Storage(暂时性存储)的解决方案。这类存储与诸如Spanner/ Amazon Aurora数据库存储、Haystack之类的图片存储或者是Dynamo之类的Key/Value存储系统存在很大的区别。对于 Elastic Ephemeral Storage(EES)系统被认为要满足这样的几点要求, 对大范围的对象大小都有着很高的性能; 自动地细粒度的拓展,在满足要求的情况下分配最小的资源,节约成本; 对使用的存储技术有感知,以便能够能够用做合适的方式使用存储资源和满足应用的要求; 容错,EES这类系统而言,生命周期一般只有10s - 100s,也就没必要项一般的存储系统那样对容错性有着很高的要求。 Pocket dynamically rightsizes resources across multiple dimensions (CPU cores, network bandwidth, storage capacity) and leverages multiple storage technologies to minimize cost while ensuring applications are not bottlenecked on... Read more!

  • 15 Oct 2018
    FlashShare -- Punching Through Server Storage Stack

    FlashShare: Punching Through Server Storage Stack from Kernel to Firmware for Ultra-Low Latency SSDs 0x00 引言 这篇Paper将的时如何从内核到固件为现在的Ultra-Low-Latency (ULL) SSD进行优化,这是最近的第好几篇关于这个方面的文章了。这个优化感觉和数据中心内一些为网络优化的类似,也是针对不同的应用区分不同要求的请求,在这篇Paper中特别注意的是延迟敏感性的请求。在固件层面对NVMe的控制权和缓存进行了改进,使用动态的DRAM分区满足不同应用的要求。Paper中几个重要的内容总结如下: Kernel-level enhancement,目前,Linux对于这类高性能的SSD使用的block layer是 multi- queue block layer (blk-mq),blk-mq也为SSD之类的硬件做了很多的优化,但是它没有考虑到IO请求的优先级。FlashShare先对kernel进行改进,将这类IO请求(延时敏感类型)可以绕开现在内核一些处理机制,直接达到NVMe的驱动层。 Firmware-level design,为了能让SSD的固件也能意识到这些延迟敏感类型的请求,FlashShare重新设计了固件的调度和缓存。FlashShare将SSD内置的Cache根据workload的特点进行分别分配Cache,还可以动态调整这些分区。 New interrupt services for ULL SSDs,FlashShare认为现在的基于中断的方式(message-signaled interrupts)会有存储栈带来的很长的延时的问题,使用轮询的方式会消耗大量的CPU。FlashShare则使用折中的设计,使用了一种叫做selective interrupt service routine (Select-ISR)的方式,就是对在线交互类的应用使用轮询的方式,对线下应用使用中断的方式。 通过使用这些方式它实现了一下的效果: We also revise the memory controller and I/O bridge... Read more!

  • 13 Oct 2018
    Remote Core Locking and ffwd

    Remote Core Locking and ffwd 0x00 引言 这篇总结包含了2篇Paper的内容,一篇是ATC‘12上面的Remote Core Locking,一篇是SOSP 2017上面的ffwd。两者将的都是利用另外的核心来执行临界区代码的一个并发控制的思路。对于一段程序,多核真的能加快运行速度?答案显然是不一定的。对于那种能够存在多个同时操作的结构,比如B-tree,很多时候是能起到加速的效果。但对于临界区多个线程就只能顺序的执行,实际上在这段临界区的代码中就运行多线程就可能比单核还慢,特别是核心数很多 or NUMA架构的情况下,前者是因为维持缓存一致性带来的巨大的开销,后者一般是访问远端的内存的高成本(大概就是这个意思了)。这个时候还不如直接使用单核了。Remote Core Locking 和 ffwd 就是这样一种访问临界区的方式,基本思想都是将这段访问的任务都交个另外一个核心来运行,也就是一种代理的方式。基本的思路: 减少原子指令的使用,降低cache miss率; 在另外的一个指定的核心上执行临界区代码; 快速的控制转移,没有同步也没有全局变量; 共享的数据保持在server核心上(即用来执行临界区的代码的核心),这意味着更加少的cache miss。 0x01 Remote Core Locking(RCL) RCL的基本原理: 在RCL中,执行临界区的代码编程了一种远程方法调用。为了实现这个“RPC”调用,客户端和服务段使用一个请求结构的数组来进行交互。这个数组一共有C项,这个C代表了能够请求服务的客户端的数量。一般而言都要大于CPU 核心的数量。这个数组每一项的长度为L bytes,这个L一般是CPU缓存行的大小。第i项记为req-i,代表了一个client-i和服务端和交互的结构。 req-i包含了以下的几个字段: 这个临界区相关的lock的地址; 一个context结构的地址,包含了一些会由临界区引用or更新的一些变量之类的东西; 包含了临界区代码的函数的地址,如果没有临界区,这个字段就是NULL; 操作过程 客户端: 依次写入lock的地址、context 结构的地址、要执行函数的地址到req-i的第1、2、3个部分,然后等待第3个部分被服务方设置为NULL,代表了服务方已经将请求完成,这里可以使用SSE3 的monitor/mwait指令优化。 服务端:轮询这些request结构的数组,当发现req-i的第3个字段不为NULL的时候,先检查lock是否是空闲的,如果是,则获取lock,然后执行函数,执行完成之后,设置第3个字段为NULL,重复以上的过程。 关于算法的详细伪代码和评估数据可以参看论文[1]. For the applications that spend 20-70% of... Read more!

  • 10 Oct 2018
    LegoOS -- A Disseminated, Distributed OS for Hardware Resource Disaggregation

    LegoOS: A Disseminated, Distributed OS for Hardware Resource Disaggregation 0x00 引言 这篇文章是OSDI 2018的best paper之一。这篇paper针对目前这样一个情况,提出了一种新的OS架构:目前硬件资源在数据中心这样的地方很多时候分布在不同的机器之后,而传统的一个系统由固定的几个硬件组成,主要的如内存,处理器,硬盘等。不同的应用的特性不同,对资源的使用也不同,就可能出现在一台机器上的一些资源已经很紧张了,另外的一些资源却没有怎么使用。针对这种情况,这里提出了一种叫做splitkernel 的架构,在splitkernel的模式下,设计并实现了一个LegoOS的操作系统,这个系统的主要特点就是资源分布在不同的地方,每一个地方运行不同的系统组件,各个组件之间由高速网络连接(这里使用的就是RDMA),这些组件的组合就形成了一个新的系统。Lego这个名字取的很生动形象。 Following the splitkernel model, we built LegoOS, the first OS designed for hardware resource disaggregation. LegoOS is a distributed OS that appears to applications as a set of virtual servers (called vNodes). A vNode can... Read more!

  • 08 Oct 2018
    Write-Optimized and High-Performance Hashing Index Scheme for Persistent Memory

    Write-Optimized and High-Performance Hashing Index Scheme for Persistent Memory 0x00 引言 这篇OSDI 2018会议(就是今天开的, 2018-10-08)上的一篇关于Persistent Memory上hash index设计的文章[1],是Path Hashing[2]的后续,也是华科在OSDI上发表的第一篇文章???这篇论文讨论了Path Hashing没有解决的问题,其中一个就是resize如何处理。 To cost-efficiently resize this hash table, level hashing leverages an in- place resizing scheme that only needs to rehash 1/3 of buckets instead of the entire table, thus significantly reducing the number... Read more!

  • 30 Sep 2018
    NVMeDirect -- A User-space I/O Framework

    NVMeDirect: A User-space I/O Framework for Application-specific Optimization on NVMe SSDs 0x00 引言 这篇Paper是关于在user-space实现一个为NVMe SSD优化的IO framework。与此类似的有SPDK。原来的内核的IO framework显得过于复杂,在高速的SSD面前显得开销太大,并不能很好的适应现在的NVMe的SSD,和一些network framework一样,这个NVMeDirect也尝试将其移到user-space来获取更好的灵活性和更高的性能, ... the proposed framework provides flexibility where user applications can select their own I/O policies including I/O comple- tion method, caching, and I/O scheduling. Our evaluation results show that the proposed framework... Read more!

  • 27 Sep 2018
    Split-Level I/O Scheduling

    Split-Level I/O Scheduling 0x00 引言 这篇文章是SOSP‘15上一篇关于IO调度的文章。主要的思路就是在block, system call, 和page cache三个层面实行分开的IO调度的逻辑,实现了更加好的效果。Split-Level I/O Scheduling是一个IO调度的框架,在这个框架之上可以实现具体的调度算法。 our Actually Fair Queuing sched- uler reduces priority-misallocation by 28×; our Split-Deadline scheduler reduces tail latencies by 4×; our Split-Token scheduler reduces sensitivity to interference by 6×. We show that the framework is general and operates correctly with... Read more!

  • 25 Sep 2018
    Optimizing the Block IO Subsystem for Fast Storage Devices

    Optimizing the Block I/O Subsystem for Fast Storage Devices 0x00 引言 这篇Paper讨论的是如何优化Linux的Block I/O Subsystem以使用新的高速的硬件,这里面主要提出了6条改进方案,这些措施有些之间是相互不兼容的,也就是说不能同时使用。此外,这里讨论的是如何对内核做更改来优化,而不是在现在的内核上调整参数设置来优化性能: In this article, we explore six optimizations for the block I/O subsystem: polling I/O completion, eliminating context switches from the I/O path, merging discontiguous requests, reconfiguring an I/O scheduler for an SSD, resolving the read-ahead dilema,... Read more!

  • 22 Sep 2018
    PolarFS

    PolarFS: An Ultra-low Latency and Failure Resilient Distributed File System for Shared Storage Cloud Database 0x00 引言 PolarFS是阿里巴巴为它推出的PolarDB设计的文件系统,作为控制面和数据面分离中的一部分。PolarFS在使用新技术时还是挺激进的,在一个商业产品上面一下子就搞这么多东西,将 network stack, IO stack都做到了user-space,使用3D XPoint ,RDMA, NVMe SSD, and SPDK 等新的技术。 0x01 基本架构 PolarFS主要分为2层,Storage Layer负责管理storage nodes的磁盘资源, 为每个数据库实例提供数据卷(volume)。File system layer 支持在这些volume上实现文件管理,同时还负责访问文件元数据时的互斥和同步。Polar的组件分为一下几个部分: libpfs,一个实现在用户空间的类似POSIX的文件系统接口; Polar-Switch,运行在计算结点上,将IO请求发送给ChunkServer; ChunkServers,允许在storage结点上,处理IO请求; PolarCtrl,PolarCtrl 时控制面,有一组master组成,同时在每一个storage结点上部署了一个agent; 0x02 组件 File System Layer 这些接口以一个libpfs 库提供给使用者。... Read more!

  • 20 Sep 2018
    A Receiver-Driven Low-Latency Transport Protocol

    Homa – A Receiver-Driven Low-Latency Transport Protocol Using Network Priorities 0x00 引言 最近几年为数据中心设计的新的传输协议不少,这篇是SIGCOMM上最新的一篇(截止写这篇论文时),总而言之,这篇论文做到了: In simulations, Homa’s latency is roughly equal to pFabric and significantly better than pHost, PIAS, and NDP for almost all message sizes and workloads. Homa can also sustain higher network loads than pFabric, pHost, or PIAS. -----... Read more!

  • 17 Sep 2018
    Datacenter TCP, Deadline Driven Delivery and Deadline-aware Datacenter TCP

    Datacenter TCP, Deadline Driven Delivery and Deadline-aware Datacenter TCP 0x00 引言 这篇总结包含了3篇Paper的内容,一篇是SIGCOMM 2010上的DCTCP,一篇是SIGCOMM 2011上的Deadline Driven Delivery,还有一篇是SIGCOMM 2012上面的D2TCP。前者将的是如何利用Explicit Congestion Notification (ECN)解决数据中心网络中TCP的一些问题,第二个是如何加入deadline的优化,后者是前2者的优化。这里只是简单地介绍。 0x01 ECN ECN就是显示的拥塞通知。对于IPv4,它使用了DiffServ字段最右边的两个bits来标示(在一些早一点的书上,可以发现说这里是预留给以后的功能的,目前没有使用,当然现在是已经使用了),在IPv6上Traffic Class字段的最后两个bits。 ​ 这里只给出了IPv4的header,图片来源于维基百科。 00 – 不支持ECN; 10 – 支持ECN; 01 – 支持ECN,和上面相同; 11 –遇到了阻塞; ECN还有更多的细节,可参考相关资料。 0x02 问题 incast 问题,在Partition/Aggregate模式中比较常见,服务器同时回复请求端导致某个地方的包突然大量增加,从而导致丢包; 排队问题,长时间的流和短时间的流同时使用一个交换机端口时,导致排队,也导致短时间的数据被drop,及时没有被drop页导致了延时的增加; buffer的问题,不同的流使用不同的交换机短空,长时间的流占用了共享的buffer。 0x03 DCTCP DCTCP利用了ECN。在交换机上,当一个端口的包超过一定的阈值之后,给包加上ECN标志。包的接受端这在接受到这些包之后,将这些信息回复给发送者。发送者根据收到的包里面的ECN的情况来调整发送行为。这样就可以在发生拥塞之前就调整行为。总结一下就是3个部分: Simple Marking at the... Read more!

  • 15 Sep 2018
    Linux Multi-Queue Block Layer

    Linux Block IO: Introducing Multi-queue SSD Access on Multi-core Systems 0x00 引言 这篇Paper讲的是Linux Multi-Queue Block Layer。Linux Multi-Queue Block Layer主要是为了解决现在的Linux Block Layer不能很好地使用新的高速的存储硬件(比如4k读写能得到100W的超高速的NVMe的SSD)。Multi-Queue Block Layer在Linux 3.x的后期合并到了Linux内核主线,在Linux 4.x变化比较大。 硬件性能的快速变化,这里还只是2012年的数据,实际上现在的SSD的性能比这些数据高出很多。 0x02 目前的问题 Linux目前的Block Layer都是为HHD优化设计的。 IO操作在Block Layer中会经过复杂的操作才会被执行,在高速的存储硬件目前暴露出了以下的缺点: Request Queue Locking,现在的请求队列只的操作中,会频繁地使用锁,而这里的很多锁都是全局的,也就是说所有经过这里的请求都有可能形成竞争。在HHD这样性能比较低的硬件上,带来的竞争不明显。但是在SSD上,这里的竞争、同步操作显著了性能。 Hardware Interrupts,IOPS达到了几十万甚至更加高的时候,很多的时间就会被消耗在中断处理上了。 Remote Memory Accesses,目前的设计会导致CPU核心访问的会是Remote Memory,这个造成了不小的性能损失,特别是在NUMA架构的机器上。对缓存也不友好。 0x03 基本设计 顾名思义,Mutil-Queue就是由对个队列,不过不是简单的拆分而言,还要考虑到block layer上层和block layer下层各自的特性。这里使用两级队列的结构,上层的软件队列和下层的硬队列,两个队列实现不同的功能,对应不同的优化策略。 Software Staging Queues 多个Software... Read more!

  • 13 Sep 2018
    BFQ IO Scheduler of Linux

    BFQ I/O Scheduler of Linux 0x00 引言 Linux目前使用的IO Scheduler有CFQ,NOOP和Deadline。在最近几年,Linux的Block Layer做了很多的有哈,最大的一个改变就是添加了multi-queue block layer。相适应的,IO Scheduler也出现了新的变化,在4.12版本中新加入了Budget Fair Queueing (BFQ) Storage-I/O Scheduler和Kyber multiqueue I/O scheduler。前者有不少的资料,这里先记录一下BFQ。Kyber multi-queue I/O scheduler没有文档资料,不过这个应该是一个比较简单的,代码只有约1000行,先研究研究再说。BFQ包含了很多细节的优化,这里以后慢慢完善。 0x01 BFQ基本思路 BFQ保持每一个进程一个IO请求队列,不同于CFQ用RR的方式轮询这些队列的方法,BFQ给这些队列一个I/O budget,这个I/O budget代表了下次能写入到磁盘的扇区(这里是HHD上面的说法)的数量。这个I/O budget的计算时一个很复杂的过程,这里只会简单的说明,不会很具体的讨论。这个I/O budget主要和进程的行为有关。 一个基本的过程如下: 挑选一下一个服务的进程,这里使用内部的B-WF2Q+,一个内部的fair-queueing调度器; 请求分发,等待调用相关函数,处理请求,这时候的处理逻辑是: 一个内部的C-LOOK调度器选择这个应用的一个请求,从它的请求队列中那处理,然后存储设备处理请求。这个C-LOOK既能适应HHD也能适应SSD。 应用的budget会逐渐递减; 如何这个应用的请求处理完成,or 没有了budget之后,执行下面的第3步; 这个应用会被退出服务,赋予一个新的budget,这里会有算法计算新的这个budget; 在BGQ中,每个进程都会赋予一个固定的权重,从总体上来说,这个进程使用的磁盘的吞吐量只会和这个权重相关,和上面的budget其实没有关系。也就是说,这个磁盘的带宽会被竞争使用这个磁盘的进程共同分配。这个看上去反直觉,因为上面提到了budget,这个数值大的能帮助进程获取更加多的资源。但是这里如果是budget更加大,B-WF2Q+会将其的服务推迟得更晚,更小的budget能更及时地得到服务。进程的这个budget的计算时和这个进程的权重时没有关系了,上面提到了,这个budget更多由进程的行为决定的。如果对CFS的进程调度器也熟悉的话,这里的很多思想也是类似。BFQ、CFQ和CFS的一个目标都是公平。此外,区分进程的特点,比如区分交互进程和非交互进程以提供更加好的服务。 Budget assignment 最为一个常识,要想获得最高的磁盘性能,访问最好都是顺序的,很显然这里如果是顺序访问磁盘的进程,最好就能赋予一个更加大的budget。BFQ会通过一系列的方法来计算磁盘的性能特点和一个进程访问的特点。通过 feedback-loop算法,BFQ尝试去计算下一次的budget,让这个budget尽可能的接近进程的需求,当然这里值的计算要考虑到目前的系统状况和磁盘的特点。 BGQ会给一个进程最大的使用时间,这样可以避免随机访问的进程长时间的占有磁盘而降低了吞吐量(这里可以猜想,这里是因为随机访问的应用实际写入的数据比较小,磁盘随机访问的性能远低于顺序访问的性能,而导致budget消耗速度比较慢,从而导致了一直占有磁盘)。 To further limit the extent... Read more!

  • 11 Sep 2018
    New Syscalls of Linux 4.x

    New Syscalls of Linux 4.x 引言 Linux 4.19 就要发布了,按照套路,4.19应该是Linux 4.x的最后一个版本。Linux 4.0发布在2015年4月(那时候还是大二的小懵懂)。这几年中Linux改变了那些东西呢。这篇是总结了一下新增的syscalls的,其实syscall与新特性大部分时候都没啥关系,这里只是为了好玩。 Syscalls copy_file_range ssize_t copy_file_range(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags); Linux 4.5中添加的,主要是为了减少不必要的数据拷贝。比如从一个文件的数据拷贝到另外一个文件是,可以不经过user space。 mlock2 int mlock(const void *addr, size_t len); int mlock2(const void *addr, size_t len, int flags); int munlock(const void *addr, size_t... Read more!

  • 09 Sep 2018
    BTRFS -- The Linux B-Tree Filesystem

    BTRFS: The Linux B-Tree Filesystem 0x00 引言 BtrFS号称是Linux的下一代文件系统,不过感觉现在进展不怎么样,目前性能也渣。虽然有一大堆的新功能和高级特性,不过bug一大堆。从2007年开始开发到现在都11年了,还是这个鬼样子,有种要扶不上墙的感觉。这篇Paper就介绍了BtrFS的基本技术。诸多的新功能: (1) CRCs maintained for all metadata and data; (2) efficient writeable snapshots, clones as first class citizens; (3) multidevice support; (4) online resize and defragmentation; (5) compression; (6) efficient storage for small files; (7) SSD optimizations and TRIM support. 一些BtrFS基本的概念的简单介绍。 0x01 基本设计... Read more!

  • 06 Sep 2018
    F2FS

    F2FS: A New File System for Flash Storage 0x00 引言 SSD有种它自己的特点。Linux的Ext FS,XFS FS等主要还是为HHD设计,优化的出发点也是HHD的工作方式。而SSD的工作方式和HHD有着本质的不同. F2FS是Linux上的一个为SSD设计的FS,另外F2FS是一个Log Structured的FS(所以先看一下[2,3]),现在在很多的智能手机上已经使用了(苹果也号称它的新的APFS是为SSD优化设计的,不过找不到具体技术细节的东西)。 The detrimental effects of random writes could be reduced by the log-structured file system (LFS) approach and/or the copy-on-write strategy. For exam- ple, one might anticipate file systems like BTRFS and NILFS2 would perform well... Read more!

  • 05 Sep 2018
    Flash-based SSDs

    Flash-based SSDs 0x00 引言 SSD在个人电脑是逐渐要普及了。在一个很多公司,数据库的机器也是被特殊对待,一般会配备性能杠杠的SSD。这篇主要参考了[1],这本书是可以免费获取的。 0x01 基本结构和操作 SSD中分为2级的结构,blocks常见的大小是128KB 256KB,另外一个是Page,最常见的大小是4KB。SSD中更加基本的结构是transistor ,一个transistor 可以存储1 2 3 4bits(目前最多一般只有4个)的信息。一个transistor 里面bit越多,性能越差,寿命越短(相对而言,在同样的技术条件下)。 基本操作 Flash的基本操作有3个: Read(page): 读取一个page的数据,这个是SSD比HHD的优点之一,随机读的性能远高于HHD; Erase (a block): 很不幸的是,这个是Flash-based SSD的最大最麻烦的一个问题,也极大地影响了SSD和其控制器的设计。在一个page被program之前,SSD必须擦除page所在的整个块。这个是由于SSD存储的原理决定的。 Program (a page): 将数据写入到一个已经擦除的page中。 0x02 FTL 很不幸的是,SSD的寿命也不如HHD,主要的原因是block能被擦出的次数有限: The typical lifetime of a block is currently not well known. Manufac- turers rate MLC-based blocks as having a... Read more!

  • 04 Sep 2018
    Log-Structured File System

    Log-Structured File System ### 0x00 引言 Log是Computer Science中一个非常重要的思想,与存储相关的地方都非常常见。Log-Structured File System(这里是LFS)是不同与常见的Unix FFS的一类文件系统,这篇论文发表于1992年(还是比我年龄要大呀),比发表于1984年的Unix FFS晚了8年时间。计算机系统随着时间也发生了很多的变化,新的方法也会随之诞生。Log-Structured 是从文件系统,内存分配起到NVM空间管理,到Log-Structured 的数据结构,SSD的内部等等等,一大堆。可以来一个集合。 0x01 动机 动机基于以下的观察: System memories are growing; There is a large gap between random I/O performance and se- quential I/O performance; Existing file systems perform poorly on many common workloads; File systems are not RAID-aware; 所以这里系统设计的核心就是[1]:... Read more!

  • 03 Sep 2018
    A Fast File System for Unix

    A Fast File System for Unix 0x00 引言 Unix FFS是针对HHD的经典文件系统设计,文章发表于1984了,距今已有34年了(比我年龄大上好多)。这篇论文在大三的时候就看过了。FFS的论文里面的思想影响到了现在很多文件系统的设计。 0x01 原有解决方案存在的问题 ​ 经典的Unix文件系统布局: Super Block +------+---------+---------------------------+ | | | | | | | Data | | | inodes | | +------+---------+---------------------------+ 原有系统的问题就是糟糕的性能表现,大概只能发挥出磁盘2%的带宽,低到可怕。性能低的一个最主要的原因就是远文件系统的设计是把此篇当作是一个随机访问的内存,只不过这个不支持byte-addressable而已,只能按块来访问。系统运行一段时间后碎片导致了文件块发布在此篇的各个地方,操作文件造成了大量的seek操作,严重降低了性能。所以FFS的核心就是[2]: How can we organize file system data structures so as to improve per- formance? What types of... Read more!

  • 02 Sep 2018
    Two Scheduling Methods

    Two Scheduling Methods 0x00 引言 MLFQ应该OS课程都会将到的一个Scheduling算法吧。因为某些原因需要复习一下几年前学过的内容。 The Multi-level Feedback Queue (MLFQ) scheduler was first described by Corbato et al. in 1962 in a system known as the Compatible Time-Sharing System (CTSS), and this work, along with later work on Multics, led the ACM to award Corbato its highest honor, the... Read more!

  • 01 Sep 2018
    ISA Wars

    ISA Wars: Understanding the Relevance of ISA being RISC or CISC to Performance, Power, and Energy on Modern Architectures 0x00 引言 RISC和CISC的比较来源已久,早期的比较大多都集中在性能方面。一般情况下,会认为CISC处理器的性能更加好,而能耗和能效更加低,RISC反之,当然这种说法不一定准确。而现在,CPU架构发展已经相对成熟,单核性能每年增长的幅度很小,CPU多核化,智能手机等移动设备的CPU越来越受关注。那么在CPU发展变化之后,RISC和CISC的指令集类型对处理器的各个关键指标又有什么样的影响呢?这里我们来看一看TPCS 2015上的一篇文章[1]。这篇paper主要做的就是: We present an exhaustive and rigorous analysis using workloads that span smart-phone, desktop, and server applications. In our study, we are primarily interested in whether and, if... Read more!

  • 31 Aug 2018
    Designing a True Direct-Access File System with DevFS

    Designing a True Direct-Access File System with DevFS 0x00 引言 这篇Paper主要讲的是新的硬件下面的文件系统的优化的问题。下面的这幅图比较的表示了DevFS的主要内容,主要就是如果将文件系统的实现完全绕开Kernel,与硬件集成,应用可以直接操作, Evaluation of an emulated DevFS prototype shows more than 2x higher I/O throughput with direct access and up to a 5x reduction in device RAM utilization. 0x01 基本思路 上面的图中表示了几种文件系统类型的设计: 传统的FS,所有的工作都交给Kernel来完成,应用只是使用syscall来调用Kernel提供的功能。这个也是最常见的实现方式; 混合类型的user-level的FS,Control-Plane运行在内核,但是读写数据的时候应用可以直接和硬件交互; 带Server的混合类型的user-level的FS,与上一种类似,区别在于未来减少Control-Plane给Kernel带来的Overhead,这些工作交给一个可信的另外一个应用完成; 基于FUSE的user-level的FS,使用Linux上面的FUSE。处理的路径更加长,和这篇Paper内容关系不大; 真直接访问的user-level的FS,就是这篇Paper提出的FS,基本思路就是Control-Plane和Data-Plane都不需要Kernel处理; 由于Control-Plane和Data-Plane都不需要Kernel,这样的话需要处理下面几个问题,也基本是就是原来由内核处理的几个问题需要处理: 文件系统完整性,这里主要就是处理一些情况下更新的问题和并发的问题; 权限,实现POSIX的文件权限的功能; Crash一致性,这个是一个文件系统要处理的一个问题; DevFS这样做的主要的优点就是:1.... Read more!

  • 30 Aug 2018
    Barrier-Enabled IO Stack for Flash Storage

    Barrier-Enabled IO Stack for Flash Storage 0x00 引言 这是一篇非常好的Paper,还是FAST18的best paper,很值得一看,也不是很好理解,233333,看这篇问题最好看一下[2,3],另外,[4]也是一篇理解相关知识的很好的文章。这篇Paper是关于在Flash存储上面IO栈的一个优化,核心的思路就是消除传统的IO栈上面Transfer-and-Flush在现在的一些新的存储硬件上面的开销。Barrier-Enabled IO Stack主要就是将数据的持久化和IO请求的属性分离开,在此之前的方法都是使用fysnc和fdatasync的API来实现这两个的功能。这种方式在现在的一些新的存储硬件上面不能很好的发挥硬件的性能,而Barrier-Enabled IO Stack则添加了fbarrier和fdatabarrier两个API,实现更加细粒度的控制,从而提高性能。 We implement the barrier-enabled IO stack in server as well as in mobile platforms. SQLite performance increases by 270% and 75%, in server and in smartphone, respectively. In a server storage, BarrierFS brings as much as... Read more!

  • 29 Aug 2018
    RFLUSH -- Rethink the Flush

    RFLUSH: Rethink the Flush 0x00 引言 这篇Paper也和前面的一篇一样,讨论的是Flush的一些优化。与前面的从文件系统方面的优化不同,这里优化的方向是直接优化Flush操作本身。这篇Paper主要的优化思路是使得Flush更加细粒度化,可以指定一段范围内(a range of logical block addresses (LBAs))的数据Flush(RFLUSH (Range Flush))。通过这种方式, Performance evaluation using the prototype shows that the inclusion of RFLUSH improves the throughput by up to 6.5x; reduces the write traffic by up to 43%; and eliminates the long tail in the response time.... Read more!

  • 28 Aug 2018
    Optimistic Crash Consistency

    Optimistic Crash Consistency 0x00 引言 这篇Paper是Paper[2]中提及到的比较多的一篇Paper,发表在SOSP’13上面。这篇Paper是一篇非常好的一篇Paper,墙裂推荐。主要探讨的是文件系统中一致性和性能之间的权衡的问题。另外[3]是一个理解这篇Paper的好Presentation。Paper提出了一个Optimistic Crash Consistency的方法来解决文件系统中的Crash的一致性的问题。Paper中提出了两个新的系统原语: osync和dsync(现在的系统中有的是fsync和fdatasync)来将写入的顺序和持久化的顺序分离开。通过使得应用可通过OptFS提供的API来实现不必要使用flush的方式来实现写入的顺序从而提高性能, OptFS improves performance for many workloads, sometimes by an order of magnitude; we confirm its correctness through a series of robustness tests, showing it recovers to a consistent state after crashes. Finally, we show that osync() and dsync() are useful in... Read more!

  • 27 Aug 2018
    LightNVM -- The Linux Open-Channel SSD Subsystem

    LightNVM: The Linux Open-Channel SSD Subsystem 0x00 引言 继续来看关于新存储硬件的Paper。这篇Paper是FAST ‘17上面关于Linux的Open-Channel SSD Subsystem的文章。Open-Channel的主要主要目的是用来解决Log-on-Log之类的问题的。可以是应用获得很多的对SSD内部的一些组件的控制能力,这个对于一些应用特别是数据库和KVS之类的很有用,比如RocksDB。 We introduce a new Physical Page Address I/O interface that exposes SSD parallelism and storage media characteristics. LightNVM integrates into traditional storage stacks, while also enabling storage engines to take advantage of the new I/O interface. Our experimental... Read more!

  • 26 Aug 2018
    Consistency Without Ordering

    Consistency Without Ordering 0x00 引言 这篇Paper讲的是如何利用backpointer-based consistency的技术来实现不依赖于操作顺序的Crash一致性, we show through experiments that NoFS is robust to such crashes, and delivers excellent performance across a range of workloads. Backpointer-based consistency thus allows NoFS to provide crash consistency without resorting to the heavyweight machinery of traditional approaches. 0x01 基本思路 NoFS的基本思路还是很简单的,如下面的图所示,NoFS通过在一些文件系统的元数据和数据后面添加了一个Breakpointer指针来实现一致性的检查, Paper中对一致性的一个理解就是: Data... Read more!

  • 25 Aug 2018
    Path Hashing and SmartCuckoo

    A Write-Friendly and Cache-Optimized Hashing Scheme for Non-Volatile Memory Systems 0x00 引言 非易失性内存(NVM)是现在的一个研究热点。对于现在存在的一些hash table的算法都不能很好的适应NVM的环境,其主要原因就是NVM写的成本相对来说比较高,而常规的设计会造成很多额外的写操作。这篇paper的主要目的就是减少额外的写操作,同时为cache优化。 0x01 基本思路 这篇paper使用的方法叫做Path hashing ,方法理解起来很简单,文章中的一段话加上一幅图即可: Storage cells in the path hashing are logically organized as an inverted complete binary tree. ... All nodes in the remaining levels are non-addressable and considered as the shared standby positions... Read more!

  • 24 Aug 2018
    Application Crash Consistency and Performance with CCFS

    Application Crash Consistency and Performance with CCFS 0x00 引言 这篇Paper将的文件系统中Crash一致性和性能之间的权衡的问题。Paper的基本思路是提出了stream的抽象,在一个stream之内,操作都是顺序的,但是在不同的stream的时候,操作可以被灵活地重新排序相当于一种带限制的重排序的方式, Further, we show that ccfs performance under standard file-system benchmarks is excellent, in the worst case on par with the highest performing modes of Linux ext4, and in some cases notably better. Overall, we demonstrate that both application correctness and... Read more!

  • 23 Aug 2018
    Soft Updates -- A Solution to the Metadata Update Problem in File Systems

    Soft Updates: A Solution to the Metadata Update Problem in File Systems 0x00 引言 这篇Paper是讨论解决文件系统中一致性问题。关于文件系统中一致性的解决方法主要有Journaling、CoW的解决方式。另外这篇Paper提出的Soft Updates也是一种方法。但是在实际的使用中,Soft Updates并没有得到多少实际地使用,主要是因为其实现的难度很大。一般文件系统使用的还是日志或者是写时复制的技术。 0x01 基本思路 Soft Updates的核心思路是满足更新之间的依赖关系。这些操作的顺序的限制总结起来主要就是3点, 不能指向一个没有初始化的结构,比如一个目录指向的inode必须已经初始化了; 在之前指向一个资源的指针没失效之前不能重新使用,比如必须保证一个inode指向的一个数据块失效之后,这个数据块才能被重新分配; 对于一个存活的资源,在新的指针没有设置之前不能重置之前指向这个存活资源的指针,比如重命名一个文件的时候,在一个新的文件名没有写入的时候不要去移除旧的文件名; 满足这样的要求下,文件系统可以保证正确性,在Crash之后一定会是可以恢复的,但是可以导致磁盘空间“泄露”,这个通过额外的方法解决。Soft Updates通过追踪更新操作之间的依赖关系,来安排写入的顺序来保证一致性。Soft Updates在开始的时候准备使用DAG(有向有环图)来表示这些操作之间的依赖关系(在这些文件系统的操作之中,是很容易造成循环依赖的关系的)。但是在实际考虑之后发现这种方式操作的难度太大,转而使用了另外的方式。在Soft Updates中,依赖的关系是在很小的粒度上面保持的(在字段or指针基本的粒度)。对于每一个更新操作,都会保存之前和之后的版本,以及它依赖的更新操作的链表。 上面的图是一个循环依赖的例子。系统在一个目录下面创建文件A之后,会导致一个目录块到Inode块的依赖关系,前者依赖于后者,所以后者必须在前者之前持久化。之后的操作在该目录中删除了文件B,导致了一个Inode块到目录块的依赖关系。这样就形成了一个循环依赖的关系。这里Soft Upfates解决的方法是回滚操作,Soft Upfates写入的顺序是可以随意的。。加入这里要写入目录的数据块,由于存在被依赖者Inode的数据库,所以不能写入。这里就会暂时地回滚创建A的操作,就可以将其写入,之后在重新操作即可。这里实际上会导致目录块写入两次。 上面的图显示了这样的操作过程。在内存中两个操作完成之后,形成了一个循环依赖的关系。为了写入目录块,写入的是删除文件B之后的目录块,内存中的目录块依赖于Inode块的信息还保留。下一次的操作就是将初始化的A的Inode的Inode块写入到磁盘,满足前面的3点的要求。最后再是写入了添加文件A的目录块更新,所有的依赖关系解除,操作完成。可以发现在这个过程中目录块写入了2次,在中间任何状态Crash的时候,文件系统是安全的,但是可能导致Inode的泄露。 Sofe Updates实现在4.4BSD的FFS中。可以发现,要追踪这类细粒度的依赖关系,实际上是与文件系统实现是强依赖关系的,也就是说Soft Updates实现的可移植性很低。在基于FFS的实现中,主要有4个主要的结构修改需要顺序的更新:1. 块分配,2. 块回收,3. 增加链接(比如创建文件),4. 移除链接。其操作的实现主要就是要满足前面的几个限制条件。具体的信息比较多[1]。 0x03 恢复 和 文件系统语义 在基于Soft Updates实现的文件系统中,在系统Crash之后恢复的时候可以马上挂起使用。文件系统也可能存在以下的一些不一致的状态, 没有使用的Blocks没有出现在空闲空间中; 没有使用的inode被标记为已经使用了; Inode上面的引用计数可以多于实际的值,这个可以导致资源不能及时得到回收。 系统可以通过在后台运行fsck这样的工具来处理这样的情况, Maintaining... Read more!

  • 22 Aug 2018
    Endurable Transient Inconsistency in Byte-Addressable Persistent B+-Tree

    Endurable Transient Inconsistency in Byte-Addressable Persistent B+-Tree 0x00 引言 今天继续来看一篇FAST2018上关于Btree的Paper,这篇Paper主要讲的是在PM(byte-addressable persistent memory)上面的B+-Tree上对数据Cache在CPU的Cache中和需要持久化保存到PM上面的一些问题。Paper主要就是提出了两个算法:Failure-Atomic ShifT(FAST,失败原子性挪动) ,Failure-Atomic In-place Rebalance (FAIR,失败原子性就地重平衡,不要在意这里的翻译(。ì _ í。))。这两种算法的使用使得使用8byte的store指令的时候让B+tree进入另外的一致的状态or或者是另外一种短暂的不一致状态,但是可以在读操作可以容忍这样的不一致的情况。这样就避免了为了保持一直的一致性而需要使用的COW、WAL之类的方法,从而提高性能, • We develop Failure Atomic Shift (FAST) and Failure-Atomic In-place Rebalance (FAIR) algorithms that transform a B+-tree through endurable transient inconsistent states... • We make read transactions non-blocking... 在PM上面实现PM在Paper中主要要解决下面两个问题: clflush and... Read more!

  • 20 Aug 2018
    Optimizations of Ext4 File System

    Evolving Ext4 for Shingled Disks 0x00 引言 这篇Paper是关于ext4文件系统在叠瓦式磁盘上面的一个优化。由于SMR磁盘极差劲的随机写的性能,在ext4原本的工作方式下面,文件系统的性能会下降得非常明显。特别是ext4文件系统还是起源于Unix FFS文件系统,其元数据的写还是一些随机写的操作。这篇Paper讲的就是如何优化ext4文件系统更新元数据时的性能, ... We present benchmarks on four different drive-managed SMR disks from two vendors, showing that ext4-lazy achieves 1.7-5.4× improvement over ext4 on a metadata-light file server benchmark. On metadata-heavy benchmarks it achieves 2-13× improvement over ext4 on drive-managed SMR disks as... Read more!

  • 18 Aug 2018
    Fine-grained TCP Retransmissions

    Safe and Effective Fine-grained TCP Retransmissions for Datacenter Communication 引言 TCP中对于超时重传的时间处理上,为了避免虚假的超时重传,设置来一个最小的超时时间。在Linux上,这个是时间一般是200ms。在广域网上,这个最低的值设置是有意义的。但是在延时很低的数据中心内部,设个时间限制就可能导致一些问题,特别是incast的情况(就是多台机器与一台机器同时通信)。 这篇Paper就讨论了减小这个RTO带来的影响,发现可以通过将这个RTO的最小值设置的很小也能保证安全和效率,同时解决存在的问题。 问题分析 现在常见的RTO计算方式是: RTO = SRTT + (4 × RTTVAR) 考虑到指数退让,这里就是: timeout = RTO × 2 ^ backoff 模拟中这个RTO的最小值对性能的影响,可以看出来RTO的最小值对性能有着明显的影响(模拟情况): Paper中的在实际情况中的测试,也显示出减小RTOmin对性能的影响。 Despite these differences, the real world results show the need to reduce the RTO to at least 1ms to... Read more!

  • 17 Aug 2018
    Strata -- A Cross Media File System

    Strata: A Cross Media File System 0x00 引言 这篇Paper是SOSP’17上面的一篇关于跨介质文件系统的文章。现在的持久化的存储介质有NVM、SSD和传统的HDD,它们有着各自不同的特点。而现在的很多文件系统都是针对其中一种存储介质进行优化,比如NOVA之于NVM、F2FS面向SSD已经ext4对HDD。这篇Paper则提出利用类似LSM-tree的方法,将文件系统系统做成层次化的结构,利用好不同介质的不同的特点。 ... Strata using a 3-layer storage hierarchy of emulated NVM, a flash-based SSD, and a high-density HDD. Strata has 20-30% better latency and throughput, across several unmodified applications, compared to file systems purpose-built for each layer, while providing synchronous and unified... Read more!

  • 15 Aug 2018
    Willow -- A User-Programmable SSD

    Willow: A User-Programmable SSD 0x00 引言 Willow这篇Paper发表在OSDI ‘14上面,关于一个可编程的SSD系统。在不影响现在的文件系统的情况下,Willow通过可以让应用开发一些SSD的一些增强功能来拓展SSD的应用和提高SSD的性能表现。这个的拓展思路和现在的Open Channel、lightnvm很相似,但是在如何去实现可编程拓展SSD功能存在很大的差别。Willow SSD提供的一些功能更像是一种功能增强的“裸”设备, We find that defining SSD semantics in software is easy and beneficial, and that Willow makes it feasible for a wide range of IO-intensive applications to benefit from a customized SSD interface. 0x01 系统设计 下图显示了Willow SSD的一个基本的架构,基本的组件和一般的SSD没有很大的差别。在结构上面,一个Willow的SSD会包含一组的storage processor units (SPUs),一个SPU包含了一个微处理器以及与其它的SPU连接的接口,一组non-volatile的存储介质。在每一个SPU上面,运行一个很小的操作系统SPU-OS 。... Read more!

  • 13 Aug 2018
    NOVA-Fortis -- A Fault-Tolerant NVMM File System

    NOVA-Fortis: A Fault-Tolerant Non-Volatile Main Memory File System 0x00 引言 这也是SOSP’17上面一篇关于NVM上面文件系统设计的Paper。NOVA-Fortis是在之前的NOVA文件系统之上功能增强发展而来, NOVA-Fortis’ reliability features consume 14.8% of the storage for redundancy and reduce application-level performance by between 2% and 38% compared to the same file system with the features removed. NOVA-Fortis outperforms DAX-aware file systems without reliability features by 1.5×... Read more!

  • 11 Aug 2018
    HopsFS -- Scaling Hierarchical File System Metadata Using NewSQL Databases

    HopsFS: Scaling Hierarchical File System Metadata Using NewSQL Databases 0x00 引言 ​ 这篇Paper讲的是在Hadoop FS基础上的一个进化。主要讨论如果优化Haddop的NameNode。Hadoop FS基于的是GFS的设计,其元数据是保存在NameNode的内存中。在Google的GFS的下一代的CFS中,这部分的元数据被保存到了分布式的存储系统之上(Bigtable?)。CFS目前还没有发表论文介绍。这篇Paper的基本思路也差不多。它通过讲分布式文件系统的元数据保存到NewSQL之上,实现了比原来的Hadoop FS强大得多的拓展性。这里可以看作是Hadoop FS中NameNode设计的一个进化,基本的工作方式还是没有变化了,而且HopsFS和Hadoop FS的客户端还是兼容的,只是使用Hadoop的客户端可能某些功能就发挥不出来, we introduce HopsFS, a next generation distribution of the Hadoop Distributed File System (HDFS) that replaces HDFS’ single node in-memory metadata service, with a distributed metadata service built on a NewSQL database.... Read more!

  • 09 Aug 2018
    Three Papers of the BetrFS

    BetrFS: A Right-Optimized Write-Optimized File System 0x00 引言 BetrFS是一个以TokuDB为基础的文件系统。它有以下的几个特点:1. 基于写优化的数据结构Bε-tree;2. 将文件系统的操作转化为TokuDB的Key/Value操作;3. 自身不能算是一个完整的操作系统,空闲空间管理等其实还是要利用ext4文件系统,也就是BetrFS其实是一个构建在ext4文件系统上面的文件系统, On one microdata benchmark, BetrFS provides more than 4× the performance of ext4 or XFS. BetrFS is an ongoing prototype effort, and requires ad- ditional data-structure tuning to match current general-purpose file systems on some operations such as... Read more!

  • 06 Aug 2018
    UpBit -- Scalable In-Memory Updatable Bitmap Indexing

    UpBit: Scalable In-Memory Updatable Bitmap Indexing 0x00 引言 Bitmap索引在一些情况下是一种非常有用的索引。它在一个字段的取值范围只是确定的一个较小的集合时很有用。一个基本的bitmap index如下图。途中一个字段的取值可能为3个值,每一个可能的取值会用一个bitvector标识。很显然,这样的方法在取值的范围更加大的时候会有很多的内存的消耗,而且存在优化的空间。所以bitmap index会采取一些压缩编码的测量。这样的好处就是减少了内存的使用,缺点就是每次的更新操作都需要进行解码编码的操作,减低了更新操作的性能。 已有的一些解决办法比如Update Conscious Bitmaps,使用了将一些更新的信息追加到结构的末尾。同时将原来的位置的值置为无效,如果只是删除的话直接置为无效几个。这个标记有效的结构为另外的一个bitvector。 0x01 基本思路 UpBit使用的思路是同时维持一个V bitvector,标记值,另外一个U bitvector,标记更新。基本的结构和操作如下, 这样看来会增加空间的消耗。但是实际上这个增加的很小。一个原因是这个U bitvector在开始的时候均为0,这个很容易拥一个很小的空间表示,而不用实际去分配这样一个bitvector。另外,在添加了这个U bitvector之后怎么操作还是很显然的。 ... In particular, the current value of a row of the UpBit is given by the XOR between the corresponding position of the value and the update bitvectors.... Read more!

  • 04 Aug 2018
    All File Systems Are Not Created Equal

    All File Systems Are Not Created Equal: On the Complexity of Crafting Crash-Consistent Applications 0x00 引言 这篇Paper是一篇关于Crash-Consistency的Paper。对于如何写出正确的文件操作的代码很有价值。Paper中提出了一个BOB的工具来测试文件系统的persistence properties,开发了一个ALICE的工具来分析应用代码的crash vulnerabilities。 0x01 持久化特性 文件系统的持久化特性决定了持久化特性在一个操作执行的时候,发生了错误最终文件系统中数据的情况。Paper 中测试了多种的Linux下面的文件系统ext2、ext3、ext4、btrfs、xfs 和 reiserfs。应用层面的Crash一致性很依赖于文件系统的持久化特性。下面举一个🌰, write(f1, "pp"); write(f2, "qq"); 这个看上去直观的操作在操作的过程中系统发生Crash的情况下最终文件中的结果却不是很直观。这里将写入操作都是为append操作。系统在操作中间发生Crash可能出现的一些情况。如果添加的操作不是原子的,如果文件系统先修改元数据,在修改了文件的元数据之后,就可能出现A、B的情况,A出数据没有实际写入,文件中的数据是垃圾数据,B中则是没有写入完整。另外,现在的文件系统(整个IO栈都是)一般都是乱序的,也就是说上面代码中写入f2在后面,而实际可能是f2先完成操作。保证A情况不出现的性质叫做 size-atomicity,保证B情况不出现的content-atomicity。而乱序,是现在的IO栈默认的情况,谈不上正不正确,只是进行文件操作的时候也特别注意这样的可能的乱序的现象。 作者开发了Block Order Breaker (BOB)的工具检测现在的文件系统的持久化特性,下面是一个总结的表, 原子性,在上面的表中,所有的文件系统所有的配置情况都提供了单个扇区的覆盖写的一致性,一些文件系统的这个性质依赖于底层存储设备写入一个扇区的原子性(现在的存储设备应该都支持这个特性)。在一些新的存储介质上面,比如非易失性内存,它提供byte级别的写入原子性(一般最多为8bytes),而不是扇区级别。由于添加一个扇区涉及到数据块的写入和文件元数据的修改,所以这里有些文件系统是不能保证原子性的。对于一个or多个块的覆盖写,则比一个or多个块的追加更加难以处理,这个一般地使用日志、CoW等的机制来保障。支持这2个特性的文件系统就少多了。而文件系统的操作一般都能保证一致性(处理ext2),这个主要得益于日志or CoW技术地使用。 顺序,在数据日志的模or sync模式下面,几个文件系统的顺序都是保证,但是结果就是较低的性能。文件系统的延迟分配技术会影响都最佳操作的顺序。 0x02 ALICE工具 ALICE会将文件的操作抽象为逻辑操作,例如write(), pwrite(), writev(), pwritev(),和 mmap()等的操作都会被转化为overwrite 或者是 append这样的逻辑操作。基于Abstract Persistence Model(APM),利用这些逻辑操作构建依赖关系。... Read more!

  • 02 Aug 2018
    HashKV -- Enabling Efficient Updates in KV Storage via Hashing

    HashKV: Enabling Efficient Updates in KV Storage via Hashing 0x00 引言 这篇Paper主要讲的是在WiscKey上面的优化。基本的思路是在WiscKey的Key Value分离设计的技术之上,通过Hash将分区的方式来解决WiscKey中的一些问题,比如GC成本太高的问题。 HashKV uses hash-based data grouping, which deterministically maps values to storage space so as to make both updates and GC efficient. We further relax the restriction of such deterministic mappings via simple but useful design extensions. We... Read more!

  • 01 Aug 2018
    Read-Log-Update and Interval-Based Memory Reclamation

    Read-Log-Update – A Lightweight Synchronization Mechanism for Concurrent Programming 0x00 引言 RLU可以看作是RCU的升级版本。RCU在Linux Kernel 中已经得到广泛的应用了。但是其也存在一些缺点,最大的一个缺点就是很难用,其次就是只适应有很少的write操作的情形,最后就是等待读者完成操作的延时问题(具体看看RCU有关的东西?)。RLU则可以解决RCU存在的一些问题: RLU provides support for multiple object updates in a single operation by combining the quiescence mechanism of RCU with a global clock and per thread object-level logs. 0x01 基本思路 通过使用综合了结合global clock的RCU的quiescence机制和 thread直接独立的object logs,RLU一个操作支持多个对象更新。RLU有以下的基本思路,这一部分先假设写都是顺序进行的: 所有操作在开始都要读取global clock(g-clock)到自己线程局部的l-lock中,使用这个lock来对共享的对象解引用; 对于更新操作,一个线程先将对象拷贝到自己的log中,在自己的log中操作这个对象,这里要获取object(s)的lock;这里读操作不需要申请任何lock(s),可以直接访问对象;... Read more!

  • 31 Jul 2018
    Memory Checkpoint

    Memory Checkpoint 0x00 引言 这篇总结总结的是3个为内存数据库设计的checkpoint的算法,一个发表在SIMOD2016[1],另外两个出自一篇Paper[2],发表在SIGMOD 2011。这两个Paper讲的是同一个问题,如何在内存中实现 checkpoint-recovery or snapshot算法。 0x01 Wait-Free Zigzag 这个算法出自[2]。基本思路如下: 在这个算法中的开始,系统的状态会被拷贝为2份,AS0 和 AS1,这两个数组的一个字就代表了一个状态信息。另外还有两个数组MR 和 MW,MR的一个bit,MR[i]用来指示应该从哪一个AS中读取,而后者则是指示应该写入哪一个AS,前者初始化为0,而后者初始化为1。在进行checkpoint操作的周期内,MW的值不会变化,这个保证了它不会写入的AS的值不会变化,而synchronous Writer操作就是讲这些words写入到磁盘以设置checkpoint。在更新一个状态值的时候,会写入MW[i]指示的位置,同时把MR[i]设置为MW[i]一样的值。这个算法理解起来很容易,结合下面的图很显然, 伪代码, input: /* ApplicationState is a vector containing words */ ApplicationState AS0 ← initial application state ApplicationState AS1 ← initial application state /* size of application state in words */ sizeWords... Read more!

  • 30 Jul 2018
    PebblesDB -- Building Key-Value Stores using Fragmented Log-Structured Merge Trees

    PebblesDB: Building Key-Value Stores using Fragmented Log-Structured Merge Trees 0x00 引言 这篇Paper也讲的是如何优化LSM-Tree写入放大问题。与前面有写过的WiscKey不同,PebblesDB在LSM-Tree的结构上面做了很大的优化,不像WiscKey一样的依赖于SSD之类的硬件。它的使用了一种新的叫做Fragmented Log-Structured Merge Trees (FLSM) 的数据结构,基本思路和Skip List中的一些思想类似。从算法上面比较好的解决了这个写入放大的问题, We evaluate PebblesDB using micro-benchmarks and show that for write-intensive workloads, PebblesDB reduces write amplification by 2.4-3× compared to RocksDB, while increasing write throughput by 6.7×. We modify two widely-used NoSQL stores,... Read more!

  • 29 Jul 2018
    WiscKey -- Separating Keys from Values in SSD-conscious Storage

    WiscKey: Separating Keys from Values in SSD-conscious Storage 0x00 引言 这篇Paper将的都是如何解决LSM-Tree的写放大的问题。Wisckey的基本思路其实很简单,使用的方法就是将Key和Value分开保存的方式,对于读取Value时造成的随机读写问题,Wisckey则认为这个在SSD上的问题能得到缓解,也使用了预取,并行读等的一些优化方式。在SOSP‘17上面的PebblesDB则对LSM-Tree的结构进行了比较好的改进,个人认为这个是一种更加好的方式。WiscKey的设计目标是为随机性能比较好的SSD优化的,因为它的设计会导致比较多的随机读,它在测试数据中实现了, We demonstrate the advantages of WiscKey with both microbenchmarks and YCSB workloads. Microbenchmark results show that WiscKey is 2.5×–111× faster than LevelDB for loading a database and 1.6×–14× faster for random lookups. WiscKey is faster than both LevelDB and... Read more!

  • 28 Jul 2018
    Dostoevsky -- Better Space-Time Trade-Offs for LSM-Tree

    Dostoevsky: Better Space-Time Trade-Offs for LSM-Tree Based Key-Value Stores via Adaptive Removal of Superfluous Merging 0x00 引言 这篇Paper是SIGMOD‘17上面的Monkey的后续的文章,都来自哈佛大学同一个实验室,讲的都是LSM-tree的一些优化。这篇Paper消除一些不必要的merge的问题, ..., we introduce Lazy Leveling, a new de-sign that removes merge operations from all levels of LSM-tree but the largest. Lazy Leveling improves the worst-case complexity of update cost while maintaining the... Read more!

  • 26 Jul 2018
    Cuckoo Filter and Cuckoo Switch

    Cuckoo Filter: Practically Better Than Bloom 0x00 引言 Cuckoo Filter是一种功能类似Bloom Filter的数据结构,它最大的一个特点就是支持删除,前在很多的情况下都实现了比Bloom Filter更加好的性能, the cuckoo filter, a practical data structure that provides four major advantages. 1. It supports adding and removing items dynamically; 2. It provides higher lookup performance than traditional Bloom filters, even when close to full (e.g., 95% space... Read more!

  • 25 Jul 2018
    SuRF -- Practical Range Query Filtering with Fast Succinct Tries

    SuRF: Practical Range Query Filtering with Fast Succinct Tries 0x00 引言 这篇Paper是SIGMOD2018得best paper。Succinct Range Filter (SuRF)是为了解决Bloom Filter不支持范围查找设计的。基与Succinct一种, Fast Succinct Trie (FST), Our experiments on a 100 GB dataset show that replacing RocksDB’s Bloom filters with SuRFs speeds up open-seek (without upper-bound) and closed-seek (with upper-bound) queries by up to 1.5×... Read more!

  • 23 Jul 2018
    Monkey -- Optimal Navigable Key-Value Store

    Monkey: Optimal Navigable Key-Value Store 0x00 引言 Monkey解决的一个问题就是如何寻找LSM-Tree中最佳的Bloom Filter的设置的问题。在LSM-Tree中,查找的时候会先使用Bloom Filter(or其它类似的数据结构)来过滤不必要的查询,减少在磁盘的数据上面查找的次数。在一般的基于LSM-Tree的系统上面,这个Bloom Filter的false positive rates在每一次层都是固定的,比如均为0.82%。在实际的系统,每一层的数据访问的量和访问的成本是不一样的,这里一个显然的思路就是将访问次数过多的、访问成本更加高层的Bloom Filter的false positive rates更加低,能获得更好的性能。下面的图就基本展示它的基本的原理, 0x02 基本思路 下面是在Paper中出现的一些符号的解释: 关于Tiered和Leveled合并方式的区别可以参考相关资料。这里先是一些基本的知识: LSM-Tree高度的证明 设内存中一个buffer的大小计为M_{buffer},大小记为B,内存中buffer的数量为P,E为数据项的平均大小,这样可以得到LSM-Tree的层高为(每一个符号的意思参照上面图中的表): \(\\ L = \lceil log_{T}( \frac{N \cdot E}{M_{buffer}} \times \frac{T-1}{T}) \rceil\) 证明: 假设每一层都达到最大的容量,则总的数据项有: \(\\ 第i层的大小为 P \cdot B \cdot T^{i}, \\ 则总数有N = P \cdot B \cdot T^{0}... Read more!

  • 22 Jul 2018
    Many Tries

    Many Tries 0x00 引言 前面的SIGMOD‘18 上面的文章提出来一个新的数据结构HOT,是一种trie的变体。里面提到了不少相关的结构,总结如下。另外这些结构能够应用的范围都比较窄。 0x01 Patricia trie Patricia trie是出现的非常早的一种trie的变体。Patricia trie的论文也很长。这里主要关注它的一个优化就是将只有一个字节点的数据直接保存到父节点中。就是对于一条长链时的节点, -> A -> B -> C -> D 每一个节点都只有一个子节点,那么久可以直接保存为一个节点, -> ABCD. 这种优化方式在一些情况下能取得很好的优化的效果。在adaptive radix tree中也使用了这样的方法优化。 0x02 BURST-Trie BURST-Trie是一种Trie和其它数据结构结合而来的。BURST-Trie的内部节点就是一般的trie的节点,而外部节点时其它的数据结构,这个结构并不固定是哪一种。 BURST-Trie这么设计的原因也是利用叶子节点来减少trie内存的使用。这里的叶子节点可以就是一棵平衡树或者是类似的节点即可。在这个叶子节点到达一定大小的时候,会被“burst“,即这个叶子节点拆分为更多的叶子节点,同时添加必要的中间的trie节点。 BURST-Trie在一些倒排索引中有使用。 0x03 HAT-Trie HAT-Trie 也可以就看作是BURST-Trie 的一个变体。它使用的叶子节点的结构时hash table。在HAT-Trie 中有两种类型的叶子的hash table, pure,在这个hash table中的数据共享一个前缀,保存的时候可以去除这个前缀; hybrid,hybrid的hash table包含来来自多个内部节点的数据,为了区分来自哪一个内部节点,需要一些前缀信息。使用hybrid的好处就是对这类节点burst操作的时候直接拆分即可,另外就是可以进一步减少trie占用的内存。 HAT-Trie的一个缺点也是来自使用hash table,由于hash table是无序的,在处理点查询的时候还好,处理范围查询的时候可以处理起来比较麻烦。 0x04 KISS-Tree KISS-Tree是一种十分简单,易于实现,Larch-free的实现起来也比较简单(还是因为它足够简单)。KISS-Tree的主要缺点就是应用范围很有限,只能应用在32bit的整数的情况下,KISS-Tree在它适用的范围内还是非常优秀的,也可以在它思路之上拓展一下适用的范围。它将32bit的整数分为3个部分,有点像现在的多级页表的实现,但是它每一层的长度和实现的方式不同。 第一次层是虚拟的,长度为16bit,用来直接定位第二层;... Read more!

  • 20 Jul 2018
    A Height Optimized Trie Index for Main-Memory Database Systems

    HOT: A Height Optimized Trie Index for Main-Memory Database Systems 0x00 引言 Height Optimized Trie (HOT) 是一种新的为Main-Memory Database设计的新的数据结构。实现了非常的性能和非常低的内存占用: 从这里看,HOT的内存占用低到惊人。在上面的几种结构来说,HOT、BTree、Masstree以及ART,后面的三种相对的结构都比较直观,而HOT这里就稍微复杂精巧一些。HOT开源的实现代码也比较复杂。 ### 0x01 基本思路 ​ 在介绍HOT的思路之前先来看看之前是如何优化Radix Tree的内存占用的。低一个基本的方法是压缩路径,对于一个长链,可以压缩为一个结点。第二个是ART[2]的办法,使用自适应的节点大小(还有其它的一些方法)。这些方法的一个特点就是一个节点的大小都是固定的,比如在ART是固定的1byte。HOT这里使用的方法是自适应的节点大小(在bitwise trie中为1bit,在ART中为1byte,在HOT中这个是不确定的)。可以想象,对于key很长的例子,它肯定是稀疏的(至少在这个key中部分段是稀疏的),要不然key的数量就爆表了。这样的话稀疏的话就可以将每一层到下一层代表的bit数变大,高度自然就变小了。密集则反之,可以想象到如果这些key密集地出现不同,那么这个密集的区域是很小的,因为32bit长的变化就是42亿多了,如果这么密集的不同那么key的数量就会非常大。 ... we propose to set the span of each node adaptively depending on the data distribution. Thus, dense key regions (e.g., near the root)... Read more!

  • 19 Jul 2018
    Automatic DBMS Tuning Through Large-scale Machine Learning

    Automatic Database Management System Tuning Through Large-scale Machine Learning 0x00 引言 这是一篇很赞的Paper。这篇Paper代表的思路很有可能引起后面更多的研究,而且在以后有很大的应用空间。利用机器学习来自动调优数据库是一个很有吸引力的事情。在之前有自动调优的一些研究称之为Self-Tuning Database System。数据里面会有成百上千的参数来调整数据库运行时候的一些行为,这篇Paper提出了数据库自动调优核心问题之一就是如何找到影响到数据库性能表现的关系参数,这里称之为knobs。为了解决这个问题,这里引入了机器学习的方式,使用监督学习和非监督学习的方式,由于实现,1. 找出这些knobs,2. 对于未曾出现的workloads,从之前出现过的workloads中找出类似的,3. 给出这些“knobs”参考设置,优化系统性能。 0x01 基本架构 OtterTune的基本架构如下图所示。主要由两个部分组成,一个部分是客户端的Controller,它于目标的数据交互。它收集通过标准的API收集数据库运行时的一些数据,也会负责将新的数据配置发送到数据中。另外的一个部分是Tunning Manager,它接受来自Controller收集到的信息,并将其数据保存。保存的数据不会包含数据库的任何机密的信息,只会保存一些配置的数据和一些性能数据。由于不同的数据版本之间的配置参数等存在一些差异,所以OtterTune会将这些数据会根据数据库的版本保存,使用这个OtterTune的一个例子, 在开启一个tuning session的时候,DBA告诉OtterTune什么指标是准备要去调优的,比如吞吐、延迟等。OtterTune COntroller之后会连接数据库获取硬件配置和目前的knob配置。这里假设和谐硬件配置不是随机的,而是从一个硬件配置的列表中选择的一个,这个在云计算的环境中问题不大。Paper中提到更加广泛的硬件支持会是未来的工作; Controller之后开始一个observation period。这一步会花费一些时间来测量一些需要的数据。DBA可以选择让数据执行一组查询或者是一个特定的workload的追踪,这些操作是数据获取的来源,这个时间段内收集的指标一般为外部可见的一些指标,比如说吞吐,延迟。在这个observation period结束之后,Controller会收集DBSM特定的内部的一些Metrics,比如MySQL从磁盘上面写入和读取的Page的数量统计。不同的DBMS提供了很多类似的指标数据,但是OtterTune不需要提供这些数据的含义具体是什么,后者是相同含义的参数在不同的数据库中有不同的名字,这些数据OtterTune都是不需要。 在Tuning Manager收到了这个observation period收集到的数据之后,这些数据会先被保存起来。基于这些数据,OtterTune计算出来下一个数据的配置参数。这步主要分为两个步骤,第一步会将这个workload的特点映射到之前一个已经知道的workload的特点上面。第二步根据这个硬件和这些数据得到一个推荐配置。这里也会给DBA提供一个控制的接口。 OtterTune的设计中存在一些假设和一些限制。OtterTune的一些操作是需要Admin级别的的权限的。由于数据有些设置在数据库中是在启动的时候就确定了的,且在运行中不能更改,所有未来更新参数,在必要的时候可能需要数据库重启。 0x02 Workload特性&Knobs OtterTune探究数据库Workload的特性并不是完全从数据当前的出发,给出一个数据库当前Workload的特性描述,而是根据目前的一些数据寻找OtterTune以及预先知道的一些Wrorkload特性的相同or相似点。在探究Workload的特性上面,OtterTune这里提出了两种基本的方式, 第一种是直接从逻辑的层面上起理解。这些逻辑上的信息可以利用数据库的优化器。这样的缺点时不能很好地反映数据实际运行的信息,也不能很好地表示出一个Knobs参数改变后数据库的影响。 另外一种OtterTune采用的方式,这种方式总体上来看更好一些。这种方式直接利用数据库运行时候内部的统计的一些Metrics。现代的数据一般都在数据内存记录了大量的数据内部统计的一些信息,比如在MySQL InnoDB存储引擎中会统计Page读取和写入数量的信息,Queue Cache的利用率以及锁开销的一些信息。OtterTune通过这些内部的统计信息来标示出一个Workload的特性,这种方式的一个优化是这些统计信息反应的是数据库运行时候实际的特点,另外的一个优点是这些统计信息的值直接被Knob配置影响,不如如何配置Buffer Pool小了,在内部的统计数据中就会Buffer Pool的Cache缺失率上升。一般的数据库系统都有这样的一些统计信息,在不同的数据中这些统计信息的名字可能不同,这也是OtterTune设计为它不需要知道数据库中一个参数的含义的重要原因。 在决定来获取Workload特性的策略之后,下面要做的事就是如何获取这些统计信息,以及对统计信息进行一些处理,取出掉一些无用的信息, 信息收集,OtterTune将数据收集的操作划为为一个个的observation period。在每一个period开始的时候重置所有的统计信息,信息收集的这一步由于OtterTune最终哪些数据会有用,OtterTune这里就直接收集可以收集到的所有的信息。这些数据以Key-Value Pair的方式保存。这里还有另外的一个问题要处理,就是不同的数据库系统中这些数据统计的一个“精细”程度的不同,比如在MySQL中,这些统计信息是统计了整个数据库层面,而在其它的一些系统中,统计的是表层面或者是库层面的。为了简化处理,这里都使用了一个总的统计数据,更加细层面的数据统计处理会是以后的工作内容。 去除无用的Metrics,在收集了统计信息之后就是自动去除一些无用的数据。如果不去出一些无用参数,这样算法需要计算的空间会是一个极其大的值。多余的统计数据一般有两种出现原因,一种是不同的统计数据统计的是相同或者是很类似的数据,比如MySQL中统计的Pages读取数量和Bytes统计数。另外一个原因是这些数据虽然含义不同,但是它们之间是强相关的,知道了一个就基本上可以推导出另外的参数是个什么情况。来实现去除这些冗余数据的两种基本方式是factor analysis和k-means。前者用于高维的数据转化为更低维的数据,后者拥有是被出油强相关的统计参数,这个是一个常见的聚类的问题, Knob Configuration是OtterTune的一个核心的概念。在数据众多的参数设置中,不是所有的设置都对数据库的性能有显著的影响,在有显著影响的参数里面,也会有对数据性能影响程度的一个差别。将这些显著影响数据性能的参数找出来,可以大大减少需要工作量。这里的基本方式是线性回归的方式,找出对数据性能有这明显关系的参数。这里使用的方法是Lasso,具体内容TODO。 0x03 自动调优... Read more!

  • 15 Jul 2018
    Contention-Aware Lock Scheduling

    Contention-Aware Lock Scheduling for Transactional Databases 0x00 引言 这篇Paper是一篇比较有意思的Paper,这个算法已经被MySQL 8.0采用了。文章一步一步的说明思路,从简单的想法开始,最终得出来 Largest-Dependency-Set-First 和batched Largest-Dependency- Set-First 两种算法。 0x01 背景与动机 简而言之就是:Our goal is to find a lock scheduling algorithm under which the expected transaction latency is minimized.很不幸的是,这个问题是个NP问题,找到最优的解是不现实的。所以这里只能使用近似的方法。Paper中给出了一些概念,这里就不仔细去说这些概念了. 这里只说一下Dependency Graph,这对理解算法很重要: Dependency Graph 这里定义了这么多的东西,就是为了描述txn之间通过lock而形成的依赖关系。这个依赖图是理解后面算法的核心。这个本身比不复杂。 下面是两个例子, 0x02 算法 接下来就是讨论了几类算法,并分析了优缺点。 Most Locks First (MLF) The intuition is... Read more!

  • 14 Jul 2018
    Tree Indexing on Solid State Drives and LSbM-tree

    Tree Indexing on Solid State Drives 0x00 引言 这篇文章讨论的是如何在SSD上面优化树形索引。这个设计主要基于下面的几个在SSD上面设计indexing的原则: 将随机写转化为顺序写,这个在SSD和HHD上面都是一样的思路; 将随机写限制在一个小的区域内,SSD在一个小的区域内(512KB-8MB)的随机写的性能能够比得上顺序写; 支持多个page的IO操作。 ... shows that the FD-tree captures the best of both search and insertion performance among all competitors. In particular, it is 5.7-27.9X, 1.4- 1.6X and 3.7-5.5X faster than B+-tree, LSM-tree and BFTL, respectively, under various mixed workloads on... Read more!

  • 11 Jul 2018
    Hybrid Garbage Collection for Multi-Version Concurrency Control in SAP HANA

    Hybrid Garbage Collection for Multi-Version Concurrency Control in SAP HANA 0x00 引言 MVCC是数据库中最常用的并发控制的方式,没有之一。这篇Paper讨论的是MVCC中的GC的问题。由于MVCC的每次的更新操作,包含添加、更新和删除等都会产生一个新版本的数据(一个完整版本的新纪录,或者是纪录新旧版本之间的差异),这些都要处理的一个问题就如果在合适的时候及时的回收这些数据,以便释放其占用的空间,还能提高性能。一个版本的数据如果多所有的运行中的时候都不可见的时候,这个版本的数据就可以回收。所以最常见的GC方式就是以目前还存在的事务的最小的事务ID作为GC的参数。不过这中方式的一个缺点就是如果存在长事务的话,会阻塞这个事务执行期间的垃圾回收。而这篇Paper处理的一个核心的问题,提出几种GC混合使用的策略, ... we present an efficient and effective garbage collector called HybridGC in SAP HANA. HybridGC integrates three novel concepts of garbage collection: timestamp-based group garbage collection, table garbage collection, and interval garbage collection. Through experiments using mixed... Read more!

  • 08 Jul 2018
    Many B-trees

    Many B-trees 0x00 引言 Btree及其变体可以是是最重要和使用最广泛的较复杂的数据结构之一了。对Btree的改进页非常多,从传统的面向机械硬盘等存储介质的优化,到为内存实现的优化,再到现在的为非易失性内存的优化以及写优化等等的很多很多的变体。这里就简单地总结了若干的Btree的变体。在之前的看过的论文中包括了一些B-Tree的变体: Masstree、PLAM、Bz-tree以及Bw-tree。 0x01 Bε-tree Bε-tree是Btree的一个写入优化的版本(保存在磁盘上时),它的思路的是在一个内部节点不仅仅保存Key和指向下一层节点的指针。还包含了一部分的Buffer空间。数据添加的时候先添加到这个Buffer,在Buffer中数据的数量达到一定量的时候将其“下推”。Bε-tree这样的做的优化就是使得小数据量的写入可以先集中写,也可以实现在一个地方将写入累积其它,达到一定量的时候在写入下层对应的位置。 Bε-tree这样的做的缺点就是结构的复杂程度会提高,实现起来更加复杂。另外就是范围操作的时候可能麻烦不少。Bε-tree在BetrFS中得到了应用[3], 0x02 Write-Optimized B-Tree Write-Optimized B-Tree出自论文[4],它是在B+tree的一些优化。它在B+tree的修改体现在下面的几点: 在B+tree中,当叶子节点迁移到一个新的位置之后,由与他的兄弟节点保存了它的Page ID的信息。这个信息用于加快范围查找。缺点就是可能导致级联的更新操作,移动一个节点的时候这样只需要更新父节点的对应的信息即可。WO-Btree则去除了这个兄弟节点的指针,引入了fence key的概念。节点保护了两个fence key,标识了这个节点内Key的范围; 在去除了兄弟指针之后,WO-Btree就不同担心级联更新的问题,页面移动变得更加方便和低成本了。WO-Btree写入更新之后的Page是写入到一个新的位置,而不是就地更新,优点类似于COW。 去除了兄弟节点可以对范围查找操作又一些不利。 0x03 NV-Tree NV-Tree为Btreee在NVMM环境下的一个优化的变体。主要的思路就是3点: 选择性的强制数据一致性。在直接寻址NVMM的时候,要经常使用flush缓存以确保数据都持久化到NVMM上面。这这个操作对性能的影响比较大。NV-tree的做法是只对叶子节点确保这样的数据的强制一致性,而对内部节点,则认为内部节点完全可以从叶子节点重新构建处理,这里就发送了它的数据一致性; 数据项在叶子节点无序保存,这个的设计简化了叶子节点一些操作,同时也降低了一致性的成本。 内部节点使用缓存优化的格式,在NV-tree中,所有的内部节点按缓存行对齐保存在连续的内存中,使用偏移寻址而不是直接使用指针。这样的一个缺点就是内部节点需要添加or删除的时候会重建整个的内部节点。 0x04 FP-Tree FP-Tree在不少地方的设计和NV-Tree类似,另外FP-Tree还加入了其它的一些优化。 FP-Tree的做法是将内部节点保存在传统的内存中,而叶子节点保存在非易失性内存中。FP-Tree在一般的B+Tree的基本上的优化的几个点: Selective Persistence, FP-Tree的内部节点保存在DRAM中,而叶子节点保存在非易失性内存中; Fingerprinting,Fingerprinting是叶子节点Key的一个1byte的hash值,连续地保存在叶子节点的前面。在FP-Tree中,和NV-Tree一样,它的叶子节点也是没有排序的,使用这个方法可以加快查找的速度。这种方式在一些Cuckoo Hash Table的设计中也有类似的思路。 Selective Concurrency,对于叶子节点,FP-Tree使用细粒度的锁,而对于内部节点,使用HTM。 查找算法: while TRUE do speculative_lock.acquire(); Leaf = FindLeaf(K); if Leaf.lock ==... Read more!

  • 04 Jul 2018
    Amazon Aurora -- On Avoiding Distributed Consensus

    Amazon Aurora: On Avoiding Distributed Consensus for I/Os, Commits, and Membership Changes 0x00 引言 这篇Paper是Amazon发表的第二篇关于Aurora的文章,这篇文章讨论的是一些一致性的问题。看这篇文章之前,最好看过了[2],包含了: We describe the following contributions: (1) How Aurora performs writes using asynchronous flows, establishes local consistency points, uses consistency points for commit processing, and re-establishes them upon crash recovery. (Section 2) (2) How Aurora avoids... Read more!

  • 28 Jun 2018
    Building a Bw-Tree Takes More Than Just Buzz Words

    Building a Bw-Tree Takes More Than Just Buzz Words 0x00 引言 Bw-Tree是Microsoft Research发明的一种lock-free(在数据库中应该叫做latch-free)的数据结构,被用在Microsoft的内存数据库产品中,在CMU的学术型数据库peloton中也采用了这种数据结构。这篇paper就是CMU对其在peloton中实现中,对Bwtree的一些更加详细的讨论。从paper中得出的结论来说,Bwtree是有复杂而且在不少方面表现却比一些更加简单的、非lock-free的数据结构要差。 关于 Bwtree的论文之前有两篇, 不过这篇是讲的最清晰的。 0x01 基本结构 先来看一张图: Bwtree的4个核心内容: Base Nodes and Delta Chains 以目前的硬件,由于没有支持多CAS的(有软件的实现,之后在看看, ^_^)。所以直接修改B+tree的节点来实现lock free是不太行的通的。所以Bwtree使用了 Delta Chains的方法, Delta Chains实际上就是一个对节点修改的操作的链表。实现lock-free的链表相对来说简单多了。当这个 Delta Chains长度达到一定程度的时候,就利用这个 Delta Chains和原来的base node构造新的node,替换原来的node。这样通过一系列的操作转换,巧妙的将其转换为了lock free的结构。 Mapping Table 在原来的论文中,Mapping Table 的存在不仅仅是为了将更新node变为lock free的,还有为这个结构同时支持memory和SSD之类的多级存储的功能。在这篇文章中只在意在内存中(因为peloton是一个内存数据库). The Bw-Tree’s centralized Mapping Table avoids... Read more!

  • 24 Jun 2018
    High-Performance Concurrency Control Mechanisms for Main-Memory Databases

    High-Performance Concurrency Control Mechanisms for Main-Memory Databases 0x00 引言 Hekaton是微软SQL Server中内存数据库的一个部分。之后微软在这个方面发了很多的文章。这篇主要讲的是内存数据库的并发控制机制。这篇Paper中同时说明了一个多版本和单版本的实现,它们有着各自适应的环境, ... We also implemented a main-memory optimized version of single-version locking. Experimental results show that while single-version locking works well when transactions are short and contention is low performance degrades under more demanding conditions. The multiversion schemes have higher... Read more!

  • 18 Jun 2018
    Fast Serializable MVCC for Main-Memory Database Systems

    Fast Serializable Multi-Version Concurrency Control for Main-Memory Database Systems 0x00 引言 这篇Paper讲的是Hyper内存数据库中MVCC的实现。和前面看过的一些内存中MVCC or OCC的实现相比,Hyper数据库突出了能够处理好OLTP的任务,也能处理好OLAP的任务,在Paper中特突出了实时分析的应用。因此Hyper数据库的MVCC的设计也为这样的设计目标做了优化, Compared to our single-version concurrency control implementation, our MVCC implementation costs around 20% of performance. Still, more than 100k transactions/s are processed. This is true for our column- and a row-based storage backends. We also compared... Read more!

  • 10 Jun 2018
    Dependably Fast Multi-Core In-Memory Transactions

    Cicada: Dependably Fast Multi-Core In-Memory Transactions 0x00 引言 这篇paper是关于一个内存数据库MVCC实现的文章。在读这篇paper之前,最好读一下[2]。这篇文章基本就是从[2]中提到方面进行设计的。Cicada是最近的一些关于MVCC在内存数据库中的优化的很全面的一篇了,Paper应用了很多种的优化方法,取得了比其它类似的一些系统明显的优势, On the TPC-C and YCSB benchmarks, Cicada outperforms Silo, TicToc, FOEDUS, MOCC, two-phase locking, Hekaton, and ERMIA in most scenarios, achieving up to 3X higher throughput than the next fastest design. It handles up to 2.07 M TPC-C transactions per second... Read more!

  • 06 Jun 2018
    FOEDUS -- OLTP Engine for a Thousand Cores and NVRAM

    FOEDUS: OLTP Engine for a Thousand Cores and NVRAM 0x00 引言 FOEDUS是一种同时使用DRAM和NVRAM的内存数据库。FOEDUS的一个核心的idea是Dual Page。一个Dual Page指针指向两个逻辑上相等的数据Page,一个可变的版本保存到DRAM中,叫做Volatile Page,它可能为NULL。另外一个不可变的版本保存NVRAM中,叫做Snapshot Page。另外在FOEDUS中,所有的信息都保存在Page中, ... In all remote-ness settings, FOEDUS performs 2.4x faster than SILO on 240 cores and 2x faster on 60 cores. FOEDUS is less affected by transactional logging, too. Whether FOEDUS writes out logs to... Read more!

  • 05 Jun 2018
    Time Traveling Optimistic Concurrency Control

    TicToc: Time Traveling Optimistic Concurrency Control 0x00 引言 这篇文章是关于内存数据库的Optimistic Concurrency Control优化的一篇paper(对OCC没有了解的可以先看看论文[2])。Timestamp ordering (T/O) concurrency control 是数据库并发控制一种非常重要的方法,一般而言,系统会以事务为粒度分配timestamp,而这种方式存在一个缺点: A common way to implement the allocator is through an atomic add instruction that increments a global counter for each new transaction. This approach, however, is only able to generate less than 5 million... Read more!

  • 01 Jun 2018
    Relaxed Operator Fusion for In-Memory Databases

    Relaxed Operator Fusion for In-Memory Databases: Making Compilation, Vectorization, and Prefetching Work Together At Last 0x00 引言 和前面的一篇[2]一样(而且这篇Paper主要的一个对比对象也是[2]),这篇Paper讲的也是内存数据库的查询处理器框架。是CMU的Peloton的一部分。现在的很多数据库使用将SQL通过JIT编译为机器码执行的方式,包含MemSQL、HyPer等,PostgreSQl也有这样的功能。一些系统实现的时候都会避免将元组物化(Materialization),来减少这个操作带来的开销。但是在这篇Paper中则认为适当的物化操作可以实现更加好的性能。在Peloton中提出的方法就是Relaxed Operator Fusion(ROF),它会在查询计划重引入临时点(staging points),在这里将中间结果临时性地物化,使得系统可以通过缓存预取、SIMD等技术实现更加好的元组间的并行性, ... Our evaluation shows that our approach reduces the execution time of OLAP queries by up to 2.2x and achieves up to 1.8x better performance compared to other in-memory... Read more!

  • 27 May 2018
    Morsel-Driven Parallelism

    Morsel-Driven Parallelism: A NUMA-Aware Query Evaluation Framework for the Many-Core Age 0x00 引言 这篇Paper讲的是Hyper内存数据库的查询框架。它主要就是要解决两个问题,一个是如何利用好现在的多核的架构,另外一个就是实现正确的数据统计以便于平均将将任务分配到各个线程(核心)上面。Morsel的英文意思是少量。Morsel-Driven的执行方式就是将任务的数据拆分为大小合适、可动态调整的段,然后按照流水线的方式执行操作。另外,一个DIspatcher负责根据任务执行的一些状态、硬件NUMA的一些解决来合分发任务。还有就是一些优化的Hash Join、分区和排序等的算法, ... Our evaluation on the TPC-H and SSB benchmarks shows extremely high absolute performance and an average speedup of over 30 with 32 cores. 0x01 Morsel-Driven执行方式 Morsel的执行方式是之前每次处理一条记录(数据)的一种优化,能够更好地利用好现在的硬件,比如多核、SIMD等。HyPer内存数据库会将SQL使用JIT的方式转化为机器码执行的方式。在HyPer使用流水线执行的方式,这个流水线的一段会被编译为一段机器代码。Morsel-Driven中,代数的计划执行被称为QEPobject的对象控制,它会将执行的流水线信息传输给Dispatcher。一个操作(比如3个表的Join)会规划为若干的流水线执行,QEPobject会变为每条流水线开辟一些临时存储区域,用于保存其的结果,这里存储区域的分配会考虑到NUMA。 Paper中举例了一个3个表R、S、T 连接的例子,加上T、S表被优化器选择构建Hash Table,而使用R中符合条件的记录去“试探”这个两个Hash Table。 上面的图中左边是执行计划的示意,右边则是执行流水线的示意。这个执行的时候被分为3条流水线,构建两个Hash Table为两条流水线。使用表R“试探”这两个Hash Table又是一条流实现。QEPobject会探知这些操作的依赖关系,这里明显就是Pipe 3依赖于Pipe... Read more!

  • 19 May 2018
    The Volcano Optimizer Generator -- Extensibility and Efficient Search

    The Volcano Optimizer Generator: Extensibility and Efficient Search 0x00 引言 Volcano风格的优化器以及后面的Cascades是数据库优化器比较有名的设计。现在不少的数据库以及一些相关的框架有使用。Volcano是一种Unified Search的优化器,统一逻辑查询到逻辑查询以及逻辑查询到物理查询的操作。例如IBM的STARBURST优化器的设计是一种Stratified Search的优化器,这类优化器会先有一个查询重写的阶段,将逻辑查询重写之后在将逻辑查询转化为物理查询。Volcano容易添加新的操作和等价规则,使用基于branch-and-bound搜索的Top-down的方法。Volcano遵循下面的一些设计原则, 查询处理都是基于关系代数; 使用规则和模式来处理等价转换; 不使用中间表示状态,直接讲查询转换为计划,没有中间表示状态; 使用编译的方式而不是解释的方式(这里应该指的是优化器,而不是指SQL语句,优化器没有涉及到SQL语句); 使用动态规划的搜索方式; 0x01 基本设计 用户查询在Volcano中的优化从代数表达式(树)开始(优化器的输入),这个代数表达式(树)由用户接口的输入(一般就是SQL语言)被Parser转化而来,Parser和优化器没有什么关系。这个代数表达式(树)有一系列的逻辑操作组成(logical operators )。一个Operator会有0个或者更加多的输入,输入的数量是没有限制的。优化器的输出就是查询计划。另外就是一组的算法,表示了在数据存储上面的一些操作。Volcano的一些设计, 优化操作就是将逻辑的代数表达式转换为优化的等价的物理代数表达式,在优化的过程中,Operator的顺序是可能会被改变的,具体实现的算法会从算法的集合中选取。为了保证转换的等价性,这个使用了转换规则的概念,比如有些操作满足交换律和结合律。这些规矩可能会附加条件(condition code),多个的逻辑Operator可能会被映射到一个物理的Operator。 Logical → Logical: JOIN(A,B) to JOIN(B,A) Logical → Physical: JOIN(A,B) to HASH_JOIN(A,B) 表达式的结果被称为Properties。逻辑的Properties包括了Schema, Expected Size等之类的,物理Properties包含了排序的顺序,分区等的信息,取决于算法, When optimizing a many-sorted algebra, the logical properties also include... Read more!

  • 15 May 2018
    Access Path Selection in a Relational Database Management System

    Access Path Selection in a Relational Database Management System 0x00 引言 这篇Paper是数据库优化器设计中的一篇极为重要的文章,对后面的相关系统的设计产生了很大的影响。这篇Paper要解决的问题就是在用户在不知道数据库具体的实现细节的情况下,数据库的优化器如何讲用户的SQL转化为尽可能高效的具体的查询数据的方式, SQL statements do not require the user to specify anything about the access path to be used for tuple retrieval. Nor does a user specify in what order joins are to be performed. The System R optimizer chooses... Read more!

  • 13 May 2018
    Google Andromeda

    Andromeda: Performance, Isolation, and Velocity at Scale in Cloud Network Virtualization 0x00 引言 Andromeda是Google的云平台的网络虚拟栈,是Google网络技术方面的几个创新之一。这篇Paper发表在NSDI‘18。刚好NSDI’18上面也有微软关于云平台上面网络栈的一篇Paper。这两篇体现出来的是完全不同的思路。前面看过的微软的论文[2]重点是利用一些新型的硬件如FPGA,而Google强调的是基于软件的架构。 ... We describe the design of Andromeda and our experience evolving it over five years. Taken together, we have improved throughput by 19x, CPU efficiency by 16x, latency by 7x, and maximum network size by 50x,... Read more!

  • 09 May 2018
    BzTree -- A High-Performance Latch-free Range Index for Non-Volatile Memory

    BzTree – A High-Performance Latch-free Range Index for Non-Volatile Memory 0x00 引言 Bw-tree是lock-free的B+tree中最著名的一个。为了到达lock free,Bw-tree算法的复杂程度(不是复杂度)也是很可怕,特别是要实现一个Bw-tree,估计代码量是ART的很多倍了。Bw-tree诸多的设计都是为了在只支持单一CAS操作的硬件上实现lock free,而BzTree的设计还是利用CAS实现lock free(数据库中叫做latch free),由于没有硬件支持多个元素的CAS操作,这里BzTree使用是利用软件实现,这里就不具体说明这个是如果实现的了,可以参考[2]。 0x01 基本思路 BzTree的实质就是一棵B+ Tree,解决的问题就是加入有了一个可以支持Multi-CAS操作的库,如何讲B+ Tree变成latch free 的呢?先来看看PMwCAS(Persistent Multi-Word CAS)[2]的API: • AllocateDescriptor(callback = default): Allocate a descriptor that will be used throughout the PMwCAS operation. The user can provide a custom callback function for... Read more!

  • 07 May 2018
    Azure Accelerated Networking

    Azure Accelerated Networking: SmartNICs in the Public Cloud 0x00 引言 Azure Accelerated Networking (AccelNet)是微软的一个基于FPGA的网络栈(host SDN stack)的一个解决方案, The AccelNet service has been available for Azure customers since 2016, providing consistent < 15μs VM-VM TCP latencies and 32Gbps throughput, which we believe represents the fastest network available to customers in the public... Read more!

  • 05 May 2018
    NetCache -- Balancing Key-Value Stores with Fast In-Network Caching

    NetCache: Balancing Key-Value Stores with Fast In-Network Caching 0x00 引言 这篇Paper和之前的NetChain都是类似的工作,这个NetCache发表在SOSP 2017上面。提出了一种新的KVS的架构(a new rack-scale key-value store architecture that leverages in-network caching to provide dynamic load balancing across all storage servers,注意它的范围是在一个rack的范围内),主要的内容就是如何利用可编程的交换机来实现KVS的负载均衡, We implement a NetCache prototype on Barefoot Tofino switches and commodity servers and demonstrate that a single switch can process... Read more!

  • 03 May 2018
    NetChain -- Scale-Free Sub-RTT Coordination

    NetChain: Scale-Free Sub-RTT Coordination 0x00 引言 这篇文章将的是利用可编程交换机做的一个Coordination Service(类似Chubby Zookeeper),是NetPaxos 和NetCache的后续,想法都是将一些东西使用可编程的交换机来实现。 We present NetChain, a new approach that leverages the power and flexibility of new-generation programmable switches to provide scale-free sub-RTT coordination. In contrast to server-based solutions, NetChain is an in-network solution that stores data and processes queries entirely within the... Read more!

  • 30 Apr 2018
    The Design and Implementation of Open vSwitch

    The Design and Implementation of Open vSwitch 0x00 引言 虚拟化对数据中心网络的产生了很大的影响。现在的很多的网络接入层的端口都是虚拟化的而不是物理的。现在的网络的第一条的交换机越来越是hypervisor,而不是用来的数据中心网络中的ToR交换机。已有解决方案的不足导致了网络虚拟化的出现,在这样的网络中,虚拟交换机变成了一个重要的组成部分,虚拟的交换机在数据中心网络和hypervisor之间传输IP隧道数据包,它可以使得虚拟网络和和物理网络分离。Open vSwitch为解决这些问题和客服现有一些解决方案的局限性而出现, Today, on Linux, its original platform, Open vSwitch works with most hypervisors and container systems, including Xen, KVM, and Docker. Open vSwitch also works “out of the box” on the FreeBSD and NetBSD operating systems and ports to the... Read more!

  • 27 Apr 2018
    OpenFlow -- Enabling Innovation in Campus Networks

    OpenFlow: Enabling Innovation in Campus Networks 0x00 引言 这篇的论文的题目中透露出OpenFlow是为了实验新的网络协议,面向校园网络设计的。现在的应用当然更加广泛。OpenFlow基于以太网交换机,通过一个内部的flow-table,和一个标准的接口用来添加移除表里面的一项flow。OpenFlow是一个实用的折中办法,一方面它可以是的研究者可以实现不同的交换机的实验环境,另外一方面它不要求交换机暴露内部的细节。 0x01 为什么需要一个可编程的网络 现在使用的网络技术和相关的基础设施是如此地成功,以至于给现在的有关网络的研究要应用到现实中带来了巨大的阻碍。这里感觉IPv6就是一个例子(虽然和OpenFlow没啥关系),IPv4非常成功,替换IPv4的成本造成了现在的IPv6的使用比例依旧很低。原来存在的基础设施带动了网络的发展,但是有些时候它也阻碍了网络的继续创新。对于新的网络技术,很难在实际的环境中去验证,更别提是使用了。为了处理这些问题,现在的一些相关的社区已经提出了一些想法,比如GENI,倡导使用一些可编程的网络硬件,比如交换机, For example, in GENI it is envisaged that a researcher will be allocated a slice of resources across the whole network, consisting of a portion of network links, packet processing elements (e.g. routers) and end-hosts; researchers program their... Read more!

  • 25 Apr 2018
    NetVM and OpenNetVM

    NetVM: High Performance and Flexible Networking using Virtualization on Commodity Platforms 0x00 引言 NetVM是一种网络虚拟化的解决方案,它建立在KVM的虚拟化平台和Intel的DPDK。在NetVM之前,网络虚拟化的解决方案有这样的一些,1. 完全虚拟化的方案,使用软件来模拟网卡的行为,这样缺点很明显,就是性能相对来说很低,2. 直接访问的方案,这个的缺点就是同一时间只能被一个VM使用,3. 另外一个就是intel提出的SR-IOV的方法,通过虚拟多个VF的方法来满足被多个VMs使用,但是NetVM认为它的缺点是灵活性不足,比如无法实时迁移,支持的VF的数量也是有限的。针对之前的系统存在的这些问题,这里NetVM就提出了它的解决方案, ... Our evaluation shows how NetVM can compose complex network functionality from multiple pipelined VMs and still obtain throughputs up to 10 Gbps, an improvement of more than 250% compared to existing techniques... Read more!

  • 23 Apr 2018
    Reducing the Storage Overhead of Main-Memory OLTP Databases

    Reducing the Storage Overhead of Main-Memory OLTP Databases with Hybrid Indexes 0x00 引言 ​ 这篇文章的idea也是very excellent,paper的主要目的是减少内存数据库中内存的使用。通过讲结构分为两个部分,一个部分负责读取写入,另外一个只负责读取,通过对后一个的优化减少了大量的内存使用: The dual-stage architecture maintains a small dynamic “hot” store to absorb writes and a more compact, but read-only store to hold the bulk of index entries. Merge between the stages is triggered peri- odically... Read more!

  • 22 Apr 2018
    The ART of Practical Synchronization

    The ART of Practical Synchronization 0x00 引言 这篇文章是关于Adaptive Radix Tree上同步机制的一篇文章,ART是Hyper数据库中主要的索引数据结构。这里介绍了两个同步机制:Optimistic Lock Coupling , andRead-Optimized Write EXclusion (ROWEX) We synchronize the Adaptive Radix Tree (ART) using two such protocols, Optimistic Lock Coupling and Read-Optimized Write EXclusion (ROWEX). Both perform and scale very well while being much easier to implement than lock-free... Read more!

  • 17 Apr 2018
    GPU Key-Value

    Mega-KV: A Case for GPUs to Maximize the Throughput of In-Memory Key-Value Stores Mega-Key的基本思路就是使用GPU来做Key-Value的索引,GPU上面的显存有限,数据不保存在GPU上面。它号称可以, Running on a commodity PC installed with two CPUs and two GPUs, Mega-KV can process up to 160+ million key-value operations per second, which is 1.4-2.8 times as fast as the state-of-the-art key-value store system on... Read more!

  • 12 Apr 2018
    TinyLFU -- A Highly Efficient Cache Admission Policy

    TinyLFU: A Highly Efficient Cache Admission Policy 0x00 引言 在工作的时候使用了caffeine这个java 本地缓存库,这个库的设计非常赞,代码也非常棒(虽然目前为止只是粗略的看了一下,如果要推荐java的开源项目看看代码,这个绝对值得推荐)。这里只关注它里面的Cache Admission Policy – TinyLFU。 0x01 基本思路 先来一张图: ​ 虽然论文长达31页,但是我们这里只关注其中的两个部分: Let us emphasize that we face two main challenges. The first is to maintain a freshness mechanism in order to keep the history recent and remove old events. The second... Read more!

  • 06 Apr 2018
    SILT -- A Memory-Efficient, High-Performance Key-Value Store

    SILT: A Memory-Efficient, High-Performance Key-Value Store 0x00 引言 这一篇讲的是为flash storage设计key-value的问题,SILT,即Small Index Lager Table。SILT最的特点就是每一个key-value只占用0.7bytes的DRAM和平均1.01次的flash读取, SILT requires approximately 0.7 bytes of DRAM per key-value entry and uses on average only 1.01 flash reads to handle lookups. Consequently, SILT can saturate the random read I/O on our experimental system, performing 46,000 lookups per... Read more!

  • 02 Apr 2018
    Anna -- A KVS for any scale

    Anna: A KVS for any scale 0x00 引言 Anna是发表在ICDE 2018上的一篇关于KVS的文章。不同于前面的一些KVS,Anna的两个最主要的特点一个就是就是它的分区的方式,使用了Coordination-free Actors的模型,另外一个就是Lattice-Powered, Coordination-Free Consistency的一致性模型。Anna的标题就”非常厉害“的样子,for any scale!怎么实现?Paper里面列举的Anna要实现的目标: ... providing excellent performance on a single multi-core machine, while scaling up elastically to geo-distributed cloud deployment. In addition to wide-ranging architectural flexibility, we wanted to provide a wide range of consistency semantics as well,... Read more!

  • 28 Mar 2018
    Full-Stack Architecting to Achieve a Billion

    Full-Stack Architecting to Achieve a Billion-Requests-Per-Second Throughput on a Single Key-Value Store Server Platform 0x00 引言 这篇文章时对如何实现一个超高性能的单机key-value的一个总结,很值得一看。文章对比现在的对个KVS系统,并对它们的具体技术做了分析。结合这个团队之前发的KVS相关的几篇论文,总结出对于一个KVS来说,最重要的几个方面就是: The networking stack,由于这里讨论的是单机的KVS,所以这里网络这里主要是server和client之间的通信,client发送请求,然后server回复response。一些追求高性能的系统一般都不直接使用OS提供的网络栈,而是使用DPDK or RDMA之类的技术; Concurrency control,这里值得就是如何解决多线程访问的问题,支持并行访问的同时保持一致性,这里存在诸多的方式,比如传统的mutex,或者其它种类CC的技术。另外一个在这里,分区也是减少并发控制操作的重要方式,一般高性能的KVS系统都会采用分区的方式; Key-value processing,这里将的就是如何实现put,get的功能,还有就是如何优化这些操作,以及缓存替代策略等; Memory management,这里将的就如如何管理内存了,常见的有直接使用malloc的,还有就是使用slab之类技术的,另外一种方式就是 log-structured方式的。 下面的表是一些KVS的例子,这些在论文中是测试的对象: 网站很多事从MICA这个系统出发讨论的,使用最好先阅读一下[2]。 0x01 The Road To 120 Million RPS Per KVS Server 这里讨论的事如何使得MICA得到120M的RPS的,这里使用客户端批量执行的话可以达到160M PRS。 系统平衡优化 这里主要讨论的是计算、内存和网络等资源的配比,在Paper中使用的网络硬件中,NIC的速度为10GbE,使用的CPU为Intel Xeon E5-2697v2 (12 core, 30MB... Read more!

  • 25 Mar 2018
    Scaling a file system to many cores using an operation log

    Scaling a file system to many cores using an operation log 0x00 引言 ScaleFS是前几天看过的OpLog的一个应用。ScaleFS一个创新的地方就是将文件系统分为in-memory的部分核on-disk的部分。ScaleFS使用pre-core的operation logs,可以将一些操作实际完成的时间推迟[2]。通过诸多的优化措施,ScaleFS消除了文件系统中在并行情况下大部分的冲突, ... ScaleFS show that its implementation has no cache conflicts for 99% of test cases of commutative operations generated by Commuter, scales well on an 80-core machine, and provides on-disk performance that is comparable to... Read more!

  • 22 Mar 2018
    Rethink the Sync

    Rethink the Sync 0x00 引言 这篇Paper讲的是同步IO与异步IO的一些问题,Paper中提出了一种external synchrony的模型,可以帮助文件IO在保持同步IO的可靠性和简便性的同时实现异步IO般的性能。 For I/O-intensive benchmarks such as Postmark and an Andrew-style build, the performance of xsyncfs is within 7% of the default asynchronous implementation of ext3. ... Xsyncfs is as much as an order of magnitude faster than the default version of ext3 mounted synchronously,... Read more!

  • 20 Mar 2018
    OpLog -- a library for scaling update-heavy data structures

    OpLog: a library for scaling update-heavy data structures 0x00 引言 OpLog是为频繁更新的数据结构设计的一个库。基本思想就是推迟真正的更新操作,直到下一次读取操作(or达到其它的一些条件)得时候,一次性应用这些更新操作,使用批量的方式来降低成本,这样还大大地减少在多核情况下的数据竞争。 ... OpLog achieves generality by logging operations without having to understand them, to ease application to existing data structures. OpLog can further increase performance if the programmer indicates which operations can be combined in the logs. An evaluation shows... Read more!

  • 10 Mar 2018
    The Scalable Commutativity Rule

    The Scalable Commutativity Rule: Designing Scalable Software for Multicore Processors 0x00 引言 CPU的单核性能增长现在已经慢到不行,核心数量的增长还是很快的。如何改变软件让其适应越来越多的核心的CPU,这是个问题,233。API的设计(the design of the software interface )对系统可可拓展性有着很大的影响,一个例子就是open这个系统调用。POSIX标准规定返回的文件描述符必须是空闲的里面最小的,实际上对于这个API来说,文件描述符只要能保证是唯一的就行了,完全没必要有这样的要求。就是当初这样一个设定,导致了可拓展性的问题。在MegaPipe等之类的设计中都抛弃了这一个设定。 This forces the kernel to coordinate file descriptor allocation across all threads, even when many threads are opening files in parallel. This choice simplified the kernel interface during the early days... Read more!

  • 07 Mar 2018
    Eris -- Coordination-Free Consistent Transactions

    Eris: Coordination-Free Consistent Transactions Using In-Network Concurrency Control 0x00 引言 如果一个网络不会丢包也不会乱序,那么在这个网络上面的分布式共识问题,分布式并发控制等都是很容易实现的问题,然鹅这两点现在的网络都不能满足。Eris就尝试在对网络本身进行一些改造,来达到这样的效果,这篇Paper和OSDI‘16 上面的NOPaxos出自同一个实验室,它们使用的基本思路也是一致的,特别是OUM模型, ... it can process a large class of distributed transactions in a single round-trip from the client to the storage system without any explicit coordination between shards or replicas in the normal case. It provides atomicity, consistency, and... Read more!

  • 04 Mar 2018
    Just say NO to Paxos Overhead

    Just say NO to Paxos Overhead: Replacing Consensus with Network Ordering 0x00 引言 Paxos是分布式共识里面重要的算法了。Paxos算法的变体也非常多。而NoPaxos的把一些算法的逻辑放到了网络上面,这里核心的概念的Ordered Unreliable Multicast(OUM),即在数据中心网络实现有序但是不可靠的消息传输,并在此的基础之上实现NOPaxos(Network-Ordered Paxos),是SOSP‘17 Eris论文的后续,其作者基本相同, ... NOPaxos on a testbed using our OpenFlow/Cavium prototype and demonstrate that it outperforms classic leader-based Paxos by 54% in latency and 4.7× in throughput. It simultaneously provides 42% better latency and... Read more!

  • 01 Mar 2018
    KV-Direct

    KV-Direct: High-Performance In-Memory Key-Value Store with Programmable NIC 引言 KV-Direct[1]是SOSP 2017上的一篇关于利用可编程网卡和FPGA实现Key-Value Store的Paper。号称可在单机上实现1.22 billion的 KV操作。 A single NIC KV-Direct is able to achieve up to 180 M KV operations per second (Ops), equivalent to the throughput of 36 CPU cores. Compared with state-of-art CPU KVS implementations, KV-Direct reduces tail latency to... Read more!

  • 25 Feb 2018
    ZygOS -- Achieving Low Tail Latency for Microsecond-scale Networked Tasks

    ZygOS: Achieving Low Tail Latency for Microsecond-scale Networked Tasks 0x00 引言 这篇Paper时前面的Dune Framework和IX的后续,主要是为了解决在多核系统下面的非常细粒度的网络任务的调度问题, We evaluate ZYGOS with a networked version of Silo, a state-of-the-art in-memory transactional database, running TPC-C. For a service-level objective of 1000μs latency at the 99th percentile, ZYGOS can deliver a 1.63× speedup over Linux (because of... Read more!

  • 20 Feb 2018
    The IX Operating System

    The IX Operating System: Combining Low Latency, High Throughput, and Efficiency in a Protected Dataplane 引言 IX和Arrakis都是OSDI 2014上关于利用硬件虚拟化来提供系统IO性能的论文。IX和Arrakis在很多地方是相似的,比如Data Plane和Control Plane分离,比如使用虚拟化和硬件交互,比如都是用用户空间的网络栈等等。此外,IX实现基于之前的Dune Framework,一个利用虚拟化安全保留硬件功能的框架。IX的设计基于以下几个原则: Separation and protection of control and data plane, Run to completion with adaptive batching, Native, zero-copy API with explicit flow control, Flow-consistent, synchronization-free processing, TCP-friendly flow group migration, Dynamic... Read more!

  • 16 Feb 2018
    Arrakis -- The Operating System Is the Control Plane

    Arrakis: The Operating System Is the Control Plane 买不到票的人回不了家。 引言 这篇文章是OSDI 2014上面关于利用虚拟化优化网络和存储IO的文章,主要现在的新硬件上的系统优化。很值得一看。 We demonstrate that operating system protection is not contradictory with high performance. For our prototype implementation, a client request to the Redis persistent NoSQL store has 2× better read latency, 5× better write la- tency, and 9× better... Read more!

  • 11 Feb 2018
    The RAMCloud Storage System

    The RAMCloud Storage System 引言 RAMCloud是一个基于内存的分布式存储系统,所有的数据任何时候都保存在内存之中,RAMCloud达到了3个总体目标: low latency, large scale, 和 durability。RAMCloud各方面技术的应用都是很激进的。RAMCloud的实现的多个方面都已经发了Paper,而且之前也已经看过了3篇Paper,主要设计到RAMCloud的内存分配方式,RAMCloud的Kye/Value索引的实现以及RAMCloud的快速的恢复机制。这篇文章是RAMCloud的一篇综述性的Paper。另外RAMCloud的一篇主要的Paper就是关于其一致性实现的[2]。 架构 & 日志结构式存储 & 容错以及恢复 这几点的内容在前面的Paper中以及基本看过了[3,4,5]. RAMCloud是一种更加复杂一点的Key/Value的架构,支持索引(不够[4]发表的时间在这篇Paper之后,这里还没有设计到[4]的内容)。数据分区,分布式的内存存储,带副本。 内存分配的方式不是传统的malloc或者是类似一些类型的方式,而是一种类似在文件系统中常用的日志结构式存储。 RAMCloud会将数据持久化到磁盘上,为了支持系统在Crash之后在短时间内恢复,RAMCloud基本的思路就是使用非常大数据的磁盘来提供足够快的恢复时间。RAMCloud好像也不保证完全不丢数据。 RAMCloud恢复的方式基本还是基于副本和将数据持久化到磁盘上面的方式。 低延时 RAMCloud的一个设计的目标就是将端到端的延迟控制在5us以下,这个在当时的常见的RPC的实现上是非常难以做到的。RAMCloud在实现这么低延迟的RPC实现的时候要处理不少的问题:1. 网络带宽和延迟的问题,RAMCloud设计的时候一台交换机带来的延迟就是10到30 μs,而且一般会经过5台这样的交换机;2. Kernel call,数据包经过内核处理、上下文切换带来的开销;3. 锁等同步操作带来的开销;4. 在追求超低延迟的时候一个CPU Cache确实都要考虑到;5. 批量处理带来的问题,批量处理系统设计中常用的一个提高吞吐量的方法,但是会增加延迟。在网络基础设施本身带来的延迟上面,RAMCloud任务网络技术的发展会解决这些问题,特别是更高速以太网和RDMA之类的技术的使用。另外RAMCloud采用的解决方案, Kernel Bypass和轮询。Kernel Bypass是现在很多的优化网络栈使用的方法。Kerbel Bypass的方式绕开了内核,来消除or降低了内核网络栈冗长的处理路径、内核空间和用户空间频繁切换带来的overhead、内核空间和用户空间之间的内存拷贝。RAMCloud让NIC设备使用的内存被之间映射到应用的内存控制之重,使得应用可以直接处理来自NIC的数据。在RAMCloud设计的时候,具有这类功能的NIC还不是很常见,但是RAMCloud认为这个在以后会变的很常见。而且RAMCloud中使用的Infiniband NIC也支持这样的方式。另外,为了避免网络栈在等待事件导致增加延迟,RAMCloud直接使用轮询的方式,优化了使用中断和睡眠唤醒线程上消耗的时间; RAMCloud支持传输的方式是多样的,在RAMCloud 1.0中,支持Infiniband、Kernel Bypass方式实现的定制的协议(使用UDP数据包的格式)、TCP。TCP的延迟要比Infiniband方式长50到100 μs。很显然这里直接使用TCP是无法满足RAMCloud设计的要求的; 为了降低延迟,RAMCloud在开始设计的时候考虑了单线程的设计,单个现场轮询请求然后处理请求马上恢复。不养方法在处理一个耗时的请求的时候存在严重的缺陷(也是redis的缺陷)。最终RAMCloud还是使用了多线程的设计。RAMCloud的RPCs有一个单独的分发线程(dispatch thread)和一组工作线程(worker threads )合作处理。前者处理网络通信,后者处理实际的请求。为了降低延迟,两类线程之间的交互也是使用轮询的方式。分发线程选择一个空闲的工作线程,将请求相关结构的指针保存到这个工作线程轮询的一个地方即可。 从上面可以看出,为了降低延迟,RAMCloud采用的都是很激进的方法。 时间消耗分析 在Paper中,RAMCloud详细分析了时间消耗的地方。花费在网络上面的时间还是最多的,除此之外,内存确实和线程工作交接上面的时间先后占了主要的部分, Where Does... Read more!

  • 08 Feb 2018
    MICA -- A Holistic Approach to Fast In-Memory Key-Value Storage

    MICA: A Holistic Approach to Fast In-Memory Key-Value Storage 0x00 引言 这篇paper是关于KVS里面一篇非常好的文章。个人觉得里面很多东西都设计的很赞。此外,作者还有一篇指导如何设计一个QPS 为Billion基本的论文[2],也很值得一看(不过好像里面做的并没有实际到达1billion,倒是SOSP 2017 上的一篇文章到达了[3],之后加上这篇论文的blog)。MICA一个目的就是旨在解决之前类似系统只为read-mostly场景设计,希望能适应各种各样的场景,并提供很好的性能: Under write-intensive workloads with a skewed key popularity, a single MICA node serves 70.4 million small key-value items per second (Mops), which is 10.8x faster than the next fastest system. For skewed, read-intensive workloads, MICA’s... Read more!

  • 02 Feb 2018
    MemC3 and libcuckoo

    MemC3: Compact and Concurrent MemCache with Dumber Caching and Smarter Hashing 0x00 引言 这篇paper是关于优化memcached内部实现的。主要包含了几个方面,这里只关注optimistic cuckoo hashing 。 As a case study, we focus on Memcached [19], a popular in-memory caching layer, and show how our toolbox of techniques can improve Memcached’s performance by 3× and reduce its memory use by... Read more!

  • 30 Jan 2018
    netmap -- a novel framework for fast packet I/O

    netmap: a novel framework for fast packet I/O 引言 netmap是一个非常优秀的使用内核旁路的包处理的框架,可以在900MHz的一个CPU Core上面实现14.88 Mpps的处理速度。在这篇Paper中的数据指出可以在平摊地70cyles左右就处理一个数据包。 netmap has been implemented in FreeBSD and Linux for several 1 and 10 Gbit/s network adapters. In our prototype, a single core running at 900 MHz can send or receive 14.88 Mpps (the peak packet rate on 10... Read more!

  • 28 Jan 2018
    PacketShader -- a GPU-Accelerated Software Router

    PacketShader: a GPU-Accelerated Software Router 引言 之前在大学的时候问过系里的一位老师有没有使用GPU处理网络数据包和加密处理的研究。但是那位老师说2010年韩国的一个大学做过相关的研究。我想他说的就是这一个了。 Optimizing Packet I/O Engine 文章的主要内容中,先谈的是Packet IO Engine的优化。这里的原来的Linux的网络协议栈存在下面的两个问题: 频繁的buffer分配和回收造成不小得overhead; 相关的元数据如skb占用了大量的内存,它保存了各类协议需要的信息,而时间里面很多是很少被用到的。 Huge Packet Buffer 这里先优化的就是buffer的问题。这里不在使用动态分配skb的方式,而一次性分配两个大的buffer。一个用来保存元数据,一个用来保存数据packet。一个buffer由固定大小的cell组成,一个cell就对应了一个RX队列中的数据packet。用于保存NIC数据packet的cell的尺寸是2048bytes,可以很好的处理以太网1518bytes的最大的包的尺寸,同时保存1024bytes对齐。这里的cell会被重复利用,而不是allacate和deallcate的方式。这样避免很多的开销, The cells are reused whenever the circular RX queues wrap up. This scheme effectively eliminates the cost of per-packet buffer allocation. Huge packet buffers also reduce per-packet DMA mapping cost... Read more!

  • 26 Jan 2018
    mTCP -- A Highly Scalable User-level TCP Stack

    mTCP: A Highly Scalable User-level TCP Stack for Multicore Systems 引言 mTCP是在用户态实现的TCP网络协议栈,目的是解决目前的内核网络栈存在的可拓展性的问题。具体的一些问题在前面的几篇文章中已经提到了。 Lack of connection locality,Affinity-Accept[3]和MegaPipe[2]也尝试解决这个问题; Shared file descriptor space,VFS带来的overhead; Inefficient per-packet processing,低效的包处理; System call overhead,系统调用的开销。 mTCP通过综合多中技术:1. 将昂贵的syscall转化为为一个简单的引用操作,2. 高效的流事件聚合,3. IO操作批量化处理等最终实现了性能的大幅提升: Our evaluations on an 8-core machine showed that mTCP improves the performance of small message transactions by a factor of... Read more!

  • 24 Jan 2018
    Scalable Kernel TCP Design and Implementation for Short-Lived Connections

    Improving Network Connection Locality on Multicore Systems 引言 这个是最近三篇关于Linux 内核网络栈优化文章中的第1篇,后面的两篇会之后加上[2,3]。这篇文章解决Linux中Connection Locality的问题的。提出了一个叫做MegaPipe办法。 问题: 这以幅图就基本说明了目前存在的问题。多个核心共享一些结构导致了冲突的问题。 基本思路 基本思路就是将这些共享的结构弄成非共享的。Affinity-Accept 将这些结构变成了每一个核心一份。 第一个要解决的问题就是包路由的问题,这里需要将来自一个连接的包有交给同一个核心。这里通过网卡的功能解决。 The NIC hardware typically hashes each packet’s flow identifier five-tuple (the protocol number, source and destination IP addresses, and source and destination port numbers) and uses the resulting hash value to look up... Read more!

  • 21 Jan 2018
    MegaPipe -- A New Programming Interface for Scalable Network IO

    MegaPipe: A New Programming Interface for Scalable Network I/O 引言 网卡性能的提高,自然对kernel的网络栈的性能也提出了更加高的要求。网络栈的一些缺点在这些高性能的网卡中也会体现地更加明显。目前系统存在的一些问题: Contention on Accept Queue(accept队列上的竞争): accept queue只有一个,操作加锁,这样就导致了CPU核心之间的竞争。影响了kernel添加连接和application接受一个新的连接。此外,这样的设计也是缓存不友好的; Lack of Connection Affinity(缺乏连接亲和性): 在Linux中,已经存在了RSS、RPS等机制将接受的数据包分发到每个CPU核心上。一个CPU核心上接受的新连接的数据包可能是另外一个CPU核心接受的。 File Descriptors :POSIX中一个很差劲的设计,但是可能没想到对以后的系统会有这么大影响。每次分配的fd必须是最小的,这个在实际中是没有这个需要的,标准中确加了进去。(the cost of allocating a single FD is roughly 16% greater when there are 1,000 existing sockets as compared to when there are no existing sockets.... Read more!

  • 12 Jan 2018
    LITE Kernel RDMA Support for Datacenter Applications

    LITE Kernel RDMA Support for Datacenter Applications 引言 这篇Paper是SOSP‘17中关于利用RDMA构建数据中心应用的一篇文章,也是非常赞的一篇文章。在RDMA应用到数据中时,RDMA不够灵活、缺乏高层次的抽象的缺点不利于它的应用。为了解决这个问题,LITE提出了在Linux内核中构建一个RDMA的灵活的、高度的和易用的一个抽象, ... our implementation of graph engine has only 20 lines of LITE code, which encapsulate all the network communication functionalities. While using the same design as PowerGraph, this LITE-based graph engine outperforms PowerGraph by 3.5× to 5.6×. Our LITE-based MapReduce is... Read more!

  • 07 Jan 2018
    Dune Framework

    Dune: Safe User-level Access to Privileged CPU Features 引言 做为一个计算机系统的常识,为了保护系统,我们知道,用户进程的权限是很有限的。这样的设计带来一些好处的同时,也屏蔽了一些好处。如java虚拟机,有时候需要控制线程,要经常性地进行GC,这个时候如果能让JVM访问一些kernel feature,就能得到很多好处。Dune的一个基本思想是利用虚拟化,将一些之前只能是kernel feautre的功能暴露给应用,同时保证系统的安全性。一个Dune进程做为一个普通的Linux进程,不够使用VMCALL来进行系统调用。之前有个的一个类似的系统是Exokernel,不过那个更像是一种类型的kernel,而这个是一个内核上的功能。 基本架构 Dune可以看作是一个虚拟化的一个模块,有内核部分和应用库组成: Dune的基本架构如上图所示,在内核中,添加了一个Dune Module,一个Dune Process,运行在VMX non-root的ring0权限下,再在此之上运行平常的代码。应用不必要一开始在Dune中运行,可以在运行。通过对 /dev/dune/ 进行操作进入Dune状态。不过一旦进入,就不能退出。Dune不同于VMM的一些地方: Dune不支持运行一个完整的OS; 与一般的VMMs不同,Dune使用hypercall调用的是一般的linux syscall; 一般的VMM是虚拟完整的硬件,而Dune之暴露硬件的一部分features; Dune不需要save和restore所有的state; Dune中的内存布局可以是稀疏的,不必想VMMs一样每一个VM都有一个分隔的地址空间。 Memory Management & Exposing Access to Hardware & Preserving OS Interfaces 内存管理Dune的最大的要处理的一个问题,由于Dune想要暴露出来page table,于此同时又要保存一般的内存空间的功能。在上面的图中有一定的体现。 For processes using Dune, a user controlled page table maps guest-virtual... Read more!

  • 29 Dec 2017
    PowerLyra -- Differentiated Graph Computation and Partitioning on Skewed Graphs

    PowerLyra: Differentiated Graph Computation and Partitioning on Skewed Graphs 引言 来看一篇关于图计算的Paper,这篇Paper来自上海交通大学。PowerLyra要解决的问题主要就是现在的一些图分区的方式不能很好地处理现实中的数据发布不均匀的问题。现在使用edge-cuts或者是vertex-cuts的方法均存在不足,PowerLyra提出了一种混合的分区的方式,利用好两种分区方式适应不同情况的优点。 背景 现在的图计算为了处理大规模的图,往往不可避免地要对图进行分区。分区的一个最直观的思路就是类型Pregel的方式,将顶点根据一定的规则划分到不同的分区,这样的一个效果就是有些边是跨越了分区。另外一种就是类似在GraphLab中采用的方法,分区的时候对于跨越了分区(机器)的边的顶点,就复制顶点一份,而且边也复制一份。PowerGraph的思路与前的两种存在又存在一些区别,它也存在顶点的副本,但是边没有。 存在的问题 Pregel中和GraphLab中采用的方法被称为edge-cut的方法,它的优点就是有更加好的局部性。可以试图将可能地降低跨越了分区的边的数量,缺点就是由于顶点的度数在很多自然的数据中是发布不平衡的,少数的顶点拥有大量的边,而其它的部分的顶点的边的数量比较少,这种情况下就会导致负载不均衡的现象。而PowerGraph、GrpahX之类的系统采用的vertex-cut的方法好处就是解决了一些数据分布不均衡的问题,能获得更高的并行性。缺点就是会造成比较大的复制因子(the average number of replicas for a vertex),另外就是增加通信量,对于一些低度数的点这样的分区更多是无用的。所以,既然不同的分区方式有不同的优缺点,PowerLyra就应用一种混合的方法。 PowerLyra PowerLyra是基于PowerGraph改进而来的。在图划分的时候,和PowerGraph一样,PowerLyra将一个顶点的副本中使用一种hash算法随机选择一个作为Master,其余的作为Mirrors,也同样适用GAS的编程模型。对于顶点计算的处理,PowerLyra采用了Hybrid的方法,处理high-degree的顶点时,为了获取更高的并行性,PowerLyra基本上采用的就是PowerGraph的方法,做了一些的修改。 * Gather, two messages are sent by the master vertex (hereinafter master for short) to activate all mirrors to run the gather function locally and accumulate... Read more!

  • 22 Dec 2017
    Multiprogramming a 64 kB Computer Safely and Efficiently

    Multiprogramming a 64 kB Computer Safely and Efficiently 引言 这篇Paper是SOSP‘17上面关于利用Rust编程语言来实现一个嵌入式操作系统的Paper。TockOS面向的是资源非常有限的环境,与现在的一般的系统使用数GBor数十GB的内存不同,TockOS的环境一般只会有几十KB的内存。不仅仅是内存,其它的资源也十分有限。TockOS水用Rust语言实现,利用了Rust带来的一些安全的功能。 基本架构 与一般的通用的操作系统类型,早TockOS也主要就是Kernel和Processes组成。在TockOS中,Kernel中的组件被抽象为Capsule。下图中的一个个蓝色长椭圆就是代表了一个个的Capsules。Capsule的实现中利用了Rust语言的特性,它们实现在一个编译时处理的语言沙箱里面。Process即进程,和一般OS中进程的概率类似。TockOS中的进程支持抢占式调度,使用syscall与Kernel交换,利用硬件的一些功能进程被在内存上隔离。TockOS将使用者的角色分为4中,提供建立一个安全系统的一个机制,而不提供具体的 threat model的解决方案, Board integrators。这个与硬件直接相关,能够直接控制微控制器中的固件。 Kernel component developers,这个角色实现Kernel中的大部分功能。他们编写的代码的主要抽象形式就是Capsule。一般情况下,一个Kernel中的Capsule组件不能认为Kernel中其它的组件都是可信or可靠的。TocOS可以可以限制错误行为的组件造成的影响在一个范围内。一个Capsule可以占据CPU或者是强制重启系统,但是不能违反一些资源共享的限制,比如未授权访问外设。 Application developers,一个开始者的角色,编写应用程序。和一般的系统一样,TockOS认为这些代码都是不可信任的; End-users,一个终端用户的角色。 Capsules Capsule是Kernel中组件的一个抽象。根据不同的功能有着不同的类型。Capsule是使用Rust语言编些的,所以Capsule的对其它的Capsules的隔离性也利用了Rust语言类型安全和模块系统等的一些特性。Capsules之间彼此的隔离可以在一些Capsules的Bug或者是一些错误行为的时候保护其它的Capsules。一个Capsules只能访问其明确被授权使用的资源。另外,Capsule会暴露出结构供其它的部分使用。在并发性方面,TockOS的调度是一个事件驱动,这些事件有硬件产生or进程通过syscall产生。Capsules本身不会去产生新的事件,这样可以降低系统的负载和内存使用。 Processes TockOS中进程概念和其它的系统中进程的概率很类似。在自己一个逻辑上独立的区域上有栈、堆和静态变量等的内容。TockOS中每个进程的栈是独立的,而内核的栈只有一个共享的。另外,编写应用的语言不一定就是Rust。在TockOS中,进程与Kenrel交换的方式也是syscall。 Grants Grant的抽象主要是TockOS为了解决资源有限情况下的内存分配的问题。Kernel对于一些组件的内存的分配是静态分配还是动态分配都不能很好地适应TockOS面临的资源受限的环境和TockOS对系统灵活性的要求。Grant是位于每个进程内存空间中的内核堆的一个单独部分,TockOS提高用于访问它们的API,如下图所示。与一般的内核堆分配不同, Grant的分配不会影响分配内存给其他进程。当一个进程消耗完其Grant内存时, 可以保障系统的其余部分继续正常运行。此外, 一个进程死亡或被更换的情况下, 一个进程的所有资源都可以立即和安全地回收。这个Grant的作用可以看作是带有限制性的动态分配。 实现的一些信息 和 评估 这里的具体的信息可以参看[1]. 参考 Multiprogramming a 64 kB Computer Safely and Efficiently. SOSP ’17. Read more!

  • 18 Dec 2017
    The Multikernel -- A new OS architecture for scalable multicore systems

    The Multikernel: A new OS architecture for scalable multicore systems 引言 这篇Paper针对的是现在的系统越来越多样,CPU的核心数量越来越多。一种内核为多样的环境和多样的任务都优化得很好是不可能的。为了适应未来的挑战,Paper提出了一种叫做multikernel的新的OS架构,这种内核架构最大的一个特点就是将机器看着是一个由cores组成的一个网络,core之间没有底层的共享结构,将传统的OS的功能转移到通过消息通信的分布式系统之中。促使设计multikernel这样一种kernel 架构的动机: 系统变得越来越多样化; core也在变的多样化; 现在系统的内部连接存在很多问题; 消息通信的代价要小于共享内存; 缓存一执行不能解决所有的问题(不是万能药); 消息通信在变得更加简单; 文中认为现在系统中存在的问题与现在的内核存在很多由共享锁保护的数据结构有很大的关系,这里multikernel则引入分布式系统中的概念,将操作系统的功能分解为分布式的功能单元来重新思考。这里的设计遵循了以下的原则: 显式的core间通信;相比于传统的隐式的core间通信,这种方式使得OS可以保持良好的隔离性,以及有利于管理各种各样的核心。此外,这使得在任意的核的拓扑关系间调度任务变得更加有效(虽然我也不知道为什么,反正他就是这么说的),没有缓存一致性,没有共享内存。 保持硬件中立性;multikernel的一个设计思想就是尽可能的将OS架构和硬件分离开,这主要来消息传递的原理和硬件接口两个方面,这有利于适应新的研究而不用做出很多的修改,也有利于将方法和具体的实现分离开来。 复制状态而不是共享状态;系统中总是存在许多的状态,常见的使用共享数据结构,然后使用锁保护的方式使得系统变得更加复杂而去难以拓展。复制状态也是现在的系统提高性能常用的一种办法,常见的就是per-core的结构。复制也对在运行时改变cores很有用,比如CPU的热拔插。 The contributions of this work are as follows: • Weintroducethemultikernelmodelandthedesignprinciples of explicit communication, hardware-neutral structure, and state replication. • We present a multikernel, Barrelfish, which explores the... Read more!

  • 15 Dec 2017
    Exokernel -- An Operating System Architecture Application-Level Resource Management

    Exokernel: An Operating System Architecture for Application-Level Resource Management 引言 Exokernel是一种Kernel的架构,Exokernel的Paper发表在SOSP‘95上面。它最大的特点就是将一些资源的管理可以交给应用程序完成, Measurements show that application-level virtual memory and interprocess communication primitives are five to 40 times faster than Ultrix’s kernel primitives. Compared to state-of-the-art implementations from the literature, the prototype exokernel system is at least five times faster on operations... Read more!

  • 11 Dec 2017
    QEMU, a Fast and Portable Dynamic Translator

    QEMU, a Fast and Portable Dynamic Translator 引言 Qemu是以前做实验用过的一个虚拟化的工具。Qemu最大的一个特点就是它的动态翻译的机制,处理这些之外,还要负责模拟一些其它的设备,比如网络设备、块设备等。 ... It emulates several CPUs (x86, PowerPC, ARM and Sparc) on several hosts (x86, PowerPC, ARM, Sparc, Alpha and MIPS). QEMU supports full system emulation in which a complete and unmodified operating system is run in a virtual machine and Linux... Read more!

  • 09 Dec 2017
    My VM is Lighter (and Safer) than your Container

    My VM is Lighter (and Safer) than your Container 引言 这篇Paper是SOSP‘17上面一个关于轻量级VM的一篇文章,LightVM号称可以在2.3ms启动一个VM, LightVM can boot a VM in 2.3ms, comparable to fork/exec on Linux (1ms), and two orders of magnitude faster than Docker. LightVM can pack thousands of LightVM guests on modest hardware with memory and CPU usage comparable to that... Read more!

  • 06 Dec 2017
    Xen and the Art of Virtualization

    Xen and the Art of Virtualization 引言 这个是一篇很重量级的文章。注意这篇Paper里面的一些描述是在2003年的时候,可能已经不符合现在的情况。这里按照原论文的描述来。 This paper presents Xen, an x86 virtual machine monitor which allows multiple commodity operating systems to share conventional hardware in a safe and resource managed fashion, but without sacrificing either performance or functionality. This is achieved by providing an idealized virtual machine... Read more!

  • 02 Dec 2017
    Speedy Transactions in Multicore In-Memory Databases

    Speedy Transactions in Multicore In-Memory Databases 引言 Silo是一个MIT做的一个内存数据库,使用一种OCC并发控制协议,主要的index结构是Masstree,一种为内存数据库设计的B+tree和trie的结合体。 Silo achieves almost 700,000 transactions per second on a standard TPC-C workload mix on a 32-core machine, as well as near-linear scalability. Considered per core, this is several times higher than previously reported results. 基本架构 Silo本质上还是一个关系型数据,只不过数据都保存在内存。当然Silo也有数据备份到磁盘上面的一个版本SiloR。 Epoch Epoch是Silo中一个很重要的内容,Silo使用epoch机制来实现serializable recovery,垃圾回收,以及read-only snapshots。Epoch就是一段时间。系统换维护一个全局的Epoch,使用E表示。每一个Epoch会由一个epoch number来标示,一个指定的线程会周期性地去更新这个值,每一个在提交事务的时候都必须去参看这个值。Epoch改变的周期设计到事务提交的延迟和系统的一些的overhead,这是一个权衡的问题,在Silo中,这个周期为40ms。另外,每一个worker维护一个本地的Epoch,记为ew,这个值可以滞后于全局的E,但是不能超过1。本地的Epoch用来什么时候可以进行垃圾回收, ...... Read more!

  • 26 Nov 2017
    Fast Databases with Fast Durability and Recovery

    Fast Databases with Fast Durability and Recovery Through Multicore Parallelism 引言 这篇Paper主要讨论的是Silo内存数据库数据快速持久化和快速恢复的问题。SiloR的基本的思路和RAMCloud数据持久化和恢复是一样[4],都是通过使用堆上大量的磁盘来实现的, We design throughout for parallelism: during logging, during checkpointing, and during recovery. The result is fast. Given appropriate hardware (three SSDs and a RAID), a 32-core system can recover a 43.2 GB key-value database in 106 seconds, and... Read more!

  • 20 Nov 2017
    Masstree and Plam

    Masstree and Plam 引言 这篇总结介绍两中新型的数据结构,本质上来说,这两种数据结构都是B+-tree的变体。Masstree是一种结合了trie和b+tree的一种新型的数据结构,为内存数据库设计,被用在了silo这个内存数据库之中。之后又被其它一些相关的系统使用。Masstree的这篇paper中除了讨论Masstree的结构外,还讨论了一些关于其并发操作的内容。这里如果不是必要的话,会忽略这部分的内容,因为在SOSP‘13 silo的论文中有更加详细的讨论。这里只关注数据结构本身。PLAM则是基于Bulk Synchronous Parallel(BSP)编程模型的一种一种并发B+-tree的一种实现,BSP这种编程模型在一些图计算的系统中很常见,比如Google的Pregel[3]。 Masstree基本结构 Masstree可以看作是一棵trie,每个节点是一棵b+tree树。这样就是一种树套树的数据结构: 每一层Masstree的key长度是8bytes。至少包含了一个border节点和 0个or多个的interior 节点,前者和b+tree中的leaf节点相似,但不仅仅可以包含key values,还可以包含对下一层的指针。Masstree这样的结构能获得更加好的缓存性能。Key的保持有以下的规则 (1) Keys shorter than 8h + 8 bytes are stored at layer ≤ h. (2) Any keys stored in the same layer-h tree have the same 8h-byte prefix. (3) When two keys share a prefix, they... Read more!

  • 15 Nov 2017
    Fast Crash Recovery in RAMCloud

    Fast Crash Recovery in RAMCloud 引言 这篇是关于RAMCloud如何快速恢复的Paper,之前已经看过了RAMCloud的内存管理,以及Key-Value系统的实现。这里只会关注如何快速恢复的部分。RAMCloud可以实现在crash之后,将几十GB的数据在1-2内恢复,这个是一个很惊人的数字, RAMCloud employs randomized techniques to manage the system in a scalable and decentralized fashion. In a 60-node cluster, RAMCloud recovers 35 GB of data from a failed server in 1.6 seconds. Our measurements suggest that the approach will scale to recover larger memory... Read more!

  • 11 Nov 2017
    The Tail at Scale

    The Tail at Scale 引言 这个大名鼎鼎的 JEFFREY DEAN发表的一片关于tail-tolerance的一篇文章。一般都知道接口的一个重要的衡量指标就是TOP 90, TOP 99之类的。常见的互联网的服务比如网页加载速度、相关接口的反应时间等等是直接影响到用户体验的。Amazon和Google都要相关的数据表明加载时间长多少ms,用户就会损失多少。这个可以在网上找到相关的文章。 Tail-Tolerance 在较复杂的系统中,长尾延时总是会存在。造成这个的原因非常多,常见的有网络抖动,GC,系统调度等。文章中有总结如下: Shared resources. 公用资源产生的相互影响; Daemons. Global resource sharing. 比如交换机,共享的文件系统; Maintenance activities. Queueing. Power limits. Garbage collection. 这里不仅仅包括类似JVM的GC,还有SSD这类hardware的内部行为; Energy management. key insights: even rare performance hiccups affect a significant fraction of all requests in large-scale distributed systems. eliminating all... Read more!

  • 08 Nov 2017
    NOVA -- A Log-structured File System for Hybrid Volatile/Non-volatile Main Memories

    NOVA: A Log-structured File System for Hybrid Volatile/Non-volatile Main Memories 引言 NOVA是一个利用NVMs加速的Log-structured文件系统。在传统的Log-structured文件系统上面NOVA使用了1. 每一个inode维持一个log来提高并发度;2. 将文件的数据保存在log之外来减小log的体积和加快GC, . Experimental results show that in write-intensive workloads, NOVA provides 22% to 216× throughput improvement compared to state-of-the-art file systems, and 3.1× to 13.5× improvement compared to file systems that provide equally strong data consistency guarantees.... Read more!

  • 05 Nov 2017
    Write-Behind Logging

    Write-Behind Logging 引言 继续讲WAL进化的文章。这次的Paper讲的是NVM上面的WAL应该如何设计。利用NVM掉电不丢数据的特点,这篇Paper描述了Write-Behind Logging。Write-Behind Logging,顾名思义就是在操作之后在写Log。 Using this logging method, the DBMS can flush the changes to the database before recording them in the log. By ordering writes to NVM correctly, the DBMS can guarantee that all transactions are durable and atomic. This allows the DBMS to write less data... Read more!

  • 03 Nov 2017
    From ARIES to MARS

    From ARIES to MARS: Transaction Support for Next-Generation Solid State Drives 引言 WAL是数据库等系统的设计中一个很核心的一个部分。之前的WAL机制如ARIES都是为HHD设计的。对于现在越来越快的SSD和出现的非易失性内存,如何优化原来的WAL设计,更好的利用新的硬件,这篇Paper就是讨论了这个问题。 This paper presents a novel WAL scheme, called Modified ARIES Redesigned for SSDs (MARS), optimized for NVM-based storage. The design of MARS reflects an examination of ARIES, a popular WAL-based recovery algorithm for databases, in the context... Read more!

  • 01 Nov 2017
    ARIES -- A Transaction Recovery Method

    ARIES: A Transaction Recovery Method Supporting Fine-Franularity Locking and Partial Rollbacks Using Write-Ahead Logging 引言 ARIES(Algorithm for Recovery and Isolation Exploiting Semantics,,这篇文章应该是WAL里面最有名的一篇了,发表在1992年,现在很多数据库WAL的设计上都有它的影子。后续的对它的改进和各种的变体也很多。另外,这篇论文长达69页。还有在这篇Paper注意Latch和Lock描述的不同的含义。ARIES有以下的几个特点: 1. 操作之前先在Log中持久化相关的数据,这些log都是只追加的,从来不会修改;2. ‘No-Force’ policy,由于有了Log,也就不需要立即就将更新之后的page持久化;3. ‘Steal’ policy,没有提交的事务更新的pages也能写入到磁盘上面(这个是为了支持”很大”的事务),因为有undo log,这也是可以恢复的;4. 使用LSN (Log Sequence Numbers)来保证标记log,page是基本的管理单位。这Paper中包含了大量的细节信息,对应实际去实现这样的一个系统非常有参考价值。 相关的数据接口 在一个log record中,存在一下的字段: * LSN,唯一地表示一个log record,单调递增。在ARIES中,这个字段比不要实际保存到log记录中; * Type,操作的类型,比如compensation,update,prepare等; * TransID,一个事务的标示符,如果存在,则写入到log record中; * PrevLSN,同一个事务中写入的上一条记录的LSN。一个事务可能写入多个log,它们并不一定是连续的,这个时候就需要这个字段。在非事务的log和一个事务的第一条的log中,这个字段被置为0。 * PageID,只存在与compensation、update类型的记录中,标示那一个数据page被修改。一般包含了table和page number两部分的信息; *... Read more!

  • 29 Oct 2017
    MOSAIC -- Processing a Trillion-Edge Graph on a Single Machine

    MOSAIC: Processing a Trillion-Edge Graph on a Single Machine 引言 MOSAIC是一个单机的Out-of-Core的图计算系统,能够在单机上面处理超过1万亿条边。MOSAIC的主要思路就是利用现在的一些硬件来实现更高的性能,比如NVMe的SSD和利用Interl的Xeon Phi协处理器, MOSAIC consistently outperforms other state-of-the-art out-of-core engines by 3.2–58.6× and shows comparable performance to distributed graph engines. Furthermore, MOSAIC can complete one iteration of the Pagerank algorithm on a trillion-edge graph in 21 minutes, outperforming a distributed disk-based... Read more!

  • 25 Oct 2017
    Storage & Recovery Methods for NVM DB

    Let’s Talk About Storage & Recovery Methods for Non-Volatile Memory Database Systems 引言 这篇Paper主要讨论了数据库的不同类型的存储和恢复方式在NVM上的表现。NVM有着不同于DRAM和SSD的性能特点,自然不同的方式在NVM也有着不同的性能体现。Paper主要讨论了常见的就地更新,Copy-on-Write和 Log-structured Updates在NVM为基础的数据库上的各种的表现。 分类 基本分类: In-Place Updates Engine(InP) InP是数据库中常见的存储策略,更新数据时就直接在原来的数据上进行。 Storage 在InP engine 中,存储空间被分为一些固定长度的blocks,和一些变长的blocks。这两个不同用于存储不同的数据。每一个block由一组slot组成,tuple被保存在这些slot里面,超过8byte的字段被保存在变长的slot里面,原tuple对应的字段的位置就保存地址信息。 When a transaction inserts a tuple into a table, the engine first checks the table’s pool for an available slot. If the pool is... Read more!

  • 22 Oct 2017
    X-Stream -- Edge-centric Graph Processing

    X-Stream: Edge-centric Graph Processing using Streaming Partitions 引言 Xstream是一个以边为中心的单机的图处理系统。同时支持Out-of-Core和In-Memory的处理方式。Xtream有以下的基本的特点:1. 使用scatter-gather的编程模型,将状态值保证到顶点之中;2. 不是以顶点为中心,而是以边为中心;3. 流式地处理无序的表,而不会是去执行随机访问,由于Xstream可能使用的Out-of-Core的方式,这个特性很重要, We demonstrate that a large number of graph algorithms can be expressed using the edge-centric scatter-gather model. The resulting implementations scale well in terms of number of cores, in terms of number of I/O devices, and across different... Read more!

  • 18 Oct 2017
    An Empirical Evaluation of In-Memory MVCC

    An Empirical Evaluation of In-Memory Multi-Version Concurrency Control 引言 In-Memory的数据库也最近的一个研究的热点,此外,MVCC相对于其它存在的Concurrency Control方法,相对来说是最均衡的,新设计的In-Memory绝大部分采用的是MVCC的方法(OCC的缺点太明显了,write一多就abort)。基于MVCC的DBMS允许一个只读事务在读取一个较老版本的同时另外一个事务更新相同的一个对象,能获取更加好的并发程度。此外,如果DBMS没有移除对象的就版本,这个系统就可以支持读取过去一个时间点的快照。虽然有诸多的DBMS使用了MVCC,但是它们之间的MVCC的方式很多不同的地方。这篇论文主要分析不同MVCC在这些方面方面上的一个特点: 1. 并发控制协议; 2. 版本存储; 3. 垃圾回收; 4. 索引管理。 (更新)强烈推荐的一片论文。 MVCC Overview 表1给出了常见数据4个方面的对比: 忽略其一些具体实现的差异,一个基于MVCC的DBMS一般有相同的一些用于事务和数据元组的元数据: Transactions: DBMS会赋予一个事务一个递增的时间戳作为事务id,用于表示这个事务。并发控制协议使用这个标识符标识一个事务可以访问的元组。Tuples: 一个物理上的版本的数据包含了4个元数据字段(具体的可能有些区别),如下图所示: +--------+-----------+---------+---------+------+-------------------------------+ | | | | | | | | txn-id | begain-ts | end-ts | pointer | ... | cloumns... | | |... Read more!

  • 12 Oct 2017
    Consistency Tradeoffs in Modern Distributed Database System Design

    Consistency Tradeoffs in Modern Distributed Database System Design CAP理论深刻地影响了分布式数据库的设计,另外一个方面,一致性和延迟之间的权衡也对现在的数据库产生了直接的影响。未来融合这个两者,一个新的理论PACELC[2]被提出。DDBSs正在正在变得越来越”大”, 2个主要的原因促使了这种变化,第1个是现在的应用需要越来越多的数据和越来越高的事务处理能力,第2个是因为增长的跨国企业的需要在全球范围内开展业务,需要将数据中心建立在靠近客户的地方。在过去10年开发的DDBSs都具有高可用性或(和)全球范围内范围的能力,比如SimpleDB/DynamoDB,Cassandra,Voldmort,HBase/BigTable,MongoDB,VoltDB/H-Store以及Megastore等。 DDBSs是一个复杂的系统,开发这样一个系统是非常困难的。DDBS的设计是一门权衡的艺术,其中CAP理论是很重要的一个部分。虽然CAP很重要,但是论文[1]认为CAP被滥用了,仅仅只考虑C A P之间的权衡是不够的。实际上,CAP讨论的是故障复发生之后的一些限制。正常情况下,更为常见的权衡是一致性和延时之间的权衡,它也深刻地影响了DDBS的设计。PACELC被提出统一这些权衡,PACELC的含义为: P then AC else LC,意为在网络分区发生的时候系统需要在可用性和一致性之间做出权衡,而没有网络分区的情况下,系统需要在一致性和延时之间做出权衡。 CAP是关于故障的 由于CAP理论中三个最多只能取其二,只有以下几种类型的系统是可能的: CA,没有网络分区;CP,不能保证高可用;AP,不能保证一致性。现在很多的DDBS(默认情况下)都不保证C,比如SimpleDB/Dynamo, Cassandra等。早期的DDBS的研究的关注点在一致性,很自然的认为CAP是影响数据库架构的主要因素。DDBS是必须要能容忍出现网络分区的,这样的话,DDBS这能在A和C之间做出选择。对于可靠性有高要求的应用就只能舍弃C。 看上去这里是没有问题的。但是实际上还是有一些瑕疵,这个观点不仅仅是一致性和可用性之间的权衡,而且还包括了网络分区和网络分区的存在这个件事情。也就是,这里只是简单地认为网络分区的存在得让我们在一致性和可用性之间做出选择。但是网络分区可能性是多种原因决定的: 系统在WAN上运行?或者知识一个局部的集群?使用了什么样的硬件?等等。通常网络分区是很少见的,发生的频率低于系统中的其它类型的故障。在没有网络分区的情况下,CAP允许系统完整的实现ACID的前提下也实现高可用性。CAP理论不是这些在正常的情况下减弱一致性的理由(比如SimpleDB/Dynamo, Cassandra等)。 一致性和延时之间的权衡 理解现代一些DDBS的设计要先了解它们面向的使用场景,现在的很多DDBS(比如SimpleDB/Dynamo, Cassandra等)面向的使用场景是在线活动,对交互的延时比较敏感,延时多上100ms可能就导致用户的流失。不幸的是,在一致性、可用性和延时之间存在基本的权衡,即使没有网络分区,这种权衡也会存在,这种权衡与CAP无关。及时如此,这张权衡也是这些系统设计的关键因素。 高可用性机遇就意味着复制数据。为了实现尽可能高的可用性,DDBS就得在WLN复制数据,防治一个数据中心因为某些原因被整个损坏(比如地震、飓风)等。当出现数据复制时,就会有一致性和延时之间的权衡。只有3种方法来实现数据复制: 1. 系统同时发送更新给所有副本;2. 发送给特殊的master节点;3. 随机发送给一个节点。无论哪一种方法,都存在一致性和延时之间的权衡。 同时发送给所有副本 如果更新不经过预处理合作其它的协议,因为每个副本得到的更新的顺序可能是不同的,这样就会导致明显的缺失一致性。而如果经过预处理合作通过其它协议来保证副本应用更新的顺序,这样的话,这些操作就是延时的来源。如果使用的是使用某种协议的方法,那么协议本身就是一种延时的来源。 在使用预处理方法的情况下,主要有两个延时的来源,第一个是附加的预处理会增加延时,第二,预处理器由几台机器或者一台机器组成,多台机器的情况下又需要某种协议来保证更新的顺序,一台机器的情况下任何位置的更新都得像这个单一的节点请求更新。 数据更新发送到一个商定的位置 这个商定的位置可以称为master。Master节点所有的请求然后更新数据。由于只由master来处理请求,所以更新执行的顺序是可以保证的。Master执行玩操作后,会复制到其它的节点。这个复制有3种不同的选项 1. 同步复制: Master节点会一直等待知道所有的副本都已经复制完成。这样一致性是有保障的,但是延时不可避免地会增大。 2. 异步复制: 系统会认为在复制完成之前就认为更新已经完成。通常会保证更新的数据以及被持久化保存,但不保证更新已经同步到所有的节点,这种情况下,一致性和延时的权衡取决于系统如何读取: 如果读取请求全部有master节点处理,那么不会有一致性的问题,但是这种方法可能造成2个延时: * 发送读取请求的客户端可能距离master节点很远,即可可能存在离这个客户端很近的副本,但是不能使用; * 如果master节点负载过高或者失败,则客户端必须等待master节点负载降低或者从失败中恢复,缺乏负载均衡会增加延时。 *... Read more!

  • 09 Oct 2017
    Adaptive Radix Tree

    The Adaptive Radix Tree: ARTful Indexing for Main-Memory Databases ### 引言 Adaptive Radix Tree是最近出现的为Main-Memory Database设计的的支持范围数据结构里面个人认为最优美的一种了,不如Masstree,Bwtree那么复杂,另外,相比于传统的一些结构如T-tree,也更好的适应了现代的多核处理器。这篇时关于Adaptive Radix Tree(ART)的基本结构的,另外有一篇时关于ART的Concurrency Control的,之后会加上。ART的主要思路时使用不同大小的Node,来减少内存使用。同时加上一些额外的如高度上的优化。 基本结构 前面提到,ART的内部Node有不同的大小。一般而言,离root比较远的Node里面保护的数据项时比较小的。一般的Radix Tree使用完整的Node的话,会浪费很多的内存,而ART就解决了这个问题: ART可以做到 With 32 bit keys, for example, a radix tree using s = 1 has 32 levels, while a span of 8 results in only 4 levels.内部 Node描述: *... Read more!

  • 26 Sep 2017
    Self-Driving Database Management Systems

    Self-Driving Database Management Systems 引言 这篇文章是CMU发表的关于自治数据库的一篇文章,对应的数据就是Peloton,为CMU开发的一个学术型的内存数据库。自治数据库时利用现在的一些人工智能以及相关方法来实现自我管理的数据库,可以让数据库自我实现一起需要DBA才能完成的操作, With this, the DBMS can support all of the previous tuning techniques without requiring a human to determine the right way and proper time to deploy them. It also enables new optimizations that are important for modern high-performance DBMSs, but which are not possible... Read more!

  • 20 Sep 2017
    Bridging the Archipelago between Row-Stores and Column-Stores for Hybrid Workloads

    Bridging the Archipelago between Row-Stores and Column-Stores for Hybrid Workloads 引言 现在的数据系统中常见的两种存储方式就是行存与列存,常见的关系型数据库使用的是行存的方式,一些NoSQL如HBase之类的使用的是列存的方式。一般认为行存的方式更加适用于OLTP的环境,而列存更利于OLAP的方式。在现在的一些数据库系统,提出来HTAP(hybrid transaction- analytical processing)的概念,就是混合来OLTP和OLAP的方式。在这样的系统中。这篇文章是CPU在它的学术型数据库Peloton使用的一种混合的存储方式,FSM(flexible storage model ), We also present a technique to continuously evolve the database’s physical storage layout by analyzing the queries’ access patterns and choosing the optimal layout for different segments of data within the same... Read more!

  • 14 Sep 2017
    PacificA -- Replication in Log-Based Distributed Storage Systems

    PacificA: Replication in Log-Based Distributed Storage Systems PacificA是微软推出的一个通用的复制框架。论文[1]中强调PacificA是一个简单、实用和强一致性的。也许是基于Paxos的方法被太多的吐槽了关于复杂,难以理解难以实现,Raft、PacificA等算法都特别强调自己简单易于理解也相对容易实现。选择一个合适的复制算法就算选择一个正确的架构设计,简单和模块化是设计的几个要点。PacificA的设计有以下的特点: PacificA将配置管理和数据复制分离,由基于Paxos的模块来负责管理配置,主副本(primary/backup)策略来复制数据; 去中心化的错误检测和触发配置,监控流量遵循数据复制的策略; PacificA是一个通用的抽象的模型,易于验证,可以有不同的策略实现。 系统有以下的假设: 系统运行在一个分布式的环境之中,一些server组成集群,这些server随时可能失败,这里假设的情况是失败之后就停止运行(fail-stop failures),信息在传输的过程中可能被延时任意长的时间达到,也可能丢失,可能会发生网络分区。时钟也是不可靠的。PacificA可以在一个n+1个副本的系统中最多容忍n个副本故障。 主副本数据复制 系统将客户端的请求分为两种: queries请求只请求数据而不会更新数据,而updates请求会更新数据。所有的请求都会发送个primary,primary会处理全部的请求,而只会在updates请求的时候才会让副本参与进来。这样的主副本的策略好处就是简单易于实现。如果更新操作的结果是确定的,且所有的服务器都以系统的顺序处理了相同的请求集合,那么就可以实现强一致性。为了实现这个目标,primary(主副本)会赋予每一个请求一个唯一的单调递增的序号给所有的updates请求,每个次副本都的安装这个序号表示的顺序进行处理。这里可以表示为每个副本都维持了一个包含了它收到的所有请求的prepared list和一个对于这个list的一个commited point。这个list会根据序号排序,commited point之前的prepred list部分就是commited list。 正常情况情况下的查询和更新协议 正常情况下,primary对于接受到的queries的请求,直接就查询commited list之中的结果如何回复客户端即可。对于updates请求,primary会先给这个请求赋予下一个的编号(编号可以初始化为0),然后将这个请求带上编号和当前配置版本号(prepare message)发送给所有的次副本。在收到prepare message后,次副本会将这个请求插入prepared list(注意要按照编号的顺序),在次副本确认这个请求被安置妥当之后,就发送给primary一个ack以告知自己已经将这个请求安置妥当。当primary在收到了所有的次副本的ack之后,primary就会提交这个请求(The request is committed when the primary receives acknowledgments from all replicas)。然后,primary会移动它的committed point,然后向所有的次副本发送消息通知它们已经处理完毕,在收到了primary确认成功的消息之后,次副本也就可以移动它的committed point的了。在这种处理方式之中,会有以下的结论: Commit Invariant: Let p be the primary and q... Read more!

  • 12 Sep 2017
    A Quorum-Based Commit Protocol

    A Quorum-Based Commit Protocol 在distributed computing中,quorum是指分布式执行时必须获得的最小的票数[2],常被用于分布式的commit protocol和replica control。这里我们来看看论文[1]描述的一种quorum-based commit protocol。 介绍 这个Quorum-Based Commit Protocol(下文简称protocol or 协议)使用quorum的方式来解决错误发生之后的冲突。当有一个错误发生之后,一个事务只能在被一个quorum commit的情况下commit,这个quorum称为commit quorum,表示为V(C),同理,一个事务abort只有在一个quorum abort的情况下abort,这个quorum称为abort quorum,表示为V(A)。这个protocol有以下的一些的特点:1. 这是一个集中式(centralized)的协议(也就是说存在中心节点);2. 当所有的错误(failure)被解决之后,协议最终会终止;3. 这是一个阻塞的协议,只有当错误被修复之后才能继续运行。此外,协议可以从多种的失败中快速恢复,但是主要关注的错误的网络分区,主要是以下两种类型: 节点失败和消息丢失,这个两类情况都可以被视为是网络分区错误。 协议 在介绍这个协议之前,先来看一看经典的2PC协议,2PC可以用下图简单地表示: +---------+ | | | q | | | ++---------+ | | +----------+ | | +----------+ | | | +-> | | | w |... Read more!

  • 11 Sep 2017
    In Search of an Understandable Consensus Algorithm

    In Search of an Understandable Consensus Algorithm Raft算法[2]是一致性新晋的热门选手。Raft在一些方面和Viewstamped Replication[4]相似。Raft也有一它自己的特点[1,3]: 强领导者: Raft中领导者的地位更高,日志条目指由leader发送给其它部分。这个方式更加简单且易于理解; 领导选举: Raft在领导选举中使用了一随机的计数器,这在解决领导选举的冲突时会更加有效; 成为变更: Raft在成员变更时使用了一种新的joint consensus方法,这使得及时在成员变更时Raft也能工作。 Raft存在以下概念: Leader: 通常情况下,系统中只有一个leader,Follower: 通常情况下,出leader之外的都是follower。 Candidate: 领导人选举时的一种身份状态。Term: 一个成员担任领导人的这段时间,算法中会用一个递增的数字(任期号)表示。Raft主要分为3个部分: 1. 领导选举; 2. 日志复制;3. 安全性。 领导选举 到Follower发现自己和Leader之间的心跳出现问题时,它就会启动一次新的选举。Foller首先要递增它当前的任期号,然后转变自己为Candidate状态,然后并行地向其它成员发送投票请求,知道以下情况发生然后停止: 1. 它赢得了选举; 2. 其它成员成为Leader,3. 一段时间过后没有选举出领导人。 当一个Candidate获得半数以上的选票时,它就赢得了选举。每个领导者只会对一个任期号的第一个投票请求投票。在赢得选举之中,就会向其它成员发送消息来确定自己的地位。在等待投票的时候,它就可能收到其它成员的投票的请求,如果这个请求中的任期号比自己当前的任期号,那么它就会投这一票并回到Follower的状态,否则,拒绝请求。这里可能发生的一种情况时几个候选人争夺Leader位置导致无法选举出Leader,Raft使用的解决方案时选举超时的时间从一个时间区间内随机选择(比如150ms ~ 300ms), 日志复制 对于Leader处理的每一条记录,它都会把这条记录追加到自己的日志里面,然后向所有的Follower发送消息,要求他们复制这条记录,当确认这条记录被一半以上的称为保存之后,Leader向客户端返回成功,对于没有及时回复Leader的Follower,Leader会一致重试指到所有的Follower都保存了所有的日志。日志在被复制到多数的成员中之后,Leader就会提交这个日志,同时这日志之前的所有的日志也会被提交。日志在每个成员都是顺序保存的。Raft维护日志有以下的特点: 如果不同的日志中的两个条目有相同的索引和任期号,那么它们就保存了相同的内容; 如果不同的日志中的两个条目有相同的索引和任期号,那么它们之前的所有条目也相同。 对领导选举的限制 ​ 不同于其它的一致性算法(包括Viewstamped Replication)一个成员可以被选举为Leader,及时它没有保存所有的已经提交的日志条目。这些算法就需要额外的机制来让新的Leader获取到这个日志。而Raft不同,它可以保证所有的之前的任期号内的已经提交的日志都已经保存在新的Leader之中。 ​ Raft使用的方式是一个成员只能在已经包含了所有的已经提交的日志条目的情况下才能赢得选举。一个成员要想赢得选举,它必须获得半数以上的选票,这些选票中一定会有一个成员保存了所有的已经提交的条目,这样就可以达到阻止没有包含所有的已经提交的日志的成员被选举为Leader。Raft通过比较两份日志中最后一条日志条目的索引值和任期号来定义谁比较新,如果最后的条目的任期号不同,那么任期号大的比较新,如果任期号相同,那么索引更大的比较新。在Raft中,Leader处理日志的一些不一致时直接通过强制要求Follower复制自己的日志来解决的,有冲突的日志会被覆盖(只会是那些没有提交的日志)。 安全性 关于Raft的安全性的证明,论文[1]中有详细的描述,这里就不说了。... Read more!

  • 10 Sep 2017
    Paxos Made Simple

    Paxos Made Simple Paxos是分布式系统中的一个非常重要的算法,用于解决容错的分布式系统中对一个值达成一致的算法。论文[1]以一种很好的理解的方式描述了这个算法(这里讨论的是基础的paxos算法,不是其它的变种)。算法假设有以下的一些条件: 1. 进程(or 角色)一任意的速度执行,每个都可能出错、停止运行,也可能错误之后恢复过来。所有进程可能在选定这个值值后都失败重启,它们可能在重启之后不能确定之前被选定的值,除非其中的一些进程保存下了这些信息。 2. 信息在传输的过程中可能被延时任意长的时间达到,也可能丢失、重复,但是信息的被人不会被修改。 总的来说,这篇paper讲的还是很清晰的。 提出问题 考虑在一个可能发生一些错误的一个分布式系统中,多个进程针可以提出自己的value,最终这个进程将会对这个值达成一致。当然在没有值没有被提出的时候,也就没有值会最终选定。当只有一个值被提出的时候,算法也要保证最终被选定的值就是这个唯一提出的值,多个不同的值被提出来之后,最终只会有一个值被选定。如果一个值一旦被选定,这些进程能知道这个值。总结如下,为了保证safety的要求,算法要求: 1. 只有一个值被提出之后才能被选定; 2. 只有一个值最终被选定; 3. 一个进程认为被选定的值必须是真的最终被选定的值。 在这个算法之中,有以下的概念: Proposal: 这里可以理解为代表了一个值,Proposer: 提出Proposal, Acceptor: 决定是否接受Proposal, Learner: 接受被选定的值。 选定一个值 由于算法要求只有一个进程提出一个值的情况下这个值也会被选定,所以算法必须满足以下的要求: P1: 一个Proposer必须接受它收到的第一个Proposal 这又导致另外一个问题,由于系统中可能存在多个的Acceptor,这种做法可能导致不同的Acceptor接受了不同的值,所以这里最初一个规定: 规定: 一个Proposal只有在一半以上的Acceptor接受的情况下才能被选定 为了实现这个规定,就要求可以选定不同的Proposal(因为不这样的话就可能无法到达半数以上的Acceptor接受)。在这里,为了区分这些Proposal,我们赋予每个Proposal递增的一个编号。为了保证选定了不同的Proposal也能得到最终准确的结果,这里要求被选定的不同的Proposal的值是相等的。所以有如下的要求: P2: 如果一个Proposal被选定了,每个被选定的有更高的编号的Proposal的值必须与此相同 为了选定一个Proposal,必须要求有一个Acceptor接受,也就是说: P2a: 如果一个Proposal被选定了,那么每一个被Acceptor接受的Proposal必须与此相同 这个算法中,通信是不可靠的,进程也可能失败后又重启,也就可能存在下面这种情况: 一个Acceptor c之前没有收到过之前的Proposal,又有一个”新”(可能从失败之后恢复了过来)的Proposer向其发送了一个有更高编号的带有不同值的Proposal,由于要求P1,c必须接受这个Proposal,这就会导致维持P1和P2a直接的矛盾。为了解决这个问题,提出了以下的要求: P2b: 如果一个Proposal被选定了,那么之后的Proposer提出的编号更高的Proposal的值也必须与此相同。 从P2b可以推导出P2a,P2a有可以推导出P2(具体证明略,可以参考[1]). 那么如果保证P2b呢,这里采用的方法就是P2c: P2c: 对于任意的v和n,如果一个值为v,编号为n的Proposal被提出,存在一个半数以上的集合S满足下面两个中的任意一个条件: a: S中的任意Acceptor没见接受过比n小的Proposal;... Read more!

  • 25 Aug 2017
    Facebook Gorilla

    Facebook Gorilla Gorilla是Facebook公司内部的时序数据库产品。Facebook在世纪的使用过程中发现现有的产品不能满足对Facebook超大数据量的处理要求,开发了Gorilla这一样一个产品,通过应用多种压缩方法、将数据放在内存之中,Gorilla获得了73x的延时提升、14x的吞吐量提升。 介绍&背景 2013年Facebook就开始使用一套基于HBase的时序数据库,但是随着Facebook的发展,这套系统以及不能满足未来的负载,90%的查询已经长达几秒。一个对几千个时间序列的查询要消耗几十秒的时间来执行,而在稀疏的更大数据集上查询通常会超时。HBase被设置为写入优化,现在在其中已经保存了2PB的数据,查询的效率不高,又不太好完全更换系统。所以,Gorilla讲注意力转移到给现有的系统在一个in-memory的cache。这里数据的特点就是新数据一般是热点数据,所以选择奖近段时间内的数据cache,就能很好地提高性能。 Memcache是Facebook大规模使用的一个缓存系统,但是将memcache应用在这里,追加新数据到已经存在的时间序列中要消耗一个read/write周期,给memcache造成很大的压力,所以需要一种更好的解决方案。注:这里没怎么看懂,原文是: We also considered a separate Memcache [20] based write-through cache but rejected it as appending new data to an existing time series would require a read/write cycle, causing extremely high traffic to the memcache server. We needed a more efficient solution. 对于Gorilla,主要有以下的要求: 1. 2billion的unique的时间序列id,以string表示;... Read more!

  • 19 Aug 2017
    A Critique of ANSI SQL Isolation Levels

    A Critique of ANSI SQL Isolation Levels 在ANSI SQL-92 [MS, ANSI](之后简称SQL-92)根据Phenomena(这个类似专有名词,不翻译了,中文意思是‘现象’)定义了SQL的隔离级别:Dirty Reads, Non-Repeatable Reads, and Phantoms。《A Critique of ANSI SQL Isolation Levels》[1]这篇paper阐述了有些Phenomena是无法用SQL-92中定义的一些隔离级别正确表征的,包括了各个基本上锁的实现。该论文讨论了SQL-92中的Phenomena中的定义模糊的地方。除此之外,还介绍了更好表征隔离级别的Phenomena,比如Snapshot Isolation。 介绍 不同的隔离级别定义了不同的在并发、吞吐量之间的取舍。较高的级别更容易正确的处理数据,而吞吐量比较低的隔离级别更低,较低的隔离级别更容易获得更高的吞吐量,却可能导致读取无效的数据和状态。SQL-92定义了4个隔离级别:(1) READ UNCOMMITTED, (2) READ COMMITTED, (3) REPEATABLE READ, (4) SERIALIZABLE. 它使用了serializability的定义,加上3种禁止的操作子序列来定义这些隔离级别,这些子序列被称为Phenomena,有以下3种:Dirty Read, Non-repeatable Read, and Phantom。规范只是说明phenomena是可能导致异常(anomalous)的动作序列。ANSI的隔离级别与lock schedulers的行为相关。一些lock scheduler允许改变lock的范围和持续的时间(一般是为优化了性能),这就导致了不符合严格的两阶段锁定。由[GLPT]引入了以下3种方式定义的Degrees of Consistency(一致性程度): 1. 锁(locking); 2. 数据流图(data flow... Read more!

  • 10 Aug 2017
    SLIK -- Scalable Low-Latency Indexes for a Key-Value Store

    SLIK: Scalable Low-Latency Indexes for a Key-Value Store 引言 前面看过的Log-structured Memory for DRAM-based Storage是RAMCloud关于内存管理的部分,SLIK的RAMCloud中关于Key-Value的部分。SLIK最大的几个特点: multi-key-value store,这个事与一般的KVS最大的不同的一个地方,一般的系统都是一个key对应一个value,这个SLIK实现了类似次级索引的功能。Value和很多的KVS一样,都是当作一个bytes的对象而已; SLIK的索引和对象事分开的,而不是保存在一起; 由于分布式的方式能带来可拓展性的同时也带来的一致性的问题,这里SLIK可以保证对客户端可见的一致性。它使用了一种创新的轻量级的方式来更新索引。 SLIK可以将耗时的操作放在后台运行,而不会影响到系统的正常运行; SLIK的次级索引使用的是Btree,使用映射到主键hash值的方法保持了Btree节点的紧凑性,这里就可能导致hash冲突的问题,如何解决这个问题之后会提到。 ... the resulting system provides extremely low latency indexing and is highly scalable: • SLIK performs index lookups in 11–13μs, which is only 2x the base latency of non-indexed reads.... Read more!

  • 08 Aug 2017
    Chain Replication

    Chain Replication for Supporting High Throughput and Availability Chain Replication是一个容易理解的复制方式,primary-backup,N个服务器可以容忍N-1服务器失效。它不处理拜占庭类的错误。 上面这幅图就很容易说明了它的工作方式,更新操作发送给head,随着chain传递到tail,而查询等的操作都发送给tail。在client看来: 错误处理 在这里添加了一个master的服务,它用来探测服务器故障,通知服务器它的pre-decessor 和 successor 更新消息,通知client哪一个服务器是head,哪一个服务器是tail。Master自身使用Paxos来保证可靠性。 head 故障 head的下一个服务器成为新的head。 PendingobjID is defined as the set of requests received by any server in the chain and not yet processed by the tail, so deleting server H from the chain has the... Read more!

  • 01 Aug 2017
    Viewstamped Replication

    Viewstamped Replication Viewstamped Replication(VR)是一个适用于故障-停止的异步系统中的一个关于复制的算法,发布于80年代[2]。 在论文[1]中有一段这样的话: VR was originally developed in the 1980s, at about the same time as Paxos [5, 6], but without knowledge of that work. It differs from Paxos in that it is a replication protocol rather than a consensus protocol: it uses consensus, with a protocol very... Read more!

  • 26 Jul 2017
    Log-structured Memory for DRAM-based Storage

    Log-structured Memory for DRAM-based Storage 引言 Log-structured的文件系统是很有名的一类文件系统了,其Log-structured设计的主要目的就是讲写入转化为顺序写来提高性能。而这篇文章在Main-Memory的存储系统是讨论了Log-structured的内存分配,主要目的是提高内存利用率,此外就是提高性能。这个是RAMCloud系统的一部分。 动机 通用的使用malloc(or类似方式)的内存管理方式的一个缺点就是低的内存利用率: 从这个图标来看,各个的利用率都很不好看。 基本设计 在看这里之前需要对Log-Structured File System有些了家,如果没有,可以看看论文[2]。这里的allocator时为RAMCloud设计的,这里就可以把它看作是一个Key-Value Service。基本情况如下: LFS中log包含了很多额外的索引的信息,为的是方便读取。由于DRAM的特点以及这个allocator不会存在文件系统那样的结构,所以log的结构上会简单很多。每一个object必须包含了以下的数据(paper中还讨论了很多关于从持久化的存储中recovery的内容,这里只关注这个内存分配器的设计,RAMCloud关于recovery有另外的论文): the table identifier,2. key, and 3. version number for the object in addition to its value 。 每个segment包含了整个log的信息摘要。删除一个object时候,是在log的后面添加一个tombstone记录,tombstone 包含了 table identifier, key,和 被删除object的version number。 Tombstones have proven to be a mixed blessing in RAMCloud:... Read more!

  • 25 Jul 2017
    Facebook F4

    f4: Facebook’s Warm BLOB Storage System F4使用设计和Haystack一起使用,来降低成本的对象存储系统,一个基本的出发点就是Haystack中保存的对象(比如图片)在刚刚一开始用户传上去的时候使用频繁,不久之后使用率就会大大降低。Haystack 3-备份的形式好处在于性能良好,缺点在与成本比较高。F4使用了Reed-Solomon编码在实现高可靠的同时将副本的数量降下来。 Overview F4的数据都是从Haystack转移过来的,所以对于F4来说,它不需要insert的操作。F4只支持read和delete操作。通过10 + 4的所罗门编码blocks,每一个block的size为1GB: The block-size for encoding is chosen to be a large value—typically 1 GB—for two reasons. First, it decreases the number of BLOBs that span multiple blocks and thus require multiple I/O operations to read. Second, it reduces the... Read more!

  • 20 Jul 2017
    Consistent Hash

    Consistent Hash About 一致性hash算法的概念在很多地方都可以找到很详细的说明,这里就不在说明。简单的来说:一致性hash就是如何将N个对象就可能平均分配到M个节点之中(这里抽象为一个节点),并且在节点的数量在增加或者减少时尽量减少对象的重新分配,还要保证在节点增加时原有已分配的内容可以被映射到新的缓冲中去,而不会被映射到旧的缓冲集合中的其他缓冲区。 基于环的一致性Hash算法 基本思想 这个算法时最经典的一致性Hash算法。这个算法的基本思想是将value映射为一个值,通常情况下是一个int,而hash值存在一个数值空间,将这个空间抽象为一个环,比如0 - 2^ 32-1,0和2^32-1首尾相接。在这个空间之中,从对象的hash值出发(沿着一个方向),直到遇到一个节点,那么这个对象就放入这个节点。当节点减少时,只有这个节点到下一个节点之间的对象需要重新移动;当在环中增加一个节点时,只有这个节点到上一个节点之间的对象需要重新移动。满足了一致性hash的基本要求。 一个优化 Hash算法不能保证完全hash值完全平均分配,而且完全平均分配从理论上证明了这是不可能的(具体记不清了)。不过在节点足够多以及hash函数很好的话,这还好。但是当节点的数量很少时,这个就很容易发生不平均的问题。为了优化这种情况,引入了“虚拟节点”的概念: 所谓虚拟节点,就是一个实际的节点回应了对个虚拟的节点。 通过虚拟出更多的节点来优化这个问题。 Jump Consistent Hash jump consistent hash, a fast, minimal memory, consistent hash algorithm that can be expressed in about 5 lines of code. In comparison to the algorithm of Karger et al., jump consistent hash requires... Read more!

  • 12 Jul 2017
    Finding a Needle in Haystack

    Finding a Needle in Haystack: Facebook’s photo storage Haystack是对象存储的经典设计,它是Facebook的照片应用而专门优化定制的对象存储系统。Facebook在峰值时需提供每秒查询超过1 million图片的能力。设计上的关键点: 传统的基于NAS or NFS的存储图片的方式,因为元数据查询而导致了过多的磁盘操作。在Haystack的设计中,追求尽量减少每个图片的元数据,让Haystack能在内存中执行所有的元数据查询。在传统的POSIX的文件系统中,读取一个图片要经过读取目录信息,读取文件信息,最后才能读取文件信息,要经过多次的磁盘操作。访问文件的元数据成为了吞吐量的瓶颈。 每个数据只会写入一次、读操作频繁、从不修改、很少删除; 设计目标:1. 高吞吐量和低延迟。2. 容错。3. 高性价比。4. 简单。 架构 Haystack架构包含3个核心组件:Haytack Store、Haystack Directory和Haystack Cache。 Store是持久化存储系统,并负责管理图片的文件系统元数据。Store将数据存储在物理的卷上,此外,不同机器上的多个物理卷对应一个逻辑卷。一个图片存储到一个逻辑卷时,图片被写入到所有对应的物理卷。在物理卷的基础之上加上一个逻辑卷的方法可以解决一个物理卷损坏时导致的数据丢失和服务不可用。 Directory维护了逻辑到物理卷的映射以及其的元数据,比如某个图片保存在哪个逻辑卷已经某个逻辑卷的空闲空间的信息。 Cache的功能类似系统内部的CDN,主要处理热门的图片。Cache会尽可能的cache图片数据。Cache的存在也让系统在没有CDN的情况下也能很好的工作。 基本操作 访问一个图片:当用户使用Directory为每个图片来构建的一个URL来访问一个图片。这个URL包含几段信息,每一段内容对应了到从浏览器访问CDN(或者Cache)直至最终在一台Store机器上检索到图片的过程。一个典型的URL如下: http://<CDN>/<Cache>/<Machine id>/<Logical volume, Photo> 第一个部分指明了从哪个CDN查询此图片。到CDN后它使用最后部分的URL,包含了逻辑卷和图片ID等信息,即可查找缓存的图片。如果CDN未命中缓存,则从URL中删除相关信息,然后访问Cache。Cache的查找过程与之类似,如果还没命中,则去掉相关信息,请求被发至指定的Store机器,即。访问的过程也可以不经过CDN,而直接访问Cache。 Cache向Store请求一个图片时,需要提供逻辑卷id、key、alternate key,和cookie。Cookie的设计主要是为了安全,cookie是个数字,嵌在URL中。当一张新图片被上传,Directory为其随机分配一个cookie值,并作为应用元数据之一存储在Directory。此cookie可以保证所有发往Cache或CDN的请求都是经过Directory“批准”的,而Store,Cache就能放心处理数据。当Store机器接收到Cache机器发来的图片查询请求,由于元数据会被保存在内存之中,可以快速查找。如果图片没有被删除,Store在卷文件(一个卷文件保存了大量的图片)中seek到相应的offset,从磁盘上读取整个图片的数据(这里被称为needle),然后检查cookie和数据完整性,若都合法则将图片数据返回到Cache机器。 上传一个图片:用户上传一个图片时,图片首先被发送到web服务器。web服务器随后从Directory中请求一个可写逻辑卷,然后web服务器为图片分配一个唯一的ID,web服务器必须向store辑卷id、key、alternate key、cookie和真实数据等信息。Store接受到之后,store创建一个新的needle,添加到卷文件的末尾,更新保存在内存中的元数据和映射。更新一个图片:Haystack的设计是不考虑修改图片的。Store append-only的工作方式也不能很好的支持修改性的操作,又haystack并不允许覆盖needle,所以图片的修改都是直接通过添加一个新needle,其拥有相同的key和alternate key来完成。而如果更新之后的needle被写入到与老的needle不同的逻辑卷,需要Directory更新它的应用元数据,未来的请求都路由到新逻辑卷,如果被写入到同一个逻辑卷,则也会被store保存到同一个物理卷,根据offset的不同就可以判断文件的新旧。删除一个图片:删除图片时,store机器将内存中元数据和卷文件中相应的flag设置为已删除,只是标志已经删除。当接收到已删除图片的查询请求,会被直接返回错误信息。删除操作的最终完成是通过逐个复制needle到一个新的卷文件,并跳过任何重复项、已删除项。 Store 读操作只需提供图片ID、哪个逻辑卷、哪台物理Store机器等信息,就可以找到图片,如果机器做不到,则会返回错误信息。每个Store机器管理多个物理卷,而每个物理卷存有百万张图片。一个物理卷是一个非常大的文件(大约为100GB)。文件名字格式如下 /hay/haystack<logical volume id> 所以,store有了logical volume id和图片的offset就能非常快的访问一个图片。Store机器会将其下所有物理卷的文件描述符缓存在内存中。图片ID到文件系统元数据(文件、偏移量、大小等)的映射是检索图片的重要条件,也会全部缓存在内存中。一个物理卷是一个大型的文件,由一个Superblock和一系列的needle组成,每个needle就是一张图片。一个needle会包含以下的字段: 字段 解释... Read more!

  • 07 Jul 2017
    Mapreduce and Spark

    MapReduce: Simplified Data Processing on Large Clusters 引言 这两篇Paper好像之前就看过。另外Mapreduce和Spark产生的影响还是很大的,后续的发展也很多,这里就只看看它们原始的论文里面提到的一些东西吧。Mapreduce在分布式系统中确实是一个里程碑性质的作品s,最后面相关的系统研究产生了非常大的影响。 编程模型 Mapreduce中任务都被抽象位map和reduce两个部分, map (k1,v1) → list(k2,v2) reduce (k2,list(v2)) → list(v2) 一个基本的word count的例子, map(String key, String value): // key: document name // value: document contents for each word w in value: EmitIntermediate(w, "1"); reduce(String key, Iterator values): // key: a word //... Read more!

  • 02 Jul 2017
    Megastore -- Providing Scalable, Highly Available Storage for Interactive Services

    Megastore: Providing Scalable, Highly Available Storage for Interactive Services 引言 Megastore就是为了解决Bigtable存在的一些问题而产生的,也是基于Megastore而设计的。Megastore在NoSQL的可拓展性上面的实现了传统的RDMS的可用性。当然在Spanner出现后,Megastore被吐槽延时太高等的缺点。这篇Paper还是值的一看的。 高可用性和可拓展性 分区和局部性 为了支持分区,Megastore引入了Entity Group的概念,每一个Group都是独立地跨区域的同步复制。低层的数据保存在NoSQL中,实际使用的就是Bigtable。在一个entity group里面的entity单步骤的事务就可以处理,相关的提交的理解通过Paxos来进行复制。当操作需要跨越Entity Group是就需要2PC来完成事务的操作。 为了优化2PC的操作,Megastore使用异步消息的方式来处理,这些消息通过队列来完成。下面的图就表示了这种方式。这里要注意的是使用异步消息的两者之间的距离是逻辑上的,而不是物理上面的距离,也就是这里的其实就是在一个数据中心里面的,而在不同数据中的操作都是通过同步的复制来完成的。一个Entity Group里面的索引(Local Index,下面的图中有表现)服从ACID语义,而跨越Entity Group的Index一致性是一种弱的一致性。 Note that we use asynchronous messaging between logically distant entity groups, not physically distant replicas. All network traffic between datacenters is from replicated operations, which are synchronous and consistent.... Read more!

  • 22 Jun 2017
    毕业了

    毕业了 不悔梦归处,只恨太匆匆 Somewhere, a voice calls, in the depths of my heart   May I always be dreaming, the dreams that move my heart      So many tears of sadness, uncountable through and through   I know on the other side of them I'll find you      Everytime we fall down to... Read more!

  • 19 Jun 2017
    Ceph -- A Scalable, High-Performance Distributed File System

    Ceph: A Scalable, High-Performance Distributed File System 引言 Ceph也是一个很有名的分布式文件系统的设计。Ceph和GFS一样,也采用了元数据和数据分开管理的方法,不过设计上存在不小的差别, Performance measurements under a variety of workloads show that Ceph has excellent I/O performance and scalable metadata management, supporting more than 250,000 metadata operations per second. 在这里只是很简单地描述了Paper[1]中Ceph一些内容。 基本设计 Ceph主要由3个组件组成,客户端提供类似于POSIX的文件系统接口,一个object storage devices (OSDs)的集群,负责存储所有的数据和元数据,一个metadata server集群,负责管理命名空间,处理安全性、一致性和连贯性等的问题。 Ceph通过3个设计来实现它的高性能,高可靠性和高可用性: 元数据和数据分离。在Ceph中和GFS一样也是元数据和数据分开保存的,元数据由元数据管理集群管理。客户端则可以通过OSDs直接执行文件IO操作。和现在的一些对象的存储系统不同,Ceph消除了块分配列表的设计,而是使用CRUSH算法来实现对象发布,可以通过对象计算来得到对象存储的位置,而不是维护一个发布信息的列表; 动态元数据发布管理。元数据的操作在文件系统的操作中占了大约一半的比例,而且会随着时间的变化,数据、负载等的也会随之变化。Ceph的元数据管理会自动适应这些变化,它的管理方式是基于一种Dynamic Subtree Partitioning的方式。 可靠的自动发布的对象存储。系统中的机器一般都是逐渐加入的,在这个过程中又的机器会变得不可用。Ceph必须管理这些机器的添加、删除的操作,还要负责对数据进行复制、迁移、错误探测和故障恢复等的工作, 客户端操作 Ceph提供的接口是很类似于POSIX文件系统的接口,在这Paper的描述中,Ceph的接口是一个用户空间的接口(现在可能有拓展)。客户端打开文件的时候,相关的请求会先发送给MSD集群,正确的情况下,MSD会返回给客户端关于这个文件的一些元数据,如inode号、文件大小已经权限的信息等。当时Ceph提供了read,... Read more!

  • 15 Jun 2017
    Amazon Aurora -- Design Cloud-Native Relational Databases

    Amazon Aurora: Design Considerations for High Throughput Cloud-Native Relational Databases 引言 Aurora是Amazon的分布式数据库,为云环境设计,这篇Paper发表在SIGMOD2017上,从整体上介绍了Amazon Aurora。Aurora有很多有意思的创新的地方。这篇文章中主要讨论了三个问题: 1. How to reason about durability at cloud scale and how to design quorum systems that are resilient to correlated failures. (Section 2). 2. How to leverage smart storage by offloading the lower quarter of a traditional... Read more!

  • 10 Jun 2017
    Anti-Caching -- A New Approach to Database Management System Architecture

    Anti-Caching: A New Approach to Database Management System Architecture 引言 这篇Paper将的是一个新的数据库架构的设计。在传统的数据中,数据一般是被保存在磁盘上面的,需要处理这些数据的时候,要先将需要的数据读取到内存中去。这里处理的地方就是buffer pool,可以说在传统的数据中buffer pool是一个很核心的组件了。在这里,传统数据库设计用来处理的情况就是数据的大小大与机器内存的。所以在需要的时候需要将一些page移出buffer pool,这样的工作方式就是Cacheing的方式了。数据库最近的一些研究就是将所有的数据都放在内存中,一方面是现在内存的大小以及很大了,价格越来越低,另外一方面就是读到很大的性能提升。但是这样做也有一个问题就是数据库中的数据的使用频率是相差很大的,有得数据会频繁使用,将这些数据放在内存中是一种很好的做法,但是有些数据是很少被使用的,将这些冷的数据放在内存里面是完全没有必要的。还有的一个问题就是将所有的数据放在内存里面带来的后果就是不能处理数据大小超过内存大小的情况。 未来解决内存数据出现的这些问题,这里提出了一个Anti-Caching的新型的数据库架构。顾名思义,Anti-Caching就是反Caching,工作的思路与传统的Caching的思路相反。对于Anti-Caching的数据来说,内存就是数据保存的地方,不过对于那些没有必要保存在内存中的数据,可以将它转移到磁盘上面去。既可以解决冷数据浪费内存的问题,也可以解决存储不了大于内存数据的问题。 We implemented a prototype of our anti-caching proposal in a high-performance, main memory OLTP DBMS and performed a series of experiments across a range of database sizes, workload skews, and read/write mixes. We compared its... Read more!

  • 05 Jun 2017
    Spanner -- Google’s Globally Distributed Database

    Spanner: Google’s Globally Distributed Database 引言 Spanner是Google的全球式的分布式数据库。Spanner可以实现在跨越数千个数据中心的数百万台机器上管理万亿级别数据行的能力,可以做到非阻塞的读,lock-free的快照事务。Spanner为了解决Google之前相同存在的一些问题而产生,有着一下几个特点: 数据副本可以在很细的粒度上进行动态的控制。应用可以控制哪些数据中心保存哪些数据,控制副本之间的距离以及副本的数量。同时,这些数据还可以在数据中心之间动态透明地移动,以便于平衡数据中心内资源的使用。 Spanner还实现了分布式数据库很难实现的一些功能,比如它能提供读写的外部一致性,以及在一个时间戳下面的全球一致性的读。还有就是原子的schema变更,即使在有其它操作的情况下也可以。 Google发表的关于Spanner的文章包含了两篇Paper和一篇杂志文章的内容,一般就是OSDI‘12上面的Spanner的最初的论文,还有就是最近在SIGMOD’17上的Spanner的第二篇论文,杂志文章的文章来自ACM Queue,讨论的是关于True Time和CAP相关的内容。总结也是按照这些文章的时间顺序来的。Spanner的第一篇论文的,主要讲的是Spanner的基本架构,一个核心技术基于原子钟和GPS的True Time,以及在此基础上实现的并发控制。 基本架构 从高层次来看Spanner,它就是一个将数据分片保存在跨越多个数据中心的Paxos状态机上面的数据库。 一个Spanner的部署被称为一个universe。一个Spanner有一些zones组成,zone是基本的管理部署单元,一个数据中心内可以有多个zone,zone可以被动态添加以及移除。在一个zone里面会有一个zone master,数百到数千个spanserber。Zone master复杂将数据交给spansever保存,spanserver则为客户端提供数据服务。另外,一个zone有一个 location proxies用来是客户端可以获取数据和spanserver之间的关系。在zone的上层,有一个universemaster,pacement driver,它们都只有一个,前者用来显示系统的一些状态信息以及调试用的,后者则是用来和spanserver周期性地交换,发现需要被移动的数据,满足副本的约束(比如某些副本变得不可用了,就需要生成新的副本),还有就是复杂均衡。 Spanserver的软件栈 Spanserver 里面的大致的架构图: 每一个spanserver复杂管理100 – 1000 个tablet的实例,Spanner中的tablet类似约Bigtable中的tablet。实现的是这样的一个映射关系: (key:string, timestamp:int64) → string 这里和Bitable不同的是,Spanner的时间戳是赋给数据的,这样Spanner就更像是一个MVCC的数据库,而不是一个Key-Value系统。一个tablet的状态是保存若干的类似Btree组织的文件和WAL的日志中的,所有的数据都保存在Colossus分布式文件系统上(这个Colossus分布式文件系统是GFS的后继产品,没有关于它的详细的信息)。每个spanserver会为每一个tablet实现了一个Paxos状态机用于复制。每一个状态机保存了对应tablet的元数据和日志。目前的实现中,每次写操作都会写2次,一次是写tablet的日志,一次是写Paxos的日志。写操作在这里必须是通过Paxos的leader初始化进行的,而对于读,这样这个副本的数据足够”新”就可以直接读取。这里的副本的集合在Spanner中被叫做Paxos Group。这里Spanner对Paxos做了很多的优化,具体可参看原论文, Our implementation of Paxos is pipelined, so as to improve Spanner’s throughput in the presence of... Read more!

  • 26 May 2017
    GraphChi -- Large-Scale Graph Computation on Just a PC

    GraphChi: Large-Scale Graph Computation on Just a PC 引言 GraphChi是一个有代表性的单机的Out-of-Core的图计算系统。它的Paper发表在OSDI’12上面。GraphChi为了处理大规模的图,它将图划分为小规模的子图。使用Parallel Sliding Windows(PSW)等的方法来使用基于磁盘的处理方式。GraphChi可以在一台普通的PC上面实现处理大规模的图, with only fraction of the resources, GraphChi can solve the same problems in very reasonable time. Our work makes large-scale graph computation available to anyone with a modern PC. 基于磁盘的图计算 GraphChi也是采用了常见的以顶点为中心的模型。对于一个顶点为中心的模型,一个实例的代码如下所示: Update(vertex) begin x[] ← read values of... Read more!

  • 20 May 2017
    一个OJ的设计

    一个OJ的设计 引言 与 动机 这个是这条咸鱼做的东西。这个部分是OJ系统的核心部分的设计,也就是编译代码,然后运行,对比输出数据,最后返回结果。不包含一般OJ的web的部分。在这里的设计中,web部分和核心的判题的部分是分离的,运行在不同的机器之上。OJ作为一个要运行用户提高的代码的系统,本身就是存在很高的风险的,所以安全的问题是这个OJ要解决的最重要的问题。在这个系统的设计过程中,找出来多种攻击这类OJ系统的方式,其中一些在现在的一些在使用的系统中都存在,严重的可以getshell,控制机器,轻一点的存在泄漏数据的可能(熟读网络安全法,这里的测试均在自己搭建的系统的机器上测试,也不会公开具体的攻击方式)。 现在的一些OJ的另外的一个问题就是拓展性的问题。一般而言,OJ上面一个题的运行时间是1秒到几秒不等,而且会有多组的测试数据,这个时间是不可能优化的,而且是由用户的代码和题本身的特点决定,需要这么多的时间就是必须要这么多的时间。为了支持更大的QPS,只能使用增加机器的方式。现在的一些OJ系统的设计将判题的部分和web的部分耦合在一起,部署在一台机器之上,web部分做高QPS很简单,一般一台机器几百是很简单的事情了,但是在一台机器上面同时判题几百道,这个在目前是不太可能的。所以这种架构很难拓展。 基本设计思路 每一个判题的程序运行在一个单独的机器之上; 每一个机器之上有多个进行实际判题工作的进程(worker进程),另外还有一个对这些woker进程管理的Master进程; 每个Woker进程从消息队列中获取数据; Worker进程只将必要的数据保持到数据库,暂时性的数据都发给消息队列or放进有过期时间的缓存中; 编译的安全性和运行的安全性一样重要; 使用Linux的namespace和seccomp机制等保证安全,rlimit之类的机制限制资源使用; 整体的设计 用户提交的任务交给web端。由web负责进行一些必要的检查(比如检查代码的大小or其它一些数据的合法性),赋予这个任务一个唯一的id(这里叫做rid),这个id对于判题核心来说没有直接的用途,只用做标示作用。然后用合适的序列化方式序列化,将这些数据方式到消息队列里面。Worker进程会尝试从消息队列里面获取任务,这里使用的是“拉”的方式,每个Worker进程根据需要拉取任务,不需要处理负载均衡的问题。整个判题核心部分由C++写成。 单机的设计 在一台机器上,会有一个 Master 进程,有与 CPU 核数相等的 Worker 进程。判题服务的启动时,首先启动的是Master 进程,在做一些必要的设置之后,Master进程会启动多个 Worker 进程。Worker 进程完成具体的工作,而 Master 只负责 Worker 的启动与重启。当 Master 监测到一个 Worker 退出时,会重启一个新的 Worker 代替退出的 Worker。但是,Master 并不会无限重启 Worker,当重启的速率太快时,必然是遇到了严重的 Bug 或者是网络异常,系统已经不能正常工作,此时再重启已经没有意义了,Master 会将所有 Worker 退出之后自己结束运行。 任务获取 任务获取主要解决两个问题:第一,解决判题服务器判题的速率和用户提交的任务 的速率不一致的问题;第二,解决如何将任务公平发送给各个 Worker 的问题。... Read more!

  • 17 May 2017
    Windows Azure Storage

    Windows Azure Storage: A Highly Available Cloud Storage Service with Strong Consistency 引言 Windows Azure Storage是微软的分布式存储系统。与其它公司的一些存储系统不同,WAS一个特点就是提供了多样化的抽象,支持Blob、Table和Queue的抽象。 In WAS, data is stored durably using both local and geographic replication to facilitate disaster recovery. Currently, WAS storage comes in the form of Blobs (files), Tables (structured storage), and Queues (message delivery). In... Read more!

  • 14 May 2017
    PNUTS and Cassandra

    PNUTS and Cassandra 引言 PNUTS是雅虎开发的一个类似的Amazon Dynamo的系统,不同的Dynamo的是,PNUTS提供了更加多样化的一致性的支持,这个系统是非开源的。而Cassandra是facebook主导开发的一个类似的系统。 数据模型 Cassandra和PNUTS之间的数据模型是很相似的,类似于Bigtable的表格的特点。在这样的一种模型上面,抽象为类似传统数据库一样的table,每个table可以由若干的指定类似的列。由于Cassandra和PNUTS本质上还是key-value的系统,它们进行删除更新等的操作的时候还是只能根据primary key来处理。下面是Cassandra的主要的接口: • insert(table,key,rowMutation) • get(table,key,columnName) • delete(table,key,columnName) columnName can refer to a specific column within a column family, a column family, a super column family, or a column within a super column. 一致性模型 PNUTS和Cassandra在一致性的一个相同点就是只支持在单行上面的事务,这点和Bigtable也相同的。 雅虎在它的应用中认为仅仅就是简单的最终一致的系统不能满足一些的要求, PNUTS provides a consistency model that is... Read more!

  • 09 May 2017
    Dynamo -- Amazon’s Highly Available Key-value Store

    Dynamo: Amazon’s Highly Available Key-value Store 引言 Dynamo是分布式Key-Value系统的经典设计。Dynamo为了追求高可用和可拓展,适当地放弃了一致性,对之后的很多系统的设计产生了很大的影响。对于Dynamo有以下几个系统假设和要求: Query Model,简单的接口,一般就是get,put之类的key-value接口; ACID Properties,ACID (Atomicity, Consistency, Isolation, Durability)中只支持弱一致性,也不提供隔离性的保证,只允许单key的更新; Efficiency,要求低延时,高吞吐; Other Assumptions: Dynamo is used only by Amazon’s internal services. Its operation environment is assumed to be non-hostile and there are no security related requirements such as authentication and authorization. Moreover, since each... Read more!

  • 02 May 2017
    Large-scale Incremental Processing Using Distributed Transactions and Notifications

    Large-scale Incremental Processing Using Distributed Transactions and Notifications 引言 Percolator时Google开发用来解决Bigtable不支持多行事务的一个系统,号称将Google索引的更新速度提高了100倍,将文档的年龄减少了50%。这篇总结只会包含Percolator如何在Bigtable上面实现跨行跨表的事务的。 By replacing a batch-based indexing system with an indexing system based on incremental processing using Percolator, we process the same number of documents per day, while reducing the average age of documents in Google search results by 50%. Percolator的设计非常巧妙,硬是在一个只支持单行事务的Bigtable上面实现了跨行跨表事务的支持。 基本架构... Read more!

  • 28 Apr 2017
    Chubby and Zookeeper

    Chubby and Zookeeper 引言 这篇两篇论文也是一个重量级的论文,对现在的很多的系统的设计产生了很大的影响。 Chubby是Google基于Paxos的分布式锁服务,Zookeeper是雅虎在基于Chubby论文开发的一个开源版本,两者的论文都是讲的是系统的一些东西,比如接口抽象、事件、API和锁之类的东西,咸鱼觉得这个的重点在与它们使用的distributed consensus protocol(分布式共识协议)以及这个protocol的实现(chubby使用的就是Multi-Paxos,而Zookeeper使用了一个变体Zab),在此基础上的抽象反而是次要的。本来这篇总结是关于Chubby论文的,回来发现论文里面没啥有意思的,就把Zookeeper加进来对比一下。这里就基本总结一下它们提供了怎么样的抽象。并对比一下,关于分布式共识协议在之后的总结中。对于Chubby。Chubby的两个关键的设计决定是: 将Chubby设计为一个锁服务,而不是一个库或者是一个共识服务; 使用一种文件的方式; Chubby倾向于只提供粗粒度的锁服务。回来的Zookeeper也基本沿用了Chubby的思路。一些决定Chubby设计的因素,这些因素由Google期望如何使用Chuuby以及Google的环境决定的: • A service advertising its primary via a Chubby file may have thousands of clients. Therefore, we must allow thousands of clients to observe this file, prefer- ably without needing many servers. • Clients and replicas of a replicated... Read more!

  • 22 Apr 2017
    Bigtable -- A Distributed Storage System for Structured Data

    Bigtable: A Distributed Storage System for Structured Data 引言 这篇是一篇对后面的系统产生重大影响的论文,Bigtable是Google的分布式结构化的存储系统。 数据模型 不提供关系模型,在Bigtable中,数据的组织像是一张巨大的表格(Bigtable名字的由来),表格一般都是由行和列确定的,这个表格在Bigtable中叫做table,在Bigtable中的数据模型是: (row:string, column:string, time:int64) → string 论文中的描述是一张table在Bigtable中是一个洗漱的、分布式的、持久化的、多维的排序好的图(map)。row + column可以理解为就是确定了这张巨大表格中的一个格子,在Bigtable中也把它叫做Cell。除了row和column之外,Bigtable还加入了额外的一个时间维度,它是一个64bit的时间戳。这样,Bigtable更加像一个三维的表格。这个格子对应的数据是一个字符串或者是由时间戳区分的多个版本的字符串。 Rows,Bigtable使用row keys来排序,row key实际上就是一个字符串。这里Bigtable的一个特点是能够保证一个row 可以上面的读写操作都是serializable,而且无论多少columns参与到这次操作之中。这也就是为什么说Bigtable只支持单行事务的原因。Bigtable不支持跨行的事务,这也是Google后面一些系统出现的原因,主要就是为了解决这个问题,后面会有这个方面的总结。 Columns,Bigtable会将columns分组为列族,访问控制在列族上组织。一个列族下面的列同时有相同的类型。列族是必须被显示的创建的,在创建之后就可以在其中添加列。列的key是family:qualifier 这样的格式, Column family names must be printable, but qualifiers may be arbitrary strings. An example column family for Webtable is language, which stores the language... Read more!

  • 15 Apr 2017
    The Google File System

    The Google File System 引言 GFS(or其后继者)是Google诸多系统依赖的基础,包括Mapreduce、Bigtable已经Spanner等。不同于单机上面的文件系统,GFS专门为分布式环境下存储只追加不修改的大文件设计的。另外,了解GFS的设计这些设计目标or设计假设是了解GFS的前提: 系统中的组件出现故障时常态,所以系统必须自己能够处理这些情况; GFS主要就是大文件设计的,一般都在100M以上,GB级别的文件很常见,虽然系统要支持小文件,但是不做优化; 系统的操作主要有大的连续读和小的随机读构成; 负载中有大量的顺序的追加的写操作。文件一旦写入,就很少修改。小的在任意位置的写入也被支持,但是效率可能很低; 系统必须提供良好的语义支持多个客户端的部分追加操作。这里实现同步开销小的原子性追加支持很重要; 包吞吐的优先级放在延时之前,也就是说一实现高的吞吐为目标; 基本架构 GFS的架构影响了很面很多类似系统的设计,主题部分有一个单一的Master和多个Chunkserver组成,此外还包括了一个客户端: 在GFS中,文件被分为固定大小的chunks,每一个chunk有会有一个全局唯一的不可变的64bit的id标示,在这个chunk被创建时赋予。Chunkserver就负责保存这些chunk。未来可靠性,这里一般把chunk复制3份保存。Master则是用来保存元数据的,它包含了namespace,访问控制信息,文件到chunk的映射关系以及现在这些chunk的位置。此外,Master管理chunk租约,孤儿chunk垃圾回收以及chunk在chunkserver之间的迁移。Master和Chunkserver之间通过定时的HeartBeat信息交互。客户端通过GFS的库对GFS进行操作,读写文件时,要先从Master回去文件的元数据信息,然后去Chunkserver进行实际的读写操作。GFS不提供POSIX语义的文件操作接口,也没有什么Cache: Neither the client nor the chunkserver caches file data. Client caches offer little benefit because most applications stream through huge files or have working sets too large to be cached. Not having them simplifies the... Read more!

  • 10 Apr 2017
    What’s Really New with NewSQL?

    What’s Really New with NewSQL? 引言 这篇文章是讨论新出现的被称之为NewSQL的数据库系统。数据库继SQL,NoSQL之后,一个新的发展方向。这篇文中给出了关于NewSQL的分类的讨论,还分析了现在NewSQL系统存在的技术挑战。Paper中将这些数据分为了三类,1. 全新的创建的型的数据库架构,2. 在支持的一些系统使用中间件实现的系统,3. 云计算厂商提供database-as-a-service产品,它们也是基于新的架构。 New Architectures 这类数据是指全新开发的使用多种新技术的数据库产品。代表作就是Google的Spanner。这些系统的几个特点:基于发分布式的架构,都是为分布式环境设计的,资源是shared-nothing的,有专门的组件用于支持分布式的并发控制,容错和复制,还有分布式查询技术;此类数据库的优点就是能够系统能够为多结点执行的进行专门的优化,比如为分布式环境优化的查询优化器。 这些DBMS的存储一般都是自己管理的(Google的Spanner是个例外,它的数据是保存在Google的分布式文件系统CFS上面的),这就因为这些系统不是使用现在的一些组件如HDFS,这样它们要自己负责管理这些资源。这样带来的还是就是它们可以实现将查询发送到数据那里,而不是将数据带到查询这里来。这样就显著的减少了数据传输的数量。 自己管理存储带来的另外一个好处就是可以实现更加精心设计的复制方法,通常这个可以是的系统获得更加好的性能。一些“SQL on Hadoop” 的系统直接利用的是例如Hbase之类的现有的一些东西,在这些系统的基础之上实现事务,这里Paper不将它们归类于NewSQL。 Managing their own storage also enables a DBMS to employ more sophisticated replication schemes than what is possible with the block-based replication scheme used in HDFS. In general, it allows these DBMSs... Read more!

  • 02 Apr 2017
    Pregel -- A System for Large-Scale Graph Processing

    Pregel: A System for Large-Scale Graph Processing 引言 Google的这篇关于图计算的Paper也是一篇重量级的论文。Pregel几个基本的特点:分布式、容错、可拓展性强、以定点为核心和BSP并发模型等, This vertex-centric approach is flexible enough to express a broad set of algorithms. The model has been designed for efficient, scalable and fault-tolerant implementation on clusters of thousands of commodity computers, and its implied synchronicity makes reasoning about programs easier. Distribution-related... Read more!