查看原文
其他

智囊团分享:超融合SDS系统的架构设计分享

2015-10-15 云头条

“智囊团”分享人:刘卓,华中科技大学本科毕业,美国奥本大学博士。主要研究方向:存储和大数据,曾在美国Yahoo Research从事多年的底层存储和大数据核心架构研发。在FAST和SC等顶级Conference上发表多篇论文,对新型存储介质和读写cache有深入的理论研究,对如何在大规模存储系统实现energy efficiency提出了自己的独特方式,并把这些技术深度结合用于Zetta超融合云计算产品体系。现担任Zetta(中科云)首席架构师。



因为在做Zetta之前曾经设计实现过一些大型的分布式系统以及内核态开发,我们做Zetta是希望它在scalability和reliability方面做到极致,同时很多后期可能才会重视的一些东西被我们在设计初期就考虑进去,比如maintainability,能够在不影响系统在线业务的情况下进行OS upgrade和storage version的online upgrade;比如如何能够尽量避免复杂protocol下的单机死锁和分布式死锁的问题。


一个SDS存储系统中有很多很多operation,Zetta的一个设计思路是要做到role在线可漂移,比如集群的某个role控制节点,做到在线漂移对于运维来说非常有用,能够把一些节点从集群中提出来进行运维,但如果这个节点正在处理很多很多的operation, 这些operation之间又有dependency,那么如何能够防止分布式死锁,是我们在设计的时候遇到的一个比较难做的问题。我们通过分析发现分布式系统中节点之间的operation之间会形成一个dependency DAG(directed acyclic graph), 通过graph分层的方式去quiesce operation解决了我们在这方面设计的一个重大问题。同时我们在设计SDS存储系统的一些protocol的时候,吸收了之前的工作经验,一些锁协议的prototype以及代码我们通过model checking的技术和工具检查其中是否有可能的死锁,并且做了一些优化技术避免了其中可能出现的graph state explosion问题,通过这种方式保证了我们协议的prototype是100% deadlock free的。这里非常感谢并且推荐Dr Jun Feng Yang@Columbia University的paper。另外在storage version的upgrade方面,我们因此深度hack了内核,加入了一种匿名页共享的支持方式,因此也实现了相关的热升级。


第二个设计方面的理念是要考虑到设计的协议是否starvation free和避免可能出现的livelock。我们在初始设计的时候希望能够让多个operation之间互相谦让对方,后来实际实现后出现了livelock,最后不得不修改协议的逻辑。同时SDS系统中operations之间本身并发性要求很高,我们在设计的时候要做到最细粒度的操作并发,不是一把大锁就能解决所有问题的,因此很多元数据operations之间我们是按照partial ordering(偏序)关系进行设计,但后期系统运行过程中进行并发度特别大压力测试,发现一些operation出现了starvation的问题,我们通过一些技术进行了队列的流控,从而防止了这种现象出现的可能。


第三个我们贯穿在整个SDS的设计中最重要的一个环节就是事务系统的设计和实现,在设计最初始的时候,我们就考虑了是否引入分布式事务,类似于2PC,但这种协议对于scalability来说是一个很大的问题(thanks to the guidance of the designer of ebay system:Randy Shoup),因此我们权衡了系统中某些对分布式事务有需求的操作以及如果做不到事务可能带来的结果是否是fatal的,其实这个问题就是在在scalability,parallelism,transaction atomicity之间进行取舍。引入分布式事务会影响scalability,通过某些机制让操作在一个节点上执行会影响parallellism,剩下的就是损失atomicity,如何权衡。但我们发现这并不是一个all or nothing的问题,最后我们仍然没有引入分布式事务,因为我们发现我们系统中的atomicity问题是可以通过hack后归结到一两类问题来异步解决的,而这一两类问题即使没有实现atomicity,也不会对系统造成任何语义和正确性方面的影响。另外一个就是事务处理中的journal checkpointing技术,这个对于fast failover甚至我们后面的SDS的Server SAN特性来说也是非常重要,我们参考了一些经典关系型数据库系统的理论,进行了系统实现。


第四点是我们在读写IO方面的一些设计思路和经验,我们看到nutanix也有类似的lock-free的IO流程,实际上归根结底就是避免了in-place write的overhead,所有的IO写在commit元数据修改之前,对读操作不会有任何影响的。但我们系统实现后进行实测发现,因为如果IO块特别小,这样做的效果不如直接通过journalling的方式来实现更好,因此我们采取了两者结合的思路进行实现。


第五点是作为SDS系统,我们会suppose整个系统有非常非常多的盘,如何管理这些盘,并且保证数据的可靠性也是一个设计难点,通过checksum这种保证数据安全性的东西对于有大规模的盘的存储系统已经不完全适用了,其中有些坑可能还会出现在disk driver那边,同时我个人认为只有把单个盘的IO搞清楚才有可能做好整个SDS系统,一个单盘可能出现IO error, 但实际上把IO error进行细分和细粒度处理,会有很多很多情况,比如一个盘可能会出现只能读不能写的情况,究其原因可能是reserved area的空间满了。


第六点,作为SDS系统,本身也是一个集群系统,集群系统里一个典型的问题是节点假死问题。集群管理需要判断一个节点所处的状态是否健康,常见的故障或者半故障状态包括:


  • 节点宕机了

  • 节点负载过重

  • 节点网卡坏了

  • 节点和心跳监控节点之间的网络连接存在,但和其他节点之间的连接断开了(比如因为中间连接的交换机或者路由器的故障)

  • 其他半故障情况等:比如节点因为OOM被操作系统kill了一些正在拿着某些重要锁的云平台相关的线程,从而可能导致分布式死锁。


从上面复杂的节点故障状态可以看出,需要统一的故障评判标准进行节点的故障处理,并且需要在IO层面拥有高效的fence机制,以防止对故障节点的一致性恢复数据和故障节点本身已经发到kernel IO stack里的on-the-fly的数据最后出现交叉。 集群节点的动态加入和退出协议需要一整套完善的体系,除了要解决类似原子广播,脑裂,性能可扩展性等问题以外,本身协议的实现就需要幂等性(idempotent)和starvation-free,基于此可以才有可能进一步实现针对协议处理过程中出现nested failures的处理。同时节点故障恢复过程中整个系统集群如何做到对其他虚拟机中的业务做到最小的影响,也是Zetta高可用服务的一个重要组成部分,而这需要一个严密的QOS处理器和细粒度的锁控制器。


问答环节:



Q:zetta用什么协议出块设备 (特别是虚拟机)

A:zetta采用posix文件接口,并且支持object storage接口。


Q:节点和集群管理怎么做的?

A:metadata是全分布式的,但跟ceph,glusterfs采用类似一致性哈希的思路不太一样。


Q:metadata 在那里?

A:metadata本身是存在更加底层的一个metadata表文件里


Q:网络io和本地cache?

A:我们最开始的设计思路类似于unix的所有的东西都是文件的方式进行的设计和实现。

但我们是把单机做到的极致,才开始做分布式的。Zetta是全内核态实现的

我们自己实现的posix接口,但mmap接口目前没有实现。 direct IO,AIO,buffer IO都做的很好了。

另外我们在VM做IO访问的时候,也做了data locality,因为我们是完全控制自己的block分配策略。


Q:分布式存储理论上有超越本地ssd io性能的可能么 zetta目前和本地ssd裸盘独享做过对比么

可能是一种类似本地消费 远程副本机制?


A:是的

但实际在测试过程中,我们发现了一个问题:

不繁忙时刻sata ssd 一个IO延迟一两百微秒左右,但到了繁忙时刻, ssd的IO延迟是线性增长的,最高时刻大概能>1ms。相比之下,万兆网络延迟大概在100微秒,即使繁忙时刻延迟增长也比ssd的IO增长要低。所以data locality在某些情况下并不能提升IO性能。


关于“智囊团”云计算领域讨论群,周一至周五晚8点按照入群顺序,分享行业干货,进行讨论。入群需实名制。有兴趣可以加微信:aclood


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存