IT系统应用特点
大部分IT系统都可以归结到“计算密集型应用”或“数据密集型应用”这两类;这两类系统具有不同的特定和要求。
对于一个数据密集型系统而言,cpu的能力只是其中一个限制因子,数据量的多少,数据的复杂性,数据改变的频率和速度这些因素更加要。
对一个数据密集型系统而言,一般情况下,具有一些共有的特征。
1:存储数据以及允许其他应用访问数据(database)。
2:加速对数据的访问获取(cache)。
3:允许用户从数据种搜寻到合适的结果(search index)。
4:与其他应用交互,发送消息到其他应用以便可以同步或异步处理(Stream processing)
5:周期性的对大量的数据进行处理(batch processing)
应用架构
一个典型的数据密集型应用一般架构如下
设计数据密集型系统时的关注点
对于设计开发一个数据密集型系统,有以下几个点需要特别关注
1:可靠性:系统持续提供工作的能力。
2:可扩展性,随着系统的增长(数据量的增加,复杂性增加等),系统可以以一个合适的方式进行扩展。
3:可维护性,不同的人会工作在系统之上,系统需要具有合适的维护能力。
可靠性
对于一个软件系统而言,可靠性具有如下的要求
1:应用或系统符合用户的期望功能。
2:系统能容忍用户特定的错误操作和使用。
3:在特定的负载下,系统的性能是足够的。
4:系统能阻止任何非授权的访问和操作。
这些要求都满足时,可以说一个系统是在正确的工作。
为了满足可靠性要求,在系统设计实现时,有一些关键要素需要考虑
1:硬件错误(随着硬件的持续工作,最终硬件都会存在错误)
2:软件错误,软件错误是不可避免的,在设计实现时,需要仔细考虑各种假设和限制。
3:人的错误。任何一个人在使用IT系统过程种,都存在犯错的可能性。在设计实现时,不能依赖于人员的操作正确性。要考虑让系统能在人员操作错误时尽快的恢复
可扩展性
满足今天要求的系统,在未来不一定会满足要求,因此需要考虑系统的可扩展性。可扩展性描述了系统的容量和处理能力。
一般情况下,描述可扩展性之前,需要预先定义好系统的负载,例如每秒处理多少用户请求等。在负载有明确的定义和描述后,才能对系统的性能进行正确得描述,即当负载增加后,资源需要增加多少或不需要增加。
对于这一部分,在大多数的系统种,可以通过“处理时延”,“吞吐量”等进行描述。
可维护性
可维护性描述了一个系统被操作的难易程度。一般从3个角度去描述它
1:可操作性,即用户操作系统时是否足够简单。例如很容易监控系统的健康状态,跟踪系统的问题等;当某个子系统发生异常时,对其他系统不会造成影响等。
2:简单性,即管理系统时的复杂性;系统的架构是否清晰,新工程师能很容易接手,系统是否具有良好的抽象。
3:可改变性,需求一直在变化,因此系统也会持续发生变化,可改变性有要求系统能适应这种变化,并且能以一种简单容易的方式对系统进行修改
数据密集系统设计技术考虑
数据模型及查询语言
在设计数据密集型系统是,首先要考虑的是数据模型和查询语言。数据模型是一个数据密集系统的核心,数据模型是真实世界的映射,数据模型决定了系统的结构,API只是对模型的操作和访问。
常用的数据模型可以分为“关系模型(SQL)”和“NoSQL模型”两大类,在NoSQL中比较常见的模型有“文档类数据库”和“图数据库”。每一个数据模型都有对应的查询语言,以及实现框架。
在数据组织形式上,一般不同的数据会存在“一对一关系”“一对多关系”“多对多关系”“数据之间无关联关系”几种情况,其中对于 “一对多关系”“无关联关系”型数据,使用“文档型”数据库存贮比较合适。对于“多对多”型关系,使用“图模型”数据库存储比较合适。
存储与提取
对任何一个系统,都需要考虑数据的储存于获取,例如,是将所有数据都记录在内存空间中还是将部分数据记录在内存空间,部分数据记录到文件系统中。
一般情况下,存储数据后,还需要考虑如何快速的从存储系统中获取数据,此时就会考虑对数据建立索引。
对于少量的数据,可以直接在内存空间中建立索引,但是对于大量的数据,此时就需要考虑建立稀疏索引,只在内存空间中保存部分索引信息(当然,此时需要对建立索引的key进行排序)。
此外对于log结构的数据,可以使用LSM-tree结构进行数据的存贮和访问(此时会构建一个多层的索引结构)。
数据的存贮和访问中,使用最多的索引结构是B-tree结构,B-tree结构的时间复杂都是Olog(n)级别,几乎所有的数据库系统都实现了该类索引。
对于LSM-Tree结构和B-Tree结构,LSM-Tree对频繁写更友好。
在数据存储和提取方面,除了考虑索引以外,还需要考虑数据的事务处理和分析,在一个企业系统中,对数据的处理有各种各样的要求,例如分析输出报表,这类操作会对当前正在处理的事务造成影响,因此一般会建立一个数据仓库,将在线业务数据dump到该数据仓库进行单独的分析。通过数据仓库进行数据分析时,通常采取星型模式(也称为多维模型)进行分析。通过数据仓库对数据进行分期,一般会基于一些事实表(根据时间捕获一些事件数据并进行记录)。
当数据库中有数十亿的记录以及数据大小超过PE级别时,数据的查询就变的非常困难;但在实际应用时,对一个具有几十或几百个属性的表,并不会一次访问全部的属性,只会关注其中部分属性列,此时对于以行方式存储数据的数据引擎而言,需要将所有数据读入内存进行过滤,从而带来很低的访问效率,此时可以对数据以列的方式进行存储,从而只需要加载需要的列从而能提高查询效率(面向列的存储系统依赖于每个列存储文件中,所有的行要保持相同的顺序。
数据编码和演进
应用系统会一直处于演变之中,数据的模型和存储也会持续进行变化。因此需要在两个方向上维持数据的兼容性:
前向兼容:老代码可以读新代码产生的数据。
后向兼容:新代码可以兼容老代码产生的数据。
在内存空间中,数据被组织为对象,列表,结构体,数组,hash表等,但在网络上进行传输或需要人进行阅读时,需要编码为可以自解释的格式,例如json等;在这两类数据格式之间,需要进行数据格式的转换。
比较常用的编码方式有二进制编码,json编码,xml编码等,此外在进行具体操作时,可以通过数据流的方式在不同的进程之间进行数据传输,例如可以使用rest/rpc等服务完成数据流的传递。
分布式数据
使用单机进行数据的存储,总会面临一系列问题,例如,随着数据容量的增加,无法方便的进行规模扩展,同时,如果出现断电等异常状况,单机数据存储将面临业务不可使用的风险;另外,随着系统用户的增多,一个中心的单机系统,对用户的访问友好性总是不够。因此人们引入了分布式数据存储系统,通过多个位于不同地理位置的系统,通过相互交互为用户提供服务。
随着用户容量的增加,系统需要提供更大的处理能力时,有两类常见的扩展方式,1:垂直扩展(增加更多的内存,磁盘,使用性能更强劲的CPU);2:水平扩展,通过部署多套性能较低的机器,在多个机器之间进行分担业务,水平扩展架构也被称为“Shared-nothing架构。
Replication
使用多个机器后的第一个问题是完成不同机器之间的数据Replication。为什么需要Replication,理由如下:
1:需要让用户在更接近的位置访问系统数据,此时需要将中心节点中的数据拷贝到外围节点。
2:保持系统具有持续的工作能力,确保在某些节点异常时,整体系统仍然是可以使用的。
3:扩展系统的规模后,新的节点需要能提供服务,需要将旧节点的数据复制到新节点。
在节点之间进行数据复制时,如果数据是长时间保持不变的数据,那么这是个很easy的工作,但对于一个IT系统而言,数据总是在频繁的变化中,因此在不同的节点之间进行数据的replication将变的非常具有挑战性。
每一个计算机节点存储的一份数据,我们称之为“副本”,每次数据更新修改,都需要保证在所有“副本”之间一致,如果有某一个“副本”数据与其他节点不一致,则业务体验将出现异常。
为了保证不同副本之间的数据一致性,人们探讨和定义了多种方式。例如,定义其中的一个副本为leader,其他副本为followes,当followers需要改变数据时,必须通知leader,leader完成数据的修改后,follower才能修改数据,当leader改变了数据,必须将这个变化通知到其他follower;在进行leader和follower之间的数据同步时,有异步和同步两种方式,这两种方式会带来不同的效果,此外当leader出现异常或follower出现异常时,如何保证异常节点可以恢复或保证整个系统可以正常提供服务,人们讨论了很多方法,具体这些内容都可以通过索引Paxos问题相关的内容了解到(paxos是一个数学上的多节点一致性通信问题,对该问题的解决被利用在数据存储系统多节点间数据同步上。
Partitioning
当数据量最够大或访问量非常大的时候,在一个副本种保存所有数据开始变的不太现实,此时需要对数据进行分割,将大的数据划分为多个不同的部分,这样能带来非常好的可扩展性。
大部分情况下,一个系统会将分区和复制这两个特点结合起来,在某一个节点上为每个分区构建一个副本。
把数据分区后,对数据的访问也会有一些常见问题,例如,某个分区中的数据变成了访问热点,这样将导致该分区的数据被频繁访问而其他分区几乎不被访问(这个问题,可以通过随机数据的分布避免,但又带来不确定某个数据在哪个分区的问题,在查询该数据时,需要检查所有的节点才能知道具体的位置)。
当数据量持续增加,此时增加了新的节点和分区,此时将面临着将已有的数据重新分布到新节点上,即分区数据需要重平衡,在实现上需要构建新的hash规则。
事务
一个系统总是不可避免的会出现异常,在出现异常后,如何保证数据的正确性是一个很重要的问题,即保证数据在改变时,要么全部改变成功,要么全部改变不成功,而不会出现数据部分修改成功,部分修改失败。
在当前所有主流数据库系统中,都有一套机制保证完成事务流程。一般我们用ACID来描述数据库系统保证事务的四个要素( 即atomicity,Consistency,Isolation,Durability)。