樊伟:可计算智能存储揭秘
3月16日在北京举行的腾讯云自研数据库CynosDB交流会圆满落下帷幕。现将技术团队分享的内容整理如下。
我们先看一下整体的软件架构,上面是TXSQL;左边是Space manager,负责空间分配映射;底下是一个DBStore的模块,负责处理redo和page相关逻辑;再下面是Atlas node,这个大家可能不太熟悉,它是腾讯云后端的存储平台,现在支撑的服务有块存储,数据库,文件,后面再做介绍。
接下来是介绍客户端的一些读写流程,因为page的读写,它跟Redo的处理逻辑比较相似,这里只给出一个Redo的处理流程来做说明。假设TXSQL发了一个log流(100~104),到达客户端之后,进行地址映射,将空间映射到下面的T1~T4(T1-T4是指分布式存储的复制单元)。这样就能把一个log流引入到下面多个流,分发到下面的分布式节点去处理。日志流在存储节点返回成功后,进行到右边的第三步。假设那100和103先返回了,这时候就会推进VDL到100,告诉DB说存储系统已经持久化到这个点了。如果后续101返回了,则可以直接推进到103的位置了。普通的page读写操作流程,处理方式和redo类似。
接下来看一下DB recovery,它的流程会变成什么样?首先TXStore-client会获取表空间映射,获得分布到存储空间哪些存储单元(T1~T4)相关信息。然后向这些存储单元获取lsn。这里会有一些优化,会根据一些持久化的点进行获取lsn,以此来减少返回的lsn量。获取到lsn后进行排序,如图所示lsn会推进到103,recovery point就到这里。当然这个例子中忽略了一些因素,为了简化流程说明,没有考虑mtr相关因素。实际处理中有可能103不是mtr,recovery point可能还需要向左边返回一些。
接下来介绍一下DBStore模块,它负责所有Redo的相关逻辑处理以及page的读写操作。首先是客户端发送redo到DBStore,DBStore对这个log进行一个简单的排序,它要判断排序中的log和persist queue中的log是否连续。如果连续,则紧接着进行持久化,并且把这些log向副本进行复制。等到日志持久化和副本返回成功后,整个redo流程处理就完成了。Redo log在单个节点内一次写入就可以完成。
这里介绍下刚才提到Atlas分布式存储平台。它对上支持的用户业务包括一些腾讯的业务和外部业务(比如拼多多、摩拜之类的业务)。中间这一层是它支撑的云服务,包括块服务、文件服务、DB服务等。接下来是Atlas平台提供的功能罗列,借助平台的能力可以快速构建DB上的能力,比如说一些扩容、流控、快照等。
下面介绍一下Atlas的软件架构,它是一个典型两层分布式存储架构。先看客户端,它支持丰富的接口和一些高级功能(比如快照、卷迁移)。左边是控制节点,负责分布式集群的状态控制,包括节点故障恢复以及负债均衡等功能。右下角是三副本跨交换机分布的存储节点,它提供了高性能的存储引擎,数据同步恢复功能,强一致性复制协议,故障容忍F+1等。
接下来看下数据路由方式。在支持块存储的时候路由方式比较简单,经过哈希函数得到一个虚拟节点,之后通过右边的路由关系找到一个存储节点,然后进行读写。在DB里面发生一些变化,如果也按照块存储的方式去hash路由的话,这个拆分太散了,会导致redo很分散,达不到聚合的作用。所以我们分配的时候会使用MDS分配的方式,直接将DB的某一段空间直接映射到哈希上的某一段,映射到分布式存储的一个复制单元。
接下来我们介绍一下Atlas系统的IO协议栈。首先从IO路径上看是一个两层架构,不需要中心节点介入,一方面缩短路径提高了性能,因为少了接入节点也降低了成本。最上面的接入层,支持丰富的协议,比如iscsi、file、db等;接下来是网络模块,支持普通网络和RoCE网络;再往下是复制模块,支持并行高效复制;接下来是存储引擎层,基于Append only方式的元数据管理和基于裸盘的空间管理,有效降低了写放大,提高性能;接下来是cache模块,支持一些低成本方案。比如可以通过配置一些较慢的介质做主存、较快的介质来做cache来达到成本和性能的均衡。DB场景下为了追求极致性能,目前没有选择混存配置方式;layout层这里不做介绍了;接下来是磁盘管理模块,负责IO提交,会进行合并、批提交等优化处理。
接下来介绍这个系统的高可用能力,Atlas无法回避分布式节点里面故障节点,在分布式系统中故障是常有的。故障处理分为故障临时故障和永久故障。上图是临时故障的过程,假设左边A节点故障了,当它再次恢复的时候它会向主节点B发起增量数据恢复;下图是全量同步的过程,当一个节点永久故障时候,需要其它所有节点参与重建。临时故障只需要同步少量的增量数据,全量同步可以让系统很多的节点共同参与,因此同步都是快速的,系统能快速回归到稳态。
这里是一个高可用的补充,通常分布式系统中会依赖一些心跳去探测节点的好坏。但是假设遇到网络丢包或者慢盘等亚健康状态,就不那么生效了。我们是对IO进行随路探测,更及时的发现这些故障,上报到我们的Master节点进行仲裁把它隔离掉,减少对业务的影响。
接下来介绍一下存储平台的特性。比如快照,基于这些快照,我们可以快速实现DB的一些物理备份;卷迁移,因为云上有很多的仓储,可能会涉及到迁移调度,或者后续有一些性能体验更好的仓库,通过在线迁移可以提升用户体验;预读的能力,这是一个分布式预读,可能一些应用或者数据库本身也有预读的cache,但它的特点因为是单机的,空间是很有限的。在分布式系统中,分布式节点有很多,所以把读cache做到下面之后跟上面的DB服务、块存储服务形成配合。取数据还需要跨网络,但是可以省去访存储介质的时间而且支持多点访问;多介质支持,支持一些存储介质的组合,比如SSD、HDD、SSD和HDD混存;还有支持流控、共享磁盘等功能,后续还有更多的功能在迭代开发中。
Q:您好,我提问两个问题,你刚才说到我们在读写的时候,底层有一个大的cache
,我的问题是比如某个节点堵了cache,你缓存的机制是什么?能介绍一下吗?比如通常说有大的计算或者需要大量的数据出报表,或者出各种计算的时候,可能需要大量的数据,我们这个缓存的机制是什么?
A:关于预读,预读的逻辑更多的是靠前端的模块配合的。预读请求发送之后也不需要应答,告知存储层把数据准备好就可以了。
Q:通常我们是这样,比如他去分析数据,哪些日志是常用的东西,他可能会做一个缓存计划,这样来了备份直接去用IO读,我们一般会有这样的一个分析的逻辑。所以说您说的还不太理解。
A:也就是说比如DB的逻辑,可能后面会用到哪几个块,会提前读到buffer pool里面来,但因为buffer pool还是有限的;有了存储预读功能后,不需要将数据读到buffer pool,只需要告诉存储,等真正用的时候不用到介质上去读。
Q:关键是怎么知道想读哪些?
A:这个是要靠应用自己去逻辑分析,比如块里面一些简单的顺序模型,会很容易的推测出来后续可能要用这些块。MySQL中本身也有一些预读逻辑,可以将MySQL的预读逻辑和后端存储平台打通。
Q:这一页SSD和HDD混合的存储,你的数据如何分布的?存储的策略,这一块你们是怎么设计的?还是说在规划中?
A:不是规划中,这个是Atlas平台的能力,这个算法有很多的配置,典型的是两级LRU的配置,就是根据数据访问的频度,然后决定数据是在SSD上还是淘汰到HDD上。
Q:这个调度的算法是你在存储层做的?
A:存储层做的。
Q:这主要是根据存储层读页面的程度来访问它的吗?
A:对,统计它的冷热程度。
![](https://jkboy.com/wp-content/uploads/2021/10/Pasted-11.png)