千家信息网

Zeppelin:一个分布式KV存储平台之元信息节点

发表于:2024-11-23 作者:千家信息网编辑
千家信息网最后更新 2024年11月23日,从Zeppelin:一个分布式KV存储平台之概述的介绍中我们知道元信息节点Meta以集群的形式向整个Zeppelin提供元信息的维护和提供服务。可以说Meta集群是Zeppelin的大脑,是所有元信息
千家信息网最后更新 2024年11月23日Zeppelin:一个分布式KV存储平台之元信息节点

从Zeppelin:一个分布式KV存储平台之概述的介绍中我们知道元信息节点Meta以集群的形式向整个Zeppelin提供元信息的维护和提供服务。可以说Meta集群是Zeppelin的大脑,是所有元信息变化的发起者。每个Meta节点包含一个Floyd实例,从而也是Floyd的一个节点,Meta集群依赖Floyd提供一致性的内容读写。本文将从角色、线程模型、数据结构、选主与分布式锁、集群扩容缩容及成员变化几个方面详细介绍,最后总结在Meta节点的设计开发过程中带来的启发。

角色

从上图可以看出Meta集群的中心地位:

  • 向Client及Node Server提供当前的元信息,包括分片副本信息,Meta集群成员信息等;

  • 保持与Node Server的心跳检测,发现异常时进行切主;

  • 接受并执行运维命令,完成相应的元信息变化,包括扩容、缩容、创建Table、删除Table等;

线程模型

相对于存储节点,元信息节点的线程模型比较简单:

  • 处理请求的Dispatch线程Worker线程

  • 修改Floyd的Update线程,Update线程是唯一的Floyd修改者。所有的元信息修改需求都会通过任务队列转交给Update线程。同时为了减轻Floyd的写入压力,这里采用了延时批量提交的方式;

  • Condition线程用来等待Offset条件,一些元信息修改操作如SetMaster,扩容及缩容,需要等到分片副本的主从Binlog Offset追齐时才能执行,Meta从与Node之间的心跳中得到Offset信息,Condition线程不断的检查主从的Offset差距,仅当追齐时通知Update线程完成对应修改;

  • Cron线程执行定时任务,包括检查和完成Meta主从切换、检查Node存活、Follower Meta加载当前元信息、执行数据迁移任务等。

数据结构

为了完成上述任务,Meta节点需要维护一套完整的数据,包括Node节点心跳信息、Node节点Offset信息、分片信息、Meta成员信息、扩容迁移信息等。由于一致性算法本身限制,我们需要尽量降低对Floyd的访问压力,因此并不是所有这些数据都需要直接维护在Floyd中。Zeppelin根据数据的重要程度、访问频率及是否可恢复进行划分,仅仅将低频访问且不易恢复的数据记录在Floyd中。

上图所示是Meta节点所维护数据的数据结构及存储方式,可以看出,除了一致性库Floyd中记录的数据外,Meta还会在内存中维护对应的数据结构,内存数据结构依赖Floyd中的数据,重新组织并提供更方便访问的接口。从所完成的任务来看,主要包括三个部分:

1,维护和提供集群元信息(Zeppelin Meta Info)

对应内存数据结构InfoStore,InfoStore依赖Floyd中的数据,包括:

  • 当前元信息的版本号Epoch,每次元信息的变化都会对Epoch加一;

  • 数据分片副本的分布及主从信息Tables

  • 存储节点地址及存活信息Nodes

  • Meta集群自己的成员信息Members

InfoStore重新组织这些数据,对外提供方便的查询和修改接口;除此之外InfoStore还会维护一些频繁修改但可以恢复的数据:

  • 存储节点上次心跳时间:宕机后丢失,可以通过Floyd中的Nodes信息及恢复时的当前时间恢复,注意这里使用恢复时的当前时间相当于延长的存储节点的存活;

  • 存储节点的分片Binlog偏移信息:Meta需要这些信息来决定副本的主从切换,宕机恢复后可以从Node的心跳中获得,这也就要求Node在重新建立心跳连接后的第一个包需要携带全量的Binlog偏移信息。

2,扩容缩容相关的迁移信息(Epend Shrink)

对应内存数据结构MigrateRegister,负责迁移过程的注册和提供,这部分内容将在稍后的集群扩容、缩容章节中详细介绍。

3,实现Meta集群高可用(Meta High Available)

Meta以集群的方式提供服务,Leader节点完成写操作,Follower分担读压力,节点之间依赖Floyd保证一致,从而实现Meta集群的高可用。内存数据结构Election负责节点异常时的选主,依赖Floyd提供的Lock接口及其中的Election相关数据。这部分内容将在稍后的选主与分布式锁章节中详细介绍。

选主与分布式锁

Meta集群中的节点分为Leader和Follower两种角色:

  • 所有的写操作及心跳都会重定向到Leader,Leader将需要修改Floyd的请求封装为Task,加入等待队列,批量延时的写入Floyd,并更新本地的内存数据结构。

  • Follower定时检查Floyd中的元信息,如果变化则加载并修改本地内存数据结构,并对外提供元信息的查询操作。

因此我们需要一种机制来选主,并且每个Leader需要一个定长的租约时间,在租约时间内集群不会选择其他Meta节点作为新的Leader,相当于牺牲一定的可用性来优化读性能。选主问题是典型的分布式锁的应用,获得分布式锁的节点即为主。我们认为分布式锁是由三层相互独立的问题组成的,如下图左边所示,自下而上分别是一致性(Consistency),锁的实现(Lock)及锁的使用(Usage of Lock)。其中Consistency是为了高可用,Lock提供了互斥的加锁的机制,而Usage of Lock部分通常有两种实现:

  • 严谨实现:加锁时返回Sequence,这个Sequence自增,获得锁的节点之后的所有操作的受体都必须检查这个Sequence以保证操作在锁的保护中;

  • 简单实现:节点在尝试加锁时需要提供一个时间,锁服务保证这个时间内不将锁给其他节点。使用者需要自己保证所有的操作能在这个时间内完成。这个方法虽然不严谨但是非常简单易用,Zeppelin的Meta集群采用的正是这种方式。

如上图右边部分显示了这三部分在Meta中的对应关系:

  • Consistency我们依赖Floyd实现的Raft,同时Raft对外提供了细粒度的锁接口以及存储数据的Set、Get接口;

  • 依赖Raft提供的接口,Meta实现了自己的粗粒度锁Coarse-Lock,简单的说,通过Set Get接口存储或查询当前Leader的地址信息及上次刷新时间;并通过Floyd的细粒度锁保护互斥的访问;Leader定时刷新自己的时间,Follower发现Leader超时后取而代之。Coarse-Lock层实现了Meta集群锁需要的Election。

  • 利用Coarse-Lock,Meta实现了自己的高可用。Cron线程中不断触发当前节点检查并在需要的时候尝试选主。

这里需要说明的是,相对于Fine-Lock而言,Coarse-Lock加锁的时间更长,响应的锁的迁移也会带来更大的成本。比如主从链接的重新建立,任务队列的丢弃及清空,Meta工作线程的切换等。因此我们希望下层Lock抖动尽量不要影响上层的主从关系,针对这点Meta中设计了如下两种机制:

  • Meta主从关系与Floyd主从关系解耦,即使Floyd主从变化,依然有可能对上层Meta集群透明;

  • 引入Jeopardy阶段,正常运行过程中,Meta会记录当前的Leader信息,当Floyd由于网络或节点异常无法服务时,Meta层会进入Jeopardy阶段中,Jeopardy使得Meta节点在一定的时间内依然保持主从关系不变。这个时间就是上面提到的为了读优化给Leader的Lease。之所以能够这么做,正是由于Zeppline的设计中尽量减少对Meta集群作为中心节点的依赖,从而可以接受Meta集群短时间的不可用。

集群扩容、缩容

Zeppelin作为存储集群,考虑到资源利用及业务变化,不可避免的需要进行集群的扩容、缩容或平衡操作。下图是简单的扩容操作示例,三个存储节点Node1,Node2,Node3,负责分片P1,P2,P3的九个主从副本。这时Node4加入,需要将P1的Master副本和P3的Slave副本迁移过去。

针对这类问题,主要有如下诉求:

  • 持续时间可能很长,过程中无人工介入;

  • 保证数据正确;

  • 减少线上服务无感知;

  • 不显著增大Meta负担,包括资源使用和代码复杂度;

  • Meta节点异常或网络异常后可从断点恢复;

  • 容忍Node状态变化;

  • 方便暂停、取消,可以获取状态及当前进度;

  • 负载均衡;

子问题

为了很好的解决这个问题,我们先进行子问题的推导及切割:

  • 扩容、缩容及平衡,其实都是将多个分片从源节点移动到目的节点;

  • 迁移一个分片,可以拆分为增加新的Slave分片,等待数据同步,切换并删除原分片三个步骤。

方案

上图所示是Zeppelin的扩容、缩容及平衡机制:

  • 客户端命令行工具中将扩容(Expand),缩容(Shrink)及平衡(Balance)操作,通过Zeppelin的数据分布算法DPRD转化为初始状态(Init State)和一组DIFF集合,每一个DIFF项指定一个分片副本及其要迁移的源节点、目的节点;

  • Init State及DIFF集合传递给Meta Leader节点的Migrate Registor模块,检查Init State并将DIFF集合写入Floyd;

  • Cron线程定时获取一定量的DIFF项,顺序执行每个DIFF项;

  • 生成添加新的从副本的UpdateTask1交给Update线程尽快执行,同时设置状态将该分片缓写或阻写;

  • 生成ConditionTask交给Condition线程,ConditionTask中包括一个Offset条件和一个切换副本的UpdateTask2,这个Offset条件通常指源节点和目的节点偏移量一致;

  • Condition线程等待满足Offset条件后将对应的UpdateTask2交给Update线程尽快执行;

  • 完成必要的状态改变后,将对应的DIFF项从Register中删除,并继续取出新的DIFF执行,直到全部完成。通过这种方式,任何时候Meta节点宕机,新Leader都可以从Floyd中获得DIFF并继续操作。

成员变化

通常Meta集群是一个3或5个节点的一致性集群,有时我们需要改变Meta集群的成员,增加、删除或替换。Meta集群的成员变化依赖下层的Floyd,Floyd提供每次一个节点变化的Membership Change方式,详细算法见CONSENSUS: BRIDGING THEORY AND PRACTICE。

Floyd的成员变化后,Meta集群对应修改自己的内存数据结构Membership,同时元信息Epoch加一,从而整个集群的Node及Client都能从新拉取的元信息中得知新的Membership。

Lessons We Learn

1,责任分散

将中心节点的责任分散到大量的Node和Client上,从而减轻对中心节点的依赖:

  • 心跳:由Node发起并检查链接状态;

  • 元信息提供:Node及Client发现主动拉去,而不是由Meta分发。同时Node还会在访问错误节点时,给Client返回kMove消息来帮助Client不通过Meta即可得到部分需要的元信息数据。

2,考虑扩展性时,减少通信次数有时候比优化单次请求处理速度更有效
3,限制资源的线性增长

比如,我们通过批量延迟提交Flody的方法,将一段时间以内的修改操作归并起来,变成一次对Floyd的访问。将请求数级别修改频次变为每秒常数次。

4,故障恢复时的数据恢复

同样为了减少Floyd的压力,我们不会将所有数据存储到Floyd中,那么有些只在内存中维护的数据就需要在服务恢复时恢复出来,恢复时的数据来源可以包括:

  • 持久化数据(尽量少);

  • 外部请求中携带,比如Node的Offset信息从心跳中恢复;

  • 估计值,比如Meta中的Node存活时间是直接用恢复的当前时间的;

5,无重试可重入

Meta中的所有操作都是无重试可重入的,指所有步骤的失败不直接进行重试,而是做一些状态恢复后丢弃,依赖外部的二次操作来完成,也就要求所有的的操作都是可重入的,这样做带来的好处是:

  • 处理清晰简单,所有发生错误的地方可以直接丢弃任务;

  • 上层更好估计操作完成需要的时间,从而向分布式锁或Node作出时间上的保证。

参考

https://github.com/Qihoo360/zeppelin

https://github.com/PikaLabs/floyd

https://ramcloud.stanford.edu/~ongaro/thesis.pdf

http://baotiao.github.io/2017/09/12/distributed-lock/

http://catkang.github.io/2018/01/07/zeppelin-overview.html

http://catkang.github.io/2018/01/07/zeppelin-overview.html

https://whoiami.github.io/DPRD

原文链接:https://mp.weixin.qq.com/s/eCDWqgRG-FmWFkK6cgzm4w

节点 信息 数据 集群 时间 线程 存储 主从 变化 数据结构 结构 副本 内存 分布式 成员 检查 一致 任务 接口 状态 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 服务器配置更新是什么意思 在数据库中用什么来检测是否为空 中国金融资源数据库 浙江嵌入式软件开发定制费用 河南安卓软件开发哪家可靠 河南软件开发售后服务怎样 嵌入式软件开发加班那 工控系统网络安全等级认证试验 奉贤区机械网络技术厂家直销 我的世界服务器卡伤害 湖北服务器机柜方案 网络安全 基础知识试题 保障数据库的安全 好用安全的ftp服务器 我的世界国际搬家服务器 数据库2005怎么配库 江苏软件开发价格表 七年无人管理的服务器 网络棋牌软件开发风险 广西刺猬网络技术有限公司 中文数据库的特点主要有 走进网络安全知识 浏览器 服务器模式 怎么计算要多少台服务器 红警怎么联机服务器 网络技术知识普及讲座 云丁网络技术有限公司财务 我的世界怎么玩东方大陆服务器 网络技术安全年度总结 检索文献可用的数据库
0