当前位置:   article > 正文

把数据转换为在内存中Tree(树形结构)。_财富管理中的分布式技术应用思考

财顾系统

作者 | 冯瑞飞

编辑 | 涂锟斌  魏涓涓  

3ec14c451e4f986116715d40001fdec8.png

财富管理平台的总体目标在于给大众客户提供财富管理服务,对技术上提出海量数据分析和联机访问需求,对应的技术解决方案就是分布式技术;分布式门派众多,对于同一概念也有不同的表述,却有着许多共同的技术基础,这些基础来自于在历史上技术探索和积累,分析清楚这些技术基础有利于在系统建设中灵活和恰当的使用。本文主要探讨数据模型和数据存储这两个与应用关系比较紧密的基础内容。

智能财顾

智能财顾构建于有着数十年历史的财富管理,金融投资等专业领域知识之上,结合大数据和AI作为工具,为客户提供全方面的财富管理服务,将原来只为高端客户提供的服务带入大众客户中。

智能财顾对海量的客户信息、客户合约、客户行为等数据进行分析和挖掘,为客户在流动性、保障性、投资三方面提供智能化的服务。在系统建设中,其中一个重要的问题是如何解决好在海量数据的情况下,如何平衡好扩展性、应用开发的操作性等各方面的的矛盾。 智能财顾系统属于数据密集型系统,重点在于数据层的设计,而从数据层上看可以抽象为如下技术问题:
  • 提供对于海量数据的大并发联机访问

  • 数据模型可以灵活的适应业务需求

  • 提供对于海量数据的高性能分析处理

在系统的建设过程中,我们发现这样一个数据密集型的应用, Oracle/MySQL包打天下的方法面对许多挑战,而引入NoSQL,消息队列,分布式计算引擎等等组件才能从容面对。通过这些基础,在不同领域中组装出我们需要的各类数据层组件。这些技术基础包括如下方面。

  • 数据模型

  • 数据存储

可以根据应用的场景,灵活的搭配于分布式和非分布式数据应用中。

数据模型

在历史上有多种数据模型互相竞争,从1960年开始IBM推出基于 层次模型 的IMS,后来 关系模型 自70年开始到90年代完成对主流市场的战略,后面从2000年开始随着互联网和分布式技术的出现逐步流行起来, NoSQL 解决了关系模型不适用的分布式领域。有意思的是NoSQL中一个很重要的模型代表文档模型(document data model)和最初的层次模型有相似之处, 各种技术看似层出不穷,但是其核心思想确存在继承关系

56e74302f67c9bb10f14d54711855cd0.png

下面介绍文档模型和关系模型。 关系模型和SQL 关系模型简单的说就是以业务数据和数据之间关系来组织若干个二维表,表内数据高内聚。表间关系通过各表的关联字段来保持联系。关系模型的模式(schema)较为固定,字段不能随便变化。相对于层次模型,关系模型在存储时不包含任何嵌套层次,在单表内可以很简单的搜索功能;表间也可以通过关联(JOIN)来不同表的数据聚合在一起,所以在数据存在多对多的场景中可以很好的适应。

关系模型的劣势主要是不太适应分布式的场景,由于存在许多的表间关系,在把数据进行分区时,顾得住关系中的左表,就顾不上右表,总有一方要妥协,数据访问不能本地化,成为数据访问中效率下降的一方。此外关系模型的模式较为固定,在适应业务的不断变化,和需要滚动发布的场景中存在不足。

和关系模型一起成长起来的SQL语言也成为极具生命力的语言,SQL语言及其适用于关系模型的特点,可以分成方便的申明查询和修改的逻辑。SQL的生命力也来自“申明式”这一特点。

早期的IMS数据库和分布式的计算引擎(MAPREDUCE),都需要程序员明确的告诉具体访问的路径,比如MR中需要编写明确的数据访问代码,比如如何过滤,如何切割数据,中间各环节如何落地到磁盘等等,这些程序存在不稳定的问题,一旦数据量、结构发生变化,都会引起应用的变更。 SQL只告诉数据库需要访问的数据范围,过滤条件等等,而关系数据库自动根据用户提交的SQL语句对实际的访问路径(access path)进行优化。当我们根据新的条件查询数据时,只需要创建新的索引,数据库就可以重新优化访问路径。SQL极大的降低应用和数据库的物理结构的耦合,各个数据厂商可以不断投入优化器的研发,使优化之后的访问路径在性能和易用性方面在绝大多数场景中超越了开发人员自己编写访问路径的模型。
虽然SQL最初是针对关系模型的,但是其中最重要的申明式访问的思想在其他组件中也得到了发扬光大,比如同采用关系模型的Hive和Spark也引入了SQL语言和访问优化器的思路,文档模型家族中的MongoDB使用类SQL的解决方案。都是为了降低应用访问代码和实际数据存储的耦合关系。 基于上面这些优点,至今关系模型和SQL也仍然在哪怕是对于分布式技术极度依赖的互联网巨头中也承担了大量业务中核心数据库的角色,诞生了各种分布式的关系数据库,例如在MySQL中应用分布式中间件的各类分布式方案;而且下一步业界的发展重点NewSQL也把关系模型继续放到和核心位置,比如google F1/Spanner和国内的TiDB都在做这方面的实践,并且取得非常可观的效果,后继会继续跟踪其进展并在环境中进行验证。 文档模型

文档模型是随着分布式应用逐步进入主流应用的,尤其是在互联网应用的场景中,商业应用出现了如下几个需求。

  1. 数据库可以逐步横向扩展,管理越来越多的数据,同时保持在在联机和批量业务中保持高速的访问。

  2. 数据模型可以随着业务可以灵活扩展,也就是应用在访问时才确定模型的内容

  3. 数据模型可以使用复杂的结构表达,比如树状结构,把数据内容从根节点开始逐层包在一颗树中
不管是国内的淘宝、微信、微博,还是国外的Twitter、Facebook、Amazon,业务都符合上面的模型需求,文档模型就是类似于一颗树状结构。数据类似下面这样: 文档模型可以很简单的表达复杂的结构,并且和业务对象可以直接映射,而关系模型需要基于业务把数据转换为关系模型,而且关系模型相对较为固定,当出现新的关系时,对于模型的设计会有较大影响。文档模型的所有相关数据物理上保存在一起,而关系模型需要根据关联字段到各个表中逐个搜索获取,当应用场景就是需要一次把所有数据取出时,文档模型存在较大性能优势。 文档模式当然也不是完美的,当存在多对多关系时,会需要在如下两个存在一定局限性的方案中取舍。
  • 数据冗余。数据冗余对于数据读取很友好,但是在数据修改时存在开销大、数据不一致等问题。比如把公司名称直接保存在和客户其他信息一起,一旦公司名称发生变化,所有冗余的信息都要同步修改,给修改操作带来很大的负担。这一点在关系模型中可以很简单的解决,在客户数据中只保留公司ID,而编号本身不会发生变化。

  • 保存其他文档的引用。在需要读取关联的数据时,需要应用手工关联到关系文档,取出对应的数据,增加了应用实现的复杂度。

文档模型和关系模型的结合 上面谈到了文档模型和关系模型各自的适用场景,所以各个数据库厂商都开始借鉴对方的优点。例如Oracle、MySQL开始支持保存、检索用JSON格式的内容,而NoSQL中的MongoDB等也开始支持一些基本的关联操作,比如上面例子中,使用$lookup语句来搜索相关的公司、配偶等等。 智能财股系统在不同的应用场景中使用不同的数据模型的方案,才能满足应用的功能和非功能的需求,下面两个例子可以说明这一点。 智能财顾数据需要根据基于个人客户在银行中全方面的信息,提供流动性管理建议。这个场景中,在客户访问系统时,系统实时获取客户所有全量持有产品,如果按照关系模型设计,数据表有几十张,记录数大到几万级别,在联机交易中需要关联多次,访问大量的数据,会带来性能的急速下降,这么多表的关联操作也给应用带来复杂度的上升。而利用文档模型的模型灵活和集中存放的特点,把客户所有持有的产品以客户编号排序,一个客户数据集中存在在一处,应用可以一次全部读取出来,大大提高了访问效率;而且应用可以和直接把数据映射到数据对象中,不用编写大量的JOIN语句,降低了应用的复杂程度。 另外一方面,给客户提供投资服务时,需要产生产品投资,合约内容包括产品编号、投资计划编号、投资金额,投资账户等等,适合于采用关系模型来表达,把产品详情、投资计划信息、账户信息等单独保存到各自的表中,保证这些信息在不同的场景中可以既可以各自独立的维护和访问,也可以通过关联( JOIN )到一起以后提供给应用访问。

数据存储

第二个比较重要的话题是关于数据存储。数据存储就是数据库如何把我们的业务数据保存在数据库里。从宏观角度看,大致包含三大类技术:B-TREE、LSM & SSTable、列式存储。虽然主流的关系型数据库,如Oracle、MySQL(innodb)都是采用B-TREE,但是两者其实并没有绑定关系,比如TokuDB,作为MySQL的存储引擎之一也是使用LSM作为其核心思想;NewSQL中的TiDB虽然也是基于关系模型的,但是底层的存储引擎使用RocksDB,也是基于LSM&SSTable。底层技术处于互相学习和融合之中。 B-TREE B-TREE和关系模型同步出现在70年代就开始,到90年几乎占领了所有的数据库市场。B-TREE简单的理解就是多叶节点的树,每个叶节点并非是每行数据,而是数据库的的数据块。这么设计的原因是影响搜索性能的就是树的层次,而且磁盘的读写其实是基于块(BLOCK)的,使用块可以大大减少节点数量,进而减少树的层次,B-TREE的搜索时间复杂性为O(log(  b))。使上亿条记录可以在3-4层树上表示。 B-TREE的特点在于读写性能比较稳定,响应时间和磁盘随机读写的时间成正比(10ms)。并且由于B-TREE对应到数据库的每条记录,可以很容易的实现事务、行锁和隔离级别。读的性能略高于LSM算法。而且B-TREE基于块的存储方式,可以很容易的把内存中的块和磁盘上的块一一对应起来,很容易的实现缓存,在实际应用中,前两级甚至三级节点内都可以在缓存中读取,大大提高了访问效率。 而不足在于真正面对海量数据时,比如数据量进入到百亿级别时,由于树层数和缓存比率的减少,性能会逐步下降。不过随着进化现在也出现了分布式的B-TREE实现,比如oracle的locale index。此外由于B-TREE在写入时也需要通过搜索定位到叶节点,相对于LSM写入时开销较大。 LSM & SSTable 目前主流的存储还是磁盘+内存的架构,磁盘 顺序读写 的性能高于 随机读 三个数量级,而在内存中进行随机读写的的性能也大于磁盘的三个数量级, 可以得出用磁盘当做磁带一样只做顺序读写,而把内存当做磁盘,提供所有的随机读写访问的总体思想 这也就是出LSM-Tree的算法。 简单说就是在内存中维护一张MemTable,把所有最新的数据都写到其中,所有数据依据key值进行排序( 随机读写 )。当MemTable的大小到大阈值之后,把它写到磁盘上,形成一个个的SSTable( 顺序写 )。每个SSTable构造一个索引,由于SSTable中的数据都是排好序的,所以索引较小,可以保存在内存里面,所以所有的索引搜索动作都是在内存进行的( 随机读 )。 每次查找就的过程如下,首先在MemTable中搜索(内存随机查找),如果没有依次在每个SSTable的索引中查找(内存随机查找)。 把查找从磁盘随机动作变成了基于内存的随机动作 。随着SSTable的增多,搜索的次数会增加,为了提高性能,后台会把多个SSTable合并为一个(如HBase、LevelDB等等)。并且提供布隆过滤器(BloomFilter)来过滤掉不需要的SSTable。 总体效果上看写入的效率大大高于基于B-Tree的存储引擎,而读取性能接近于B-Tree 。 LSM & SSTable在写入密集型应用中有较大优势,读取方面也有不错的表现。不足在于上面提到的不定期对不断增加的SSTable进行合并动作,合并时对于数据库会产生一定压力。 由于这些特点,LSM & SSTable大量应用许多组件中,比如HBase、LevelDB等KeyValue数据库中,还在消息引擎Kafka和搜索引擎Solr使用。 列式存储 以上两种存储引擎主要适合于联机场景,智能财顾有大量的基于客户各类行为数据的批量计算,如预计客户的流动性缺口等等。在这些场景中,列式存储在性能上有非常明显的优势。随着各类大数据应用的扩展,列式存储从和Hive共生的ORC,到和Spark共生的Parquet也应用到了各个数据分析应用中。 从传统的数据分析类应用,到人工智能应用,都需要遍历整个相关的的数据,上面也提到磁盘在顺序读写和随机读写性能方面的巨大差距,所以所有的仓库类数据库都会在面对全表便利的场景中,采用磁盘顺序遍历的方式。所以遍历的文件空间越小,性能越快。列式存储和前面两种存储方式按照“行”来保存数据不同,列式存储把数据一列一列的独立保存,减少数据库每次访问的文件尺寸。 首先,分析应用一般局限于对于表中的部分字段都分析,列式存储可以让引擎只访问部分字段,减少吞吐量。 其次,列式存储可以把数据压缩到行式存储不可实现的地步。因为行级别的存储方式压缩是基于数据块,压缩比大致为50%-70%左右,而且压缩比越大,解压缩对于CPU的占用也越大。由于单列内的数据都是非常类似的,尤其是各种码值类的数据,比如性别(男、女、其他),再比如职业也只有几十种,行数越多,压缩比越大。10亿客户的性别,也可以简单的表达为如下这样:“连续100个男性、连续50个女性、又连续80个男性、连续70个女性”,按照每行的位置依次表达下去。再次,同样由于列内数据的取值范围有限,可以通过位图来表达,比如10表示男01表示女,只用2个bit就可以表示,进一步增加压缩比,在许多场景中把以前数G的数据压缩为几百K。 上述两点可以显著降低批量计算对于存储的吞吐压力和计算效率。 当然列式存储也不是没有缺点,在更新时相对行式存储来说,很难直接做到就地修改的效果,往往都需要把整列锁住,重新计算,重新生成整个列。所以列式存储更多的适合于数据分析类需要全表遍历的场景。 数据存储总结 综合考虑上面三种存储方式的优势和不足。智能财顾根据应用访问数据的特点把数据分布到了不同的存储机制中。 对于需要提供事务、锁、数据量不是特别大的场景中,采用基于B-TREE的存储机制,例如合约签订,合约执行等业务需要数据库提供多行的事物处理,而且数据量和交易量不是特别大,把数据保持在传统关系型数据库中,也就是利用B-TREE的优点。 对于数据量和访问,以及每日新增、修改量特别大的场景,存储和访问采用LSM&SSTable作为存储引擎,例如全量客户的标签数据,数据量达到百亿级别,每日增量也可达上亿记录,数据保存在HBase数据库中,可以较为轻松的面对,在数十分钟级别完成批量更新,而查询响应时间也没有随着数据量的增加而变慢,仍然保证在几毫秒以内。 最后是列式存储,适合于数据分析类场景,智能财顾在进行客户流动性预测、客户投资方案生成这类分析场景中,需要对于数据进行反复遍历的操作,最终采用的方案是把数据从原来的产品数据库中导出后存到Hadoop集群的HDFS中采用Parquet格式存储数据,后继采用Spark来访问时,遍历数据的时间可以控制在数分钟级别

结语

在分布式领域中存在丰富到有些杂乱的组件,Spark, HBase, Casandra, Hive,Kafka等等数十个产品,但是逐个分析之后,我们发现其实背后依赖的基础存在很多共通性, 把握这些共通性,也就是基础策略和算法,掌握这些基础,可以加深我们对一这么多组件的理解,更好的把技术融汇到应用当中 要建设一个具有弹性伸缩、易于开发和维护的技术特性的系统,辨识其中各种产品的技术基础,分析其差异和优劣,才能在应用中扬长避短,达成业务目标。 关于分布式,你是怎么看的?欢迎参与投票

END

 往期推荐 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/528249
推荐阅读
相关标签