数据库系统设计概述(上篇)

大家好我是佩奇
发布于 2022-8-4 15:21
浏览
1收藏

数据库系统设计概述

世界上只有两种开发人员,一种使用数据库系统的,一种开发数据库系统的。

数据是系统最重要的信息。大部分系统都是对数据的管理。应用系统通过数据模型来构建现实世界,通过算法操作对象或数据结构,来改变数据模型的状态。数据被组织在操作系统文件中,我们通过数据系统来组织,查询,搜索,处理数据。

本文将从数据库的发展、数据库的分类、常见数据库架构,数据库常见概念和技术等方面探讨这个我们接触最多的底层系统,并通过穿插不同数据库的实现原理,来了解数据库的具体实现。

本文分为五个大章节。探古溯源,从数据库的诞生,发展,现状和展望来了解数据库存在的意义,以及数据库设计的历史与现实原因。百家争鸣,本节从不同分类方式,讲解一些不同的数据库系统实现,有助于拓展我们的视野,在技术选型时可以作为参考(底层数据库系统的选型对整个系统的架构实在太重要了)。承上启下,本节是整篇文章的中间章节,前两章以兴趣点,纯理论展开,在本节中将对前两章做一个总结,有了前两章知识,我们已经可以去选择适合项目需求的数据库系统,对那些想更深入了解底层存储的同学也可以选择自己感兴趣的数据库类型和方案找到相应的实现,从而进入下一步学习。下面两章将讲解更多具体的技术点。知行合一,这一章节将讲解数据库的实现,分析一些数据库架构,分布式问题和解决方案,透析具体的数据库常见的技术点。

针对不同兴趣,大家可以按需取之,跳过不感兴趣的,看想关注的点。

 

一、探古溯源

疑今者察之古,不知来者视之往。——《管子》

数据库管理系统允许人员组织,存储和从计算机检索数据。在计算机的早期,使用“打孔卡”用于输入,输出和数据存储。打孔卡提供了一种快速的数据输入和检索方法。数据库在计算机的最新发展中起了非常重要的作用。第一批计算机程序是在 1950 年代初期开发的,几乎完全专注于编码语言和算法。当时,计算机基本上是大型计算器,数据(名称,电话号码)被认为是处理信息的残余物。当计算机开始商业化后,数据的重要性开始越来越被人重视。

数据库系统设计概述(上篇)-鸿蒙开发者社区timeline of database

题外话:穿越时间——笔者去了解一个东西,总喜欢追根溯源,从时间的起点,或从逻辑的深处开始探索。一个东西的逻辑原点往往是纯粹的简单的,之后随时间发展和广延的展开会逐渐复杂起来。所以从头开始了解一个东西,往往更容易理解。比如我们看一个系统的源码,可以从该系统的 1.0.0 版本开始,可以从这个系统最初想要解决的问题开始。

计算机数据库始于 1960 年代。此十年中,有两种流行的数据模型:称为 CODASYL 的网络模型和称为 IMS 的层次模型。SABER 系统被证明是商业上成功的一种数据库系统,该系统被 IBM 用来帮助美国航空管理其预订数据。

1970 年,大神 EF Codd 发表了一篇重要的论文:《👉大型共享数据库的数据关系模型》,提出了使用关系数据库模型的建议,他的想法改变了人们对数据库的看法。在他的模型中,数据库的架构或逻辑组织与物理信息存储断开连接,这成为数据库系统的标准原理。之后 UBC 开发了 Ingres 和在 IBM 开发了 SystemR。Ingres 使用一种称为 QUEL 的查询语言,引导而诞生了 Ingres Corp,MS SQL Server,Sybase,PACE 和 Britton-Lee 之类的系统。另一方面,System R 使用 SEQUEL 查询语言,它有助于 SQL / DS,DB2,Allbase,Oracle 和 Non-Stop SQL 的开发。关系数据库管理系统(RDBMS)已经成为公认的术语。

1976 年 P. Chen 提出了一个新的数据库模型,称为 Entity-Relationship,即 ER。该模型使设计人员可以专注于数据应用程序,而不是逻辑表结构。1980 年结构化查询语言或 SQL 成为标准查询语言。

RDBM系统是存储和处理结构化数据的有效方法。然而,随着互联网的快速发展,“非结构化”数据(视频,照片,音乐等)变得更加普遍。非结构化数据既是非关系数据,又是无模式数据,而关系数据库管理系统根本就没有设计用于处理此类数据。21 世纪后,NoSql模型进入人们的视野,NoSql 的出现是对互联网以及对更快的速度和对非结构化数据的处理需求的一种回应。一般而言,由于 NoSQL 数据库的速度和灵活性,它们在某些用例中比关系数据库更可取的。NoSQL模型是非关系型的,并且采用“分布式”数据库系统。这个非关系系统速度很快,使用临时组织数据的方法,并且处理大量不同类型的数据。一般而言,NoSQL 相对于 RDBMS 系统有如下优势:

 ● 更高的可扩展性
 ● 分布式计算系统
 ● 低成本
 ● 灵活的架构
 ● 可以处理非结构化和半结构化数据
 ● 没有复杂的关系
在数据库的发展历程中,虽然只经历了短短半个世纪,却诞生了一批优秀的数据库系统,SystemR、Postgresql、Mysql、DB2、Oracle、MongoDB、HBase、Neo4j、Elasticsearch 等等,都在软件的发展中发挥了重要的。

数据库系统设计概述(上篇)-鸿蒙开发者社区hitory of database


二、百家争鸣

现在春天来了嘛,一百种花都让它开放,不要只让几种花开放,还有几种花不让它开放,这就叫百花齐放。—— 毛泽东

迄今为止,业界诞生的数据系统数不胜数。如果你打开👉DB-Engines 网站,可以看到几百个功能定位不同的数据库系统。查看DB-Engines的分类排名,可以看出DB-Engines将如此众多的系统大致分为以下几类(👉网址):

数据库系统设计概述(上篇)-鸿蒙开发者社区db engines

Willian Blair 在《Database Software Market:The Long-Awaited Shake-up》一文中以以下维度为数据库系统做了一个细致的分类:关系型/非关系型、操作型/分析型。

数据库系统设计概述(上篇)-鸿蒙开发者社区databases

上图中的纵轴分类为 Relational Database(关系型数据库,RDBMS)和 Nonrelational Database (非关系型数据库,NoSQL),横轴的分类为 Operational(操作型,即 OLTP)和 Analytical(分析型,即 OLAP)。

非关系型的分类是一个比较笼统的划分,主要是针对传统关系型来区分的,与传统关系型系统模型不一致的都划分到了非关系型中。

非关系型(NoSQL)可以再进一步划分:Key-Value 型、列存储型、文档型、图数据库等。

 ● 文档存储:MongoDB、Elasticsearch、Amazon DocumentDB、Azure Cosmos DB 等。
 ● Key-Value 存储:Redis Labs、Oracle Berkeley DB、Amazon DynamoDB、Aerospike、LevelDB 等。
 ● 图数据库:Neo4j 等。
 ● 时序数据库:InfluxDB、Timescale 等。
 ● WideCloumn:DataStax、Cassandra、Apache HBase 和 Bigtable 等。

数据库系统设计概述(上篇)-鸿蒙开发者社区database type

关系模型
关系型模型是大多数开发人员接触最早,接触最多的数据库模型。它基于集合理论,是最经典的数据库模式。关系型数据库采用行和列的二维表来建模数据。它适合于提前知道数据模型,并且数据模型比较固定,发生变化比较小,对查询比较灵活的场景,你只需要将数据以行和列的方式存储,在查询的时候以不同的需要组合数据。关系型不适合数据层次较多,记录与记录之间关联较多的场景,这种场景往往造成查询复杂度上升,查询性能下降。

关系型数据库主要用于大多数商业数据处理,其大多数是事务处理(如 ERP 系统、银行交易、航空公司订票、销售系统、金融财务管理系统等)和批处理场景(如客户发票、工资单、报告等)。

20 世纪 70 年代至今,关系型数据库经久不衰,其简洁的数据模型和经典的 SQL 查询语句支撑了当前大部分互联网系统,在线论坛、社交网络、电子商务等等,各式各样的系统背后,都隐藏着一个强大的关系数据库。

关系型数据库用的比较多的除了 Oracle、Sql Server 等商业数据库外,就是 Mysql 了,另外本人比较喜欢和推崇是 Postgresql,被称为世界上功能最强大的开源数据库。

 

分析的世界
联机分析处理(Online analytical processing),简称OLAP,OLAP 是相对与传统的OLTP(联机事务处理,Online Transaction Processing)系统而言的,OLTP 是传统的关系型数据库的主要应用,侧重于基本的、日常的交互式的事务处理,例如银行交易。OLAP 是数据仓库系统的主要应用,支持复杂的分析操作,侧重分析决策支持,并且提供直观易懂的查询结果。OLAP 工具让用户能够从多个角度交互地分析多维数据。OLAP 由三个基本的分析操作组成:上卷(roll-up)、钻取(drill-down)、切片(slicing)和切块(dicing)。上卷涉及可以在一个或多个维度中累积和计算的数据的聚合。

OLAP 利于大数据量,数据更新少,经常使用大量数据做聚合统计的场景。OLTP 适合数据量小,频繁操作更新数据的场景。

OLAP 主要应用于商业智能、风控分析、智能报表等业务场景。

分析和事务是两个世界。在分析需求不大的时候,很多团队直接使用业务事务数据库做分析使用,这只能支持小数据量、分析需求变化不大,弱分析的场景。真正的数据分析场景,往往使用单独的数据仓库。在不影响业务库的情况下,实时或周期批量地从中提取数据,转换成对分析友好的数据模式,执行必要的清理和转换,然后加载到数据仓库中。将数据导入仓库的过程称为提取-转换-加载(Extract-Transform-Load, ETL)。

数据库系统设计概述(上篇)-鸿蒙开发者社区ETL

OLTP和OLAP没有明确的边界,它们的一些典型特性如下所示:

数据库系统设计概述(上篇)-鸿蒙开发者社区

业界有许多优秀的开源的 OLAP 系统,比如:

 ● Druid:Metamarkets 公司开发的一个用于大数据实时处理的开源分布式系统。目前已经成为 Apache 的开源项目。👉官网 👉了解
 ● Kylin:Apache Kylin™ 是一个开源的、分布式的分析型数据仓库,提供 Hadoop/Spark 之上的 SQL 查询接口及多维分析(OLAP)能力以支持超大规模数据,最初由 eBay 开发并贡献至开源社区。它能在亚秒内查询巨大的表。👉官网
 ● Presto:Presto 是一个对 PB 级数据运行交互式分析的开源分布式 SQL 查询引擎。👉官网
 ● ClickHouse:ClickHouse 是由号称“俄罗斯 Google”的 Yandex 开发的一个列存储的 OLAP 系统。👉官网


列式存储
传统 OLTP 数据库通常采用行式存储。以下图为例,所有的列依次排列构成一行,以行为单位存储,再配合以 B+ 树或 SS-Table 作为索引,就能快速通过主键找到相应的行数据。

数据库系统设计概述(上篇)-鸿蒙开发者社区

row-format

行存储适用于 OLTP 场景,OLTP 的大多数操作都是以实体(Entity)为单位,即对每条记录的增删改查,因此将一行数据在物理上放在相邻的位置更利于操作,也更利于特定的优化。

在 OLAP 场景中,极少单独操作单条记录的情况。OLAP 分析往往针对大量的数据集,在大量的数据集的基础上对特定的列做分组、过滤、聚合操作。因此在物理上将每列数据放在相邻的位置。

数据库系统设计概述(上篇)-鸿蒙开发者社区

column-format

这样如果针对某一列做分析聚合,只需要找到相应列的文件,或数据块的位置,比如,要计算上图数据的平均 Age,只需要获取 Age 列的数据集即可。但是,面向行的存储引擎仍然需要将所有行从磁盘加载到内存中、解析它们,并过滤出不符合所需条件的行。这可能需要很长的时间。

基于列模式的存储,天然就会具备以下几个优点:

 ● 自动索引

因为基于列存储,所以每一列本身就相当于索引。所以在做一些需要索引的操作时,就不需要额外的数据结构来为此列创建合适的索引。
 ● 利于数据压缩

利于压缩有两个原因。一来你会发现大部分列数据基数其实是重复的,拿上面的数据来说,因为同一个 author 会发表多篇博客,所以 author 列出现的所有值的基数肯定是小于博客数量的,因此在 author 列的存储上其实是不需要存储博客数量这么大的数据量的;二来相同的列数据类型一致,这样利于数据结构填充的优化和压缩,而且对于数字列这种数据类型可以采取更多有利的算法去压缩存储。
列式存储的概念其实很早就有,只是应时代所需,列式存储在近几年才火热起来,一时涌现了很多优秀的列式存储数据库,甚至很多之前的行存储系统,也有了列式存储的能力。

 ● Hbase:一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的 Google 论文《Bigtable:一个结构化数据的[分布式存储系统]》。HBase 不同于一般的关系数据库,它是一个适合于非结构化数据存储的数据库。另一个不同的是 HBase 基于列的而不是基于行的模式。
 ● Cassandra:它最初由 Facebook 开发,用于改善电子邮件系统的搜索性能的简单格式数据,集 Google BigTable 的数据模型与 Amazon Dynamo 的完全分布式架构于一身。Facebook 于 2008 将 Cassandra 开源,此后,由于 Cassandra 良好的可扩展性其被许多知名网站所采用,成为了一种流行的分布式结构化数据存储方案。
 ● 其中上一章节提到的很多 OLAP 数据库大多数是面向列式存储的。如 Druid、ClickHouse 等。


检索不再高深
曾几何时,全文检索是一个多么高深的技术,虽然如 Google 这样的全网搜索引擎背后的搜索算法和技术依然不是轻易就可以实现的。但现在大大小小的各种 App,网站的搜索功能的背后技术基本被一个强大的开源系统轻松就可以实现了。这个系统就是 Elasticsearch,一个基于 Lucence 的分布式实时全文检索数据库。

伦敦的公寓内,Shay Banon 正在忙着寻找工作,而他的妻子正在蓝带 (Le Cordon Bleu) 烹饪学校学习厨艺。在空闲时间,他开始编写搜索引擎来帮助妻子管理越来越丰富的菜谱。

他的首个迭代版本叫做 Compass。第二个迭代版本就是 Elasticsearch(基于 Apache Lucene 开发)。他将 Elasticsearch 作为开源产品发布给公众,并创建了 #elasticsearch IRC 通道,剩下来就是静待用户出现了。

公众反响十分强烈。用户自然而然地就喜欢上了这一软件。由于使用量急速攀升,此软件开始有了自己的社区,并引起了人们的高度关注,尤其引发了 Steven Schuurman、Uri Boness 和 Simon Willnauer 的浓厚兴趣。他们四人最终共同组建了一家搜索公司。

一个程序员为帮助妻子管理菜谱开发的搜索工具最终称为一个强大的全文检索数据库。看来,面向对象依然是程序员创作的强大灵感源泉之一。

数据库系统设计概述(上篇)-鸿蒙开发者社区revert-index

将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。这部分从非结构化数据中提取出的然后重新组织的信息,称之索引。将这些索引与文档建立映射关联,通过索引检索出对应的文档数据,这种词汇到文档的映射被称之为倒排索引。先建立索引,再对索引进行搜索的过程就叫全文检索。

提到全文检索,不得不提到的一个技术就是 Lucene,Lucene 是 apache 下的一个开放源代码的全文检索引擎工具包。提供了完整的查询引擎和索引引擎,部分文本分析引擎。

Elastisearch 就是基于 Lucene 的一个分布式开源全文检索数据库。它提供了一个分布式多用户能力的全文搜索引擎,基于 RESTful web 接口。Elasticsearch 是用 Java 开发的,并作为 Apache 许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。许多系统的搜索功能背后,其实就是一个强大的 Elastisearch 服务,Elasticsearch 也常由于日志检索,数据分析场景。

 

K-V 缓存霸主
在整个计算机系统中磁盘和网络是最慢的部分,一个系统中最重要的东西就是数据,而目前系统中的数据最终都存储在磁盘上。因此当前磁盘缓慢的读写速度和人民对系统响应数据和系统高并发之间的矛盾,就是目前系统需要解决的主要矛盾。将透彻了,所有的系统优化都是在缓解这个矛盾。

为提供系统响应数据和并发能力,一个最常见的手段就是缓存。在计算机系统中,CPU,内存,磁盘,网络的访问效率差着不同的数量级,为缓解这种数量级带来的访问效率问题,最常见的手段就是缓存。CPU 和内存之间有缓存,称之为 CPU 高效缓冲;内存和磁盘之间也自带缓存。

数据库系统设计概述(上篇)-鸿蒙开发者社区

cache

在分布式系统中,数据库访问的压力,我们常常使用分布式缓存系统来解决。

Redis 是一个高性能的 key-value 数据库。它支持存储的 value 类型相对更多,包括 string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和 hash(哈希类型)。Redis 支持缓存过期时间,原子操作,数据持久化,支持集群模式。

 ● K-V 缓存:将数据 K-V 化并缓存在 Redis 中,从而提高数据的访问效率,减小数据库的访问压力,这种常见的系统优化策略。
 ● 分布式锁:分布式锁,就是一个全局的临界资源,通过对这个临界资源的独占达到一种全局锁的功能,任何全局共享资源都可以实现分布式锁的功能,甚至 MySql,分布式文件系统。基于 Redis 的分布式锁,是常见的一种实现。
 ● Pub\Sub:发布订阅的管道功能本不应该是一个分布式缓存系统的功能,但 Redis 实现了这一部分功能,在一些简单的发布订阅场景下也可以很好的工作。
 ● 布隆过滤器:通过一个 bit 的 0 或 1 来表示 key 是否存在,通过 bit 集合来表示一组数据,这就是简单的布隆过滤器的实现。相对与用类似 Hash 的方式来存储 key 映射 boolean 值的方式,布隆过滤器可以节省大量的空间。Redis 就有布隆过滤器的实现。布隆过滤器常用来对大量数据做 True Or Flase 的判断,比如缓存是否存在,比如大量用户是否有权限。
 ● HyperLogLog:HyperLogLog 是用来快速计算基数的。基数,即不重复元素的个数(类似 SQL 的 count distinct)。
 ● 工具:介绍一些好用的 Java 技术栈的相关工具。👉Jetcache,阿里开源的一个基于注解的缓存框架。👉Redisson,一个强大的 Redis Java 客户端工具。


小而精
通常我们使用的数据库系统大多是 Client-Server 模式的,即数据库服务作为一个常驻进程运行在 Server 端,应用程序通过 TCP/IP 协议访问数据库系统。还有一种嵌入式的数据库,可以运行在本机中,这种数据库嵌入到应用程序中,随应用程序启动,数据存储在本地磁盘中。这种数据库是轻量的,一般占用内存少,代码精简。

 ● 👉SQLite:遵守 ACID,实现了大多数 SQL 标准,支持 SQL 语法。支持 JDBC。
 ● 👉H2:一个 Java 编写的关系型数据库,它可以被嵌入 Java 应用程序中使用,或者作为一个单独的数据库服务器运行。Spring Boot 内置的数据库。
 ● Berkeley DB:一个高效的嵌入式数据库和键-值数据库编程库。
 ● 👉LevelDB:是 Google 开源的持久化 KV 单机数据库,具有很高的随机写,顺序读/写性能,LevelDB 应用了 LSM(Log Structured Merge) 策略。另一个 Facebook 基于 levelDB 开发的 RocksDB,也是一个高性能的 key-value 型内嵌式存储引擎。LevelDB 或 RocksDB 常常被当作存储引擎使用。比如强大的时间序列数据库 Influxdb 早期底层存储引擎就是用于的 LevelDB;RocksDB 是流式计算框架 Flink 的 Checkpoint 的底层存储引擎;著名的分布式 Actor 框架 Akka 也使用 RocksDB 作为默认的 checkpint 存储。由于其强大的顺序读写能力,也常常用来做 WAL(write-ahead-log)日志存储引擎。
这些小而精的嵌入式数据库,除了用在一些小型设备上,如手机客户端等。也常常被用于很多自研数据库系统的存储引擎。这些自研的数据库系统,以上面那些嵌入式数据库作为存储引擎,在上面实现自己特有功能,从而实现一个特殊的数据库系统,比如扩展分布式功能,基于其现实一个分布式存储系统;比如基于 LevelDB 等实现磁盘队列,和分布式队列;比如基于其存储特殊的模型的数据,如时间序列数据库;比如基于其实现本地操作日志记录和重试提交,实现最终一致性的分布式事务解决方案。

 

三、承上启下
前几章我们已经了解了数据库系统的发展,也从不同角度了解了数据库系统的不同分类,并且了解到了许多不同功能场景的数据库系统。为我们如何选择数据库系统已经增添了一份基础知识。我们应该如何选择一个适合的存储方案呢?

 

原则
选择是基于需求确定的。所以必须明确需求场景,然后按需求场景选择适合的存储方案。
没有调查就没有发言权。方案调研就是一个调查过程,需要先了解不同数据库的基本特性,才能选择合适的存储方案。


基本场景
和前章数据库系统的分类很相似。其实上面数据库系统的分类一方面就是基于不同的使用场景才设计的,从而有不同实现的数据库系统,从而有针对不同场景的特殊优化,从而逐渐形成了不同场景的特殊模型。

事务性,如 Mysql 这些是最常见的事务性系统使用的存储方案,满足 ACID,使用简单。支持千万级别数据级别的读写。分析性,适合 BI,数据报表、数据监控等数据服务系统。文档型,适合高度可变的数据模型,当你事先不知道你的数据看起来究竟像什么样子,文档型是一个不错的选择,文档型也适合点查询多余集合查询的场景。图数据库,图数据库是一种很特殊的,新兴的数据库类型,它侧重于分析解释数据之间的相互关系而不是数据值本身,它适合推荐引擎、权限访问控制和地理数据等场景。时序性,时序性数据库在数据分析,时序数据展示,监控领域使用比较多,它适合对大量时间型数据查询、过滤、组合、聚合分析等。K-V 型,缓存和固定 View 模式的数据展示,K-V 型的需要按查询组合好存储起来,这样查询时按 key 获取即可。

 

读写
 ● 是否需要写事务
 ● 顺序读写还是随机读写
 ● 偏点查询还是大量数据集分析查询
 ● 数据结构变化大,还是查询结构变化大


数据量
数据量,需要考虑数据的数量,也需要考虑数据数量的增长速度,这样就需要考虑数据库的量级承载能力以及水平扩展能力。

 

数据用途
对临时数据和重要的业务数据的存储可以采用相对侧重点不一致的方案。对数据的一致性要求的强弱也会影响数据存储系统的选型。对数据事务的要求,对数据保存时间的选择也会不一样。

 

可靠性

数据的可靠性即保证数据的可用的能力,可靠性与成本一般是权衡的一体两面,需要对数据可用性的要求选用不同的存储架构。

 

可扩展性
可扩展性表现在数据使用的可扩展和系统本身的可扩展上。

 

可维护性
 ● 可运维性:方便运营团队来保持系统平稳运行。
 ● 简单性:简化系统复杂性,使新工程师能够轻松理解系统。
 ● 可演化性:后续工程师能够轻松地对系统进行改进,并根据需求变化将其适配到非典型场景,也称为可延伸性、易于修改性或可塑性。
学习和了解数据底层存储,除了可以搭建良好的存储架构是提供思路上的帮助,也可以让我们学习到很多平时纯业务开发接触不多的底层技术实现。对底层技术的了解和掌握,又可以反过来让我们更加了解我们的整个业务系统,对系统的合理性优化做出重要的选择。也可以帮助我们实现自己的系统。

开源数据库系统的良好的分布式架构,优秀的网络通信,性能强劲的内存和磁盘访问优化以及更多经典的数据接口和算法都是值得我们学习和借鉴的。

 

 

 

未完待续:数据库系统设计概述(下篇)

 

 

 

文章转载自公众号:码哥字节

已于2022-8-4 15:21:52修改
收藏 1
回复
举报
回复
    相关推荐