21/8/7 读书笔记 新时代的数据管理技术 函数式编程思想的应用

21/8/7 读书笔记

数据库系统概论 新时代下数据库系统所面临的挑战

这应该是《数据库系统概论》的最后一次的读书笔记了,抱歉,这篇笔记质量很差。书中之后的内容我大概翻阅了一下,大部分是对技术的简要的介绍,有时为了理解一些概念还需要从参考文献中进行引用。作者也许是希望通过这些内容引导我们去继续进行自主的挖掘,但我觉得这些内容已经处于本书的范畴之外了,因此还是不要放在本书相关的读书笔记中较好。

之后可能会读一读西瓜书,以及在云服务器上装个数据库。

之前介绍的基本核心在于传统的关系型数据库,而随着数据库应用领域的拓展、数据对象的多样化和复杂化、数据规模的快速增长等环境的变化,传统的关系型数据库暴露出了新的问题。接下来从各个角度分析传统关系型数据库系统存在的缺陷以及新时代下解决问题的思路。

对于复杂对象的建模能力差

复杂对象,包括文本、时间、空间等数据类型。实际应用中复杂对象是普遍存在的,比如用于测绘的地理信息数据库、用于舆情分析的网络文本数据库等。传统的关系型数据库利用关系的方式来描述这些复杂的对象是比较困难的,归根结底在于关系模型的建模能力存在短板,因此解决问题的思路在于采用新的数据模型

面向对象数据模型是利用面向对象的思想对客观事件进行建模,表达对象间的逻辑组织、限制与联系。由于面向对象数据库(OODB)的操作语言较为复杂,可以将面向对象数据模型与关系模型结合,形成对象关系数据库系统(ORDBS)。SQL99中引入了对于面向对象的功能标准。

XML数据模型用于表示半结构化数据,模型本身由XML文档的结点标记树、树上的操作和语义约束条件构成。

理论上,具有行数据特性的数据都属于结构化数据,比如我们的账户信息等。而对于图片、文本、音频等显然不方便用一行行组成的表格所组成的数据,其结构化性质就很差。通俗点来说,能以二维表形式描述的信息就属于结构化数据,反正为非结构化数据。

半结构化数据则是指具有一定的结构化性质,但是其结构体现于自身的内容中,即自描述性。举一个例子,我们考虑汽车,A车对应的数据是“品牌是本田,百公里耗油3L,颜色是黑色”,B车对应的数据是“品牌是特斯拉,颜色是红色,车载系统版本号是v2.0”。这两个数据均描述了汽车这一对象,但是结构上具有一定的不同。事实上,他们的数据本身描述了其数据的结构,而不像结构化数据中分为元数据和一般数据,但是又不能否认其具有一定的结构,作为非结构化数据处理又小题大做。

对于海量数据的处理能力差

大数据的时代下,数据的规模指数级上升,对数据库提出了高可拓展性、高可伸缩性、高性能等要求。传统的关系型数据库难以满足海量数据的柔性管理。解决问题的思路在于引入新的数据管理系统和管理机制。

NoSQL技术是非关系型的、分布式的、不满足事务特性(即ACID要求)的一类数据管理系统。其呈现出:

  • 对数据进行划分(partitioning)并采用大量节点的并行处理来获取高性能,拓展方式为横向拓展(scale out)

    横向拓展(水平拓展):垂直扩展(scale up),指购买性能上更好的服务器来运行的数据库,已经越来越更加困难和昂贵。一个更有吸引力的选择是水平扩展(scale out),将数据库运行在更多的机器组成的集群上。

    划分:NoSQL系统可以将数据库自动分片,作为数据拓展并且最小化宕机情形的手段,即将一个数据库划分为一些数据库分片,使它们遍布在一些分布式服务器上。

  • 放松对ACID一致性的约束,接受最终一致性(eventual consistency),以取得更高的性能。根据CAP理论,在分布式系统中,一致性、可用性、分区容错性三者至多只能满足其二。NoSql牺牲了对一致性的追求,仅追求最终一致性。这导致数据可能暂时出现不一致的状态。

  • 对数据进行备份以应对各个节点可能发生的异常。

NoSQL技术只是新兴的数据管理技术中的一种,如今的数据库管理领域已经呈现出多种技术共同融合发展的局面,有基于内存的面向实时计算和大数据分析的内存数据库系统、融合NoSQL和ACID特性的NewSQL技术等等。


函数式编程思想 现实应用

函数式编程思想在Java 8中有所引入,本章从Java 8开始,然后讨论函数式思想下的应用架构。

Java 8

函数式编程中的对象是值不可变的,而Java中的集合对象大多是值可变的,因此Java提供了在值可变集合上进行化约操作的方法,使得化约结果并不是额外的副本,而是直接在原对象上进行的更新。对于Java 8中的reducecollect,后者在值可变的容器上的效率更高。

函数式接口(Functional Interface)统一了匿名函数和单抽象函数接口(Single Abstract Method, SAM),这一机制使得我们能够用匿名函数来取代匿名类来就地实例化一个接口,从而兼顾了Java的使用习惯和函数式思想。

默认方法允许我们在接口上声明和定义非抽象非静态的方法,这使得我们能够在类上更加方便地装饰默认功能。考虑Java中的Arrays、Collections类,单纯为了提供静态方法而存在,而引入默认方法机制后,可以将这些方法设置为默认方法存放在接口中,由此避免了这些纯粹工具类的存在。这是对“mixin”特性的模仿。mixin将对象的方法的定义同对象的定义相分离,使得我们能够给对象增补功能。举一个例子,类A和类B分别实现了接口I以及其M方法,而A中持有一个B对象的引用,A中的M方法直接调用持有的B对象的M方法,这是实现composition的一种简洁方法。由于有了默认方法,M方法可以在接口I中定义,就不用额外设置一个B类。

Stream API和Optional已经在前文中提到过,故不再赘述。

函数式的架构

函数式的架构的根本在于“值不可变”,其将能够让我们摆脱很多负担:

  • 测试中,可变状态越多,那么需要的测试也越多。
  • 一个值不可变的对象的变化只发生在其构造期间,测试更加方便。
  • 值不可变的对象天生是线程安全的。
  • 值不可变的对象不会因为发生未预知的异常状况而陷入异常的状态中,因为一旦对象建立就不会发生因为值可变而导致的失败。

以数据库架构为例,以往架构的设计思想将读写融合在一起,从逻辑上来说数据库对象是值可变的。而追求函数式的命令-查询职责隔离(Command-Query Responsibility Segregation, CQRS)架构将读写分离,其中进行查询时可以在值不可变的前提下展开设计,因此能够使用函数式的编程思想。但是这样的分离也会导致一种类似于分布式的架构,使得事务的ACID性质难以保持。

我们必须注意到,引入函数式的值不可变思想虽然能够简化部分的操作,使得测试和各部分的配合更加顺畅,但是也会不可避免地将一些部分变得更加复杂困难。因此将函数式的思想引入架构的过程仍然是一个trade-off的过程

posted @ 2021-08-07 14:40  neumy  阅读(99)  评论(0)    收藏  举报