分布式存储技术(上):HDFS 和 Ceph 架构原理、特点和优缺点分析
面对企业级数据量,单机容量太小,无法存储海量的数据,这时候就需要用到多台机器存储,并统一管理分布在集群上的文件,这样就形成了分布式文件系统。HDFS是Hadoop下的分布式文件系统技术,Ceph是能处理海量非结构化数据存储的对象存储技术,本文将对他们的架构原理、特性和优缺点做介绍。
— 分布式文件系统HDFS —
HDFS全称为Hadoop Distributed File System,在2006年由Doug Cutting发布了第一个版本,是运行在通用硬件上的分布式文件系统。它提供了一个高度容错性和高吞吐量的海量数据存储解决方案。HDFS的推出给当时的行业提供了一个低成本、高可扩展的数据存储方案,尤其适用于互联网行业的海量用户访问日志的存储和检索需求,因此一经推出就受到了互联网行业的欢迎,以Yahoo为代表的互联网企业快速构建了基于HDFS的企业数仓,从而加速了Hadoop在互联网行业内的快速落地(后来这个Yahoo团队独立出来创立了Hortonworks)。此后经过3~4年的快速发展,海外的大型企业都开始拥抱HDFS,各种新型应用场景开始出现并创造了较大的业务价值。从2009年开始,国内的Hadoop应用开始出现,并最早在运营商和互联网行业落地。作为Hadoop体系的最成功的项目,HDFS已经在各种大型在线服务和数据存储系统中得到广泛应用,已经成为私有化部署领域海量数据存储的实施标准。
HDFS通过一个高效的分布式算法,将数据的访问和存储分布在大量服务器之中,在可靠地多备份存储的同时还能将访问分布在集群中的各个服务器之上。在构架设计上,NameNode管理元数据,包括文件目录树,文件->块映射,块->数据服务器映射表等。DataNode负责存储数据、以及响应数据读写请求;客户端与NameNode交互进行文件创建/删除/寻址等操作,之后直接与DataNode交互进行文件I/O。
HDFS通过副本机制保证数据的存储安全与高可靠,默认如上图所示配置为3副本,每个数据块分布在不同的服务器之上。在用户访问时,HDFS将会计算使用网络最近的和访问量最小的服务器给用户提供访问。HDFS支持文件的创建、删除、读取与追加,对于一个较大的文件,HDFS将文件的不同部分存放于不同服务器之上。在访问大型文件时,系统可以并行从服务器阵列中的多个服务器并行读入,增加了大文件读入的访问带宽。通过以上实现,HDFS通过分布式计算的算法,将数据访问均摊到服务器阵列中的每个服务器的多个数据拷贝之上,单个硬盘或服务器的吞吐量限制都可以突破,提供了极高的数据吞吐量。
HDFS将文件的数据块分配信息存放在NameNode服务器之上,文件数据块的信息分布地存放在DataNode服务器上。当整个系统容量需要扩充时,只需要增加DataNode的数量,HDFS后续通过balance算法将数据块搬迁到新的DataNode实例中。通过以上实现,HDFS可以做到在不停止服务的情况下横向扩容和数据重新分布。HDFS文件系统假设系统故障(服务器、网络、存储故障等)是常态,并通过多方面措施来保证数据的可靠性。数据在写入时被复制多份,可以通过用户自定义的复制策略分布到物理位置不同的服务器上;数据在读写时将自动进行数据的校验,一旦发现数据校验错误将重新进行复制。
受限于当时的需求背景和硬件能力水平,HDFS也有一些明显的架构问题,随着技术和需求的演进而逐渐成为瓶颈。通过NameNode来管理元数据有它的架构问题,首先是服务高可用问题,在Hadoop 1.0时代这是最大的架构问题,不过在2013年Hadoop 2.0中通过Master-Slave的方式得以解决;另外每个存储的文件都必须在NameNode的内存中维护一个描述符从而占据内存空间,当文件数据量太大时就会受限于单个NameNode的内存资源从而导致性能瓶颈(一般单个集群文件数量在亿级别以上时),社区在2017年推出的Hadoop 2.9版本提供HDFS Router Federation功能,通过不同的NameService处理挂载在HDFS上不同目录下的文件的方式来缓解这个问题。
存储成本问题对于大型HDFS集群是个更大的问题,HDFS的三副本策略保证了性能和存储成本的均衡,适合于热数据和温数据的存储和处理,对于冷数据存储来说成本就偏高,尤其与对象存储类的解决方案相比。开源社区直到2019年Hadoop 3.0里才推出了Erasure Code技术(星环科技在2014年推出HDFS EC技术),但由于推出时间较晚和技术成熟度等原因,目前并没有大规模落地。与云计算的存储技术融合是另外一个重要的架构问题,公有云有成熟的云存储方案,相对HDFS成本更低,与云平台的调度系统协调的更好,而HDFS只能定位作为云上的企业存储的一个细分方案之一。如各个云平台都推出EMR(Elastic MapReduce)类产品,如Google Dataproc,阿里云EMR等,但总体受欢迎度比较一般,缺少与云上其他数据分析与处理系统的全方位的打通和互联。
从2012年开始,国内重点行业的中大型企业都已经开始了大数据的布局,到2019年像金融、运营商、能源、**等重要行业大部分企业都已经构建了基于HDFS的数据存储系统,推动了一批重点的数字化应用的推广。如金融行业的ODS、历史数据存储、数据湖、科技监管类应用,运营商的经分系统、电子围栏、数字营销系统等,都已经是广泛使用的业务系统。由于国内外行业需求的差异性以及对公有云的接受程度不同,HDFS在国内仍然是一个非常重要的数据存储技术,也拥有更好的技术和应用生态,因此有着更为完善的技术生命力。
— 对象存储Ceph —
对象存储的设计目标是为了处理海量非结构化数据的存储问题,如邮件、图谱、视频、音频以及其他多媒体文件,并在社交、移动等应用中大量被使用,此外也大量被用于数据备份和灾备场景。
在业务开发层一般提供基于S3协议的开发接口,这套API提供了一整套的RESTful API,可以让应用可以通过HTTP PUT或GET命令来操作数据对象,每个对象有个自己的访问地址。与HDFS等文件类存储采用目录结构或多层级树形结构不同,对象存储在物理存储上一般采用一个扁平的数据存储结构,每个对象都是一个包括元数据、数据和唯一标识ID的完备数据描述,这样应用可以非常方便的去找到并访问这个数据对象,在存储的管理上也相对比较简单,尤其是大部分应用场景下数据对象都存储在远端的云服务器上。对象存储管理软件会将所有的硬盘资源抽象为一个存储池,用于数据的物理化存储。相对于文件类存储,对象存储相对来说成本更低,但相对数据分析的性能不佳,需要配套各种分析的缓存技术来能提供比较好的数据分析性能。
Ceph是一个开源的对象存储项目,诞生于2004年,提供对象、块和文件存储,其中对象存储功能在业内非常受欢迎,在国内已经有很多私有化云平台的对象存储生产落地案例。一个Ceph的存储集群一般包括三个部分:
-
Ceph存储集群服务端:在Ceph存储集群服务端架构中核心组件有Monitor服务、OSD(Object Storage Daemons)服务和Manager服务等。其中Mon服务用于维护存储系统的硬件逻辑关系,主要是服务器和硬盘等在线信息。Mon服务通过集群的方式保证其服务的可用性。OSD服务用于实现对磁盘的管理并实现真正的数据读写,通常一个磁盘对应一个OSD服务。
-
Ceph Clients:以library方式提供的客户端,可以用于访问Ceph服务端,它提供了3种协议来访问,包括对象存储的RADOSGW、块存储端的RBD以及文件存储的CephFS。
-
Ceph 协议:用于服务端和Client的通信协议。
由于一个分布式存储集群管理的对象数量非常多,可能是百万级甚至是千万级以上,因此OSD的数量也会比较多,为了有好的管理效率,Ceph引入了Pool、Place Groups(PGs)、对象这三级逻辑。PG是一个资源池的子集,负责数据对象的组织和位置映射,一个PG负责组织一批对象(数据在千级以上)。同时一个PG会被映射到多个OSD,也就是由多个OSD来负责其组织的对象的存储和查询,而每个OSD都会承载大量的PG,因此PG和OSD之间是多对多的映射关系。
当用户要将数据存储到Ceph集群时,存储数据会被分割成多个对象(Ceph的最小存储单元),每个对象都有一个唯一的id,每个对象的大小是可以配置的,默认为4MB。Ceph通过自创的CRUSH哈希算法,将若干个对象映射到PG上,形成一个对象与PG的逻辑组合,并根据PG所在的Pool的副本数,将数据复制到多个OSD上,保证数据的高可用。
图片来源于:https://www.wenjiangun.com/blog/952/
在集群的可扩展性上,Ceph可以做到几乎线性扩展。CRUSH 通过一种伪随机的方式将数据进行分布,因此 OSD 的利用就能够准确地通过二项式建模或者常规方式分配。无论哪一个都可以取得完美的随机过程。随着 PG 的增加,差异就下降:对于每个 OSD 100 个 PG的情况下,标准差是 10%;对于1000 个的情况下为 3%。线性的分布策略极好地将负载在集群中平衡。CRUSH 通过卸载所有的分配碎片到一个特定的 OSD 上从而来修正这样的问题。与哈希以及线性策略不同,CRUSH 同时也最小化了数据在集群扩展产生的迁移,同时又保证了负载的平衡。CRUSH 的计算复杂度为 O(log(n))(对于有 n 个 OSD 的集群),因此只需要 10 几个微秒就可以使集群增长到好几千个 OSDs。
值得关注的是,Ceph客户端所有的读写操作都需要经过代理节点,一旦集群并发量较大,代理节点就容易成为单点瓶颈。在数据的一致性方面,Ceph只能支持数据的最终一致性。
— 小结—
本文从架构和原理介绍了高度容错性、高吞吐量的分布式文件系统HDFS,和处理海量非结构化数据存储的对象存储技术Ceph(现在各项技术发展比较快,可能存在技术描述跟最新技术发展情况不太一致的情况)。那么在特定场景下,数据的快速查询、快速写入和可扩展性也是必不可少的,下一篇我们将介绍搜索引擎技术和宽表存储技术。
下一篇: hadoop 体系结构概述
推荐阅读
-
分布式存储技术(上):HDFS 和 Ceph 架构原理、特点和优缺点分析
-
阿里味 "的《Redis核心实践全彩手册》给你,还学不会转行--Redis基本是必考点。在 "阿里味 "的《Redis核心实战全彩手册》里,你还是学不会转行--Redis基本是必考点: - Redis 常见的性能问题有哪些?Redis 最常见的性能问题有哪些,如何解决?--性能相关 - Redis 缓存的雪崩、击落和穿透到底意味着什么?如何处理?--缓存相关 - Redis 主从集群有哪些常见问题?如何解决?--可用性 - 现有的 Redis 实例有 6GB 的存储空间,预计将来会扩展到 32GB,你能提供解决方案并分析其优势和潜在问题吗?--可扩展性相关 毕竟,10 家公司中至少有 8 家的架构系统中都有 Redis,基本上可以说是 IT 基础架构的必备系统。 因此,Redis 的开发和运维是很多大厂的重要工作,也是我们必须掌握的技术栈。 不过,Redis 毕竟是一个复杂的键值数据库,在实际使用中,有非常多的技术点需要注意,比如:各种数据结构、数据持久化机制、分片集群、主从集群等等。 一不小心,性能就会每况愈下,失去 "快 "的最大特点!
-
windows下进程间通信的(13种方法)-摘 要 本文讨论了进程间通信与应用程序间通信的含义及相应的实现技术,并对这些技术的原理、特性等进行了深入的分析和比较。 ---- 关键词 信号 管道 消息队列 共享存储段 信号灯 远程过程调用 Socket套接字 MQSeries 1 引言 ---- 进程间通信的主要目的是实现同一计算机系统内部的相互协作的进程之间的数据共享与信息交换,由于这些进程处于同一软件和硬件环境下,利用操作系统提供的的编程接口,用户可以方便地在程序中实现这种通信;应用程序间通信的主要目的是实现不同计算机系统中的相互协作的应用程序之间的数据共享与信息交换,由于应用程序分别运行在不同计算机系统中,它们之间要通过网络之间的协议才能实现数据共享与信息交换。进程间通信和应用程序间通信及相应的实现技术有许多相同之处,也各有自己的特色。即使是同一类型的通信也有多种的实现方法,以适应不同情况的需要。 ---- 为了充分认识和掌握这两种通信及相应的实现技术,本文将就以下几个方面对这两种通信进行深入的讨论:问题的由来、解决问题的策略和方法、每种方法的工作原理和实现、每种实现方法的特点和适用的范围等。 2 进程间的通信及其实现技术 ---- 用户提交给计算机的任务最终都是通过一个个的进程来完成的。在一组并发进程中的任何两个进程之间,如果都不存在公共变量,则称该组进程为不相交的。在不相交的进程组中,每个进程都独立于其它进程,它的运行环境与顺序程序一样,而且它的运行环境也不为别的进程所改变。运行的结果是确定的,不会发生与时间相关的错误。 ---- 但是,在实际中,并发进程的各个进程之间并不是完全互相独立的,它们之间往往存在着相互制约的关系。进程之间的相互制约关系表现为两种方式: ---- (1) 间接相互制约:共享CPU ---- (2) 直接相互制约:竞争和协作 ---- 竞争——进程对共享资源的竞争。为保证进程互斥地访问共享资源,各进程必须互斥地进入各自的临界段。 ---- 协作——进程之间交换数据。为完成一个共同任务而同时运行的一组进程称为同组进程,它们之间必须交换数据,以达到协作完成任务的目的,交换数据可以通知对方可以做某事或者委托对方做某事。 ---- 共享CPU问题由操作系统的进程调度来实现,进程间的竞争和协作由进程间的通信来完成。进程间的通信一般由操作系统提供编程接口,由程序员在程序中实现。UNIX在这个方面可以说最具特色,它提供了一整套进程间的数据共享与信息交换的处理方法——进程通信机制(IPC)。因此,我们就以UNIX为例来分析进程间通信的各种实现技术。 ---- 在UNIX中,文件(File)、信号(Signal)、无名管道(Unnamed Pipes)、有名管道(FIFOs)是传统IPC功能;新的IPC功能包括消息队列(Message queues)、共享存储段(Shared memory segment)和信号灯(Semapores)。 ---- (1) 信号 ---- 信号机制是UNIX为进程中断处理而设置的。它只是一组预定义的值,因此不能用于信息交换,仅用于进程中断控制。例如在发生浮点错、非法内存访问、执行无效指令、某些按键(如ctrl-c、del等)等都会产生一个信号,操作系统就会调用有关的系统调用或用户定义的处理过程来处理。 ---- 信号处理的系统调用是signal,调用形式是: ---- signal(signalno,action) ---- 其中,signalno是规定信号编号的值,action指明当特定的信号发生时所执行的动作。 ---- (2) 无名管道和有名管道 ---- 无名管道实际上是内存中的一个临时存储区,它由系统安全控制,并且独立于创建它的进程的内存区。管道对数据采用先进先出方式管理,并严格按顺序操作,例如不能对管道进行搜索,管道中的信息只能读一次。 ---- 无名管道只能用于两个相互协作的进程之间的通信,并且访问无名管道的进程必须有共同的祖先。 ---- 系统提供了许多标准管道库函数,如: pipe——打开一个可以读写的管道; close——关闭相应的管道; read——从管道中读取字符; write——向管道中写入字符; ---- 有名管道的操作和无名管道类似,不同的地方在于使用有名管道的进程不需要具有共同的祖先,其它进程,只要知道该管道的名字,就可以访问它。管道非常适合进程之间快速交换信息。 ---- (3) 消息队列(MQ) ---- 消息队列是内存中独立于生成它的进程的一段存储区,一旦创建消息队列,任何进程,只要具有正确的的访问权限,都可以访问消息队列,消息队列非常适合于在进程间交换短信息。 ---- 消息队列的每条消息由类型编号来分类,这样接收进程可以选择读取特定的消息类型——这一点与管道不同。消息队列在创建后将一直存在,直到使用msgctl系统调用或iqcrm -q命令删除它为止。 ---- 系统提供了许多有关创建、使用和管理消息队列的系统调用,如: ---- int msgget(key,flag)——创建一个具有flag权限的MQ及其相应的结构,并返回一个唯一的正整数msqid(MQ的标识符); ---- int msgsnd(msqid,msgp,msgsz,msgtyp,flag)——向队列中发送信息; ---- int msgrcv(msqid,cmd,buf)——从队列中接收信息; ---- int msgctl(msqid,cmd,buf)——对MQ的控制操作; ---- (4) 共享存储段(SM) ---- 共享存储段是主存的一部分,它由一个或多个独立的进程共享。各进程的数据段与共享存储段相关联,对每个进程来说,共享存储段有不同的虚拟地址。系统提供的有关SM的系统调用有: ---- int shmget(key,size,flag)——创建大小为size的SM段,其相应的数据结构名为key,并返回共享内存区的标识符shmid; ---- char shmat(shmid,address,flag)——将当前进程数据段的地址赋给shmget所返回的名为shmid的SM段; ---- int shmdr(address)——从进程地址空间删除SM段; ---- int shmctl (shmid,cmd,buf)——对SM的控制操作; ---- SM的大小只受主存限制,SM段的访问及进程间的信息交换可以通过同步读写来完成。同步通常由信号灯来实现。SM非常适合进程之间大量数据的共享。 ---- (5) 信号灯 ---- 在UNIX中,信号灯是一组进程共享的数据结构,当几个进程竞争同一资源时(文件、共享内存或消息队列等),它们的操作便由信号灯来同步,以防止互相干扰。 ---- 信号灯保证了某一时刻只有一个进程访问某一临界资源,所有请求该资源的其它进程都将被挂起,一旦该资源得到释放,系统才允许其它进程访问该资源。信号灯通常配对使用,以便实现资源的加锁和解锁。 ---- 进程间通信的实现技术的特点是:操作系统提供实现机制和编程接口,由用户在程序中实现,保证进程间可以进行快速的信息交换和大量数据的共享。但是,上述方式主要适合在同一台计算机系统内部的进程之间的通信。 3 应用程序间的通信及其实现技术 ---- 同进程之间的相互制约一样,不同的应用程序之间也存在竞争和协作的关系。UNIX操作系统也提供一些可用于应用程序之间实现数据共享与信息交换的编程接口,程序员可以通过自己编程来实现。如远程过程调用和基于TCP/IP协议的套接字(Socket)编程。但是,相对普通程序员来说,它们涉及的技术比较深,编程也比较复杂,实现起来困难较大。 ---- 于是,一种新的技术应运而生——通过将有关通信的细节完全掩盖在某个独立软件内部,即底层的通讯工作和相应的维护管理工作由该软件内部来实现,用户只需要将通信任务提交给该软件去完成,而不必理会它的具体工作过程——这就是所谓的中间件技术。 ---- 我们在这里分别讨论这三种常用的应用程序间通信的实现技术——远程过程调用、会话编程技术和MQSeries消息队列技术。其中远程过程调用和会话编程属于比较低级的方式,程序员参与的程度较深,而MQSeries消息队列则属于比较高级的方式,即中间件方式,程序员参与的程度较浅。 ---- 4.1 远程过程调用(RPC)