后端技术体系概览

本文是极客时间《后端面试38讲》笔记总结。

一、软件的基础原理

学习方法

软件运行原理

进程

线程

数据结构原理

数组

链表

哈希表

队列

网络编程原理

DNS

CDN

HTTP

TCP

LB(负载均衡)

文件系统原理

硬盘

文件系统

分布式文件系统

数据库原理

数据库架构和 SQL 执行过程

一个 SQL 提交到数据库,需要经过连接器将 SQL 语句交给语法分析器,生成一个抽象语法树 AST,AST经过语义分析和优化器,进行语义优化,使计算过程和需要获取的数据尽可能少,然后得到数据库执行计划,执行计划提交给具体的执行引擎进行计算,最后将结果通过连接器再返回给应用程序。

连接器

提交 SQL 到数据库执行,首先需要建立与数据库的连接,数据库连接器会为每一个连接请求分配一块专用内存空间用于上下文管理。建立连接一般比较耗时,因此应用程序启动时,一般会初始化一些连接放在连接池里。

连接一旦建立,就会消耗数据库的内存资源,如果启动了很多应用程序实例,这些程序就会尝试大量的连接,这样即使不提交 SQL 到数据库执行,也会对数据库产生很大的压力。优化连接的主要方法如下:

语法分析器

连接器收到 SQL 以后,会将 SQL 交给语法分析器处理,根据 SQL 语法规则生成对应的抽象语法树。如果 SQL 中存在语法错误,在生成语法树的时候就会报错。

语法分析和优化器

语义分析和优化器会对抽象语法树进一步进行语义优化,也就是在保证 SQL 语义不变的前提下进行语义等价转换,比如,将各种嵌套 SQL 进行语义等价转换,并利用索引等信息进一步优化,使最后的计算量和中间过程数据量尽可能小。

语义分析和优化器最后会输出一个执行计划,有执行引擎完成数据查询或更新,这一步可以使用 explain 语句查看。

执行引擎

执行引擎,或者叫存储引擎最后执行这个执行计划。MySQL 有多种执行引擎,默认是 InnoDB,其他还有 MyISAM、Memory 等。每个执行引擎有不同的特点。

数据库文件存储原理

B + Tree

image-20200808183234347

数据库的索引 使用 B+ 树结构,B+ 树是一种 N 叉排序树,树的每个节点包含 N 个数据,这些数据按顺序排列。两个数据之间是一个指向子节点的指针,而子节点的数据则在这两个数据大小之间。

B + 树的节点存储在磁盘上,如果每个节点存储 1000 多个数据,这样树的高度最多只需要 4 层,就可以存储数亿的数据。如果将根节点缓存在内存中,则最多只需要 3 次磁盘访问就可以检索到需要的数据。

在进行查找操作时,首先在根节点上进行二分查找,找到 key 所在的指针,然后递归的在指针指向的节点上进行查找,直到查找到叶子节点,然后在叶子节点上进行二分查找,找出 key 所对应的 data,时间复杂度为 O(logn)。

聚簇索引

聚簇索引的数据记录和索引记录存储在一起,也就是叶子节点包含了完整的数据记录,查找记录只需要对树进行搜索,查找到 key 也就查到了完整的数据。MySQL InnoDB 的主键就是这种聚簇索引,主键 ID 和所在的记录行存储在一起。

image-20200808183536831

InnoDB 建表后创建的文件:

如果要建立辅助索引,InnoDB 引擎会建立辅助索引字段的 B+ tree,节点里存的是 key 的值,叶子节点存储的是主键的值,注意 是主键 key 的值,查找的过程变成:先根据辅助索引查找到主键的值,再根据主键的 B+ 树索引找到叶子节点对应的数据行记录,这个过程也称为回表。

非聚簇索引

非聚簇索引即索引文件和数据文件分开存储。不管是主索引还是辅助索引,B+ 树的叶子节点存储的都是对应数据的物理地址。拿到这个物理地址后,就可以到数据文件中直接定位到具体的数据记录了。MyISAM 引擎就是这种非聚集索引的实现方式。

image-20200808183912651

MyISAM 创建表后生成的文件有:

数据库事务

数据库可以支持事务,事务是满足 ACID 特性的一组操作的集合,即 原子性、一致性、隔离性、持久性。

一个事务对多条记录进行操作,要么全部更新,要么全部不更新。数据库主要依靠事务日志文件实现事务的操作。

在进行事务操作时,事务日志会记录更新前的记录,然后再更新数据库中的记录,如果全部记录更新成功,那么事务正常结束,否则整个事务回滚,已经更新的记录根据事务日志中的数据进行恢复,这样全部数据都恢复到提交前的状态。

多个事务并发执行,会产生并发一致性问题,主要有丢失修改、脏读、不可重复读、幻读等问题。

数据库管理系统提供了事务的隔离级别来处理并发一致性问题。

数据库备份

数据库提供了 binlog 日志文件,记录了全部的数据更新操作,这样可以复现数据库的全部历史变更。

有了 binlog 日志 还可以实现数据库的主从复制。

MySQL 主从复制主要涉及三个线程:binlog 线程、I/O 线程和 SQL 线程。

二、软件的设计原理

软件设计方法论

软件建模

通过软件建模抽象出软件系统的主要特征和组成部分。在软件开发中,有两个客观存在,一个是我们要解决的领域问题,另一个就是最终开发出来的软件系统。

4+1视图模型

软件建模比较知名的是 4+1 视图模型。包括 5 个部分:

UML建模

UML,即统一建模语言,是目前最常用的建模工具。UML 规范包含了十多种模型图,常用的有 7 种:类图、序列图、组件图、部署图、用例图、状态图、活动图。

软件设计原则

软件设计的开闭原则

开闭原则:软件实体(模块、类、函数等等)应该对扩展是开放的,对修改是关闭的。通俗点说,就是软件功能可以扩展,但是软件实体不可以被修改。

开闭原则就是要实现不修改代码就能实现需求的变更。

实现开闭原则的关键是抽象。当一个模块依赖的是一个抽象接口的时候,就可以随意对这个抽象接口进行扩展,这个时候不需要对现有代码进行任何修改,利用接口的多态性,通过增加一个新实现该接口的实现类,就能完成需求变更。

开放封闭原则是指导性的原则,为了实现这一原则,创造了多种设计模式:如策略模式、适配器模式、观察者模式、模板方法模式

软件设计的依赖倒置原则

依赖倒置原则的几个编码守则:

  1. 应用代码多使用抽象接口,尽量避免使用那些多变的具体实现类
  2. 不要继承具体类,如果一个类在设计之初不是抽象类,那么尽量不要去继承它。对具体类的继承是一种强依赖关系,维护的时候难以改变。
  3. 不要重写(override)包含具体实现的函数。

软件设计的里式替换原则

如果设计类的继承关系,怎样使继承不违反开闭原则,这就要用到里式替换原则:子类型必须能够替换掉它们的基类型。也就是,程序中所有使用父类的地方,都应该可以用子类代替。

关于继承是否合理,需要把继承放到具体的应用场景上下文判断,看使用基类的地方,是否都可以用子类去代替。

里式替换原则还要求:子类不能比父类更严格。

注:如果要使用一个类的方法,最好的方法是组合这个类,而不是继承它,组合优于继承。

软件设计的单一职责原则

软件设计有两个基本准则:高内聚和低耦合。前面几个原则都是围绕低耦合设计的。内聚性主要研究组成一个模块或者类的内部元素的功能相关性。

具体设计时,应该遵循这样一个设计原则:一个类,应该只有一个引起它变化的原因。

web 应用架构的演进过程就是一个不断进行职责分离,实现单一职责的过程。以 Java 为例,最早就是一个 Servlet 完成一个请求处理,从获取数据,进行逻辑处理,访问数据库,得到处理结果,根据处理结果构造返回 HTML。这些职责全部都在一个类里完成。

后来有了 JSP,实现了最基本的分离:构造页面的 JSP 和处理逻辑的业务模型分离。但是这种分离并不彻底, JSP 中依然存在大量的业务逻辑代码,代码与 HTML 标签耦合在一起,职责分离的并不彻底。

真正将视图和模型分离的是后来出现的各种 MVC 框架。不仅实现了页面与业务逻辑的分离,而且将复杂的业务模型实现了分层,划分为业务层、服务层、数据持久层,使各职责进一步分离,更符合单一职责原则。

软件设计的接口隔离原则

接口隔离原则是说:不应该强迫用户依赖他们不需要的方法。

通过使用接口隔离原则,我们可以将一个实现类的不同方法包装在不同接口中对外暴露。应用程序只需要依赖它们需要的方法,而不会看到不需要的方法。

接口隔离的常见做法是通过对接口多重继承的方式,一个类实现多个接口,不同接口服务不同调用者,不同调用者看到不同的方法。

设计模式

反应式编程

在高并发情况下,传统的应用处理方式是:为每一个用户请求分配一个线程,当程序内部因为访问数据库等原因造成线程阻塞时,线程无法释放去处理其他请求,这样会造成请求堆积,不断消耗资源,最终导致程序崩溃。

解决这种情况的方法是使用反应式编程。反应式编程本质上是一种异步编程方案,在多线程(协程)、异步方法调用、异步 IO 访问等技术基础上,提供了一整套与异步调用相匹配的编程模型,从而实现程序调用非阻塞,即时响应等特性。

反应式系统应该具备如下特质:

反应式编程只需要有限的几个线程就可以完成大量的 Service 处理和消息传输,这些线程不会阻塞等待,从而大大提高了系统的吞吐能力和响应时间。

组件设计原则

软件设计的核心目标是高内聚、低耦合。

组件内聚原则

组件内聚原则主要讨论哪些类应该聚合在同一个组件中,以便组件既能够提供相对完整的功能,又不至于太过庞大。具体遵循以下原则:

组件耦合原则

组件耦合原则讨论的是组件之间的耦合关系应该如何设计。组件耦合关系设计应该遵循三个原则:

书籍推荐

《UML精粹》

《敏捷软件开发:原则、模式与实践》

《架构整洁之道》

《企业应用架构模式》

《实现领域驱动设计》—— Vaughn Vernon/电子工业出版社

《领域驱动设计精粹》

三、架构的核心原理

分布式架构

垂直伸缩和水平伸缩

垂直伸缩 就是提升单台服务器的处理能力,比如用更快频率的 CPU ,用更多核的 CPU,用更大的内存,更快的网卡、更多的磁盘组成一台服务器,通过这种手段提升系统的处理能力。

垂直伸缩带来的价格成本和服务器的处理能力并不一定成线程关系,也就是说增加同样的费用,并不能得到同样的计算能力,而且单台服务器的计算能力并不能无限增加。

水平伸缩 指的是不去提升单机的处理能力,而是使用更多的服务器,将这些服务器构成一个分布式集群,通过这个集群,对外统一提供服务,以此来提高系统整体的处理能力。

互联网分布式架构演化

互联网架构的演化过程

缓存架构

缓存,就是将多次读取的数据暂存起来,这样应用程序需要多次读取的时候,就不必从数据源重复加载数据了,这样就可以降低数据源的计算负载压力,提高数据响应速度。

一般来说,缓存分为两种:通读缓存和旁路缓存。

通读缓存

通读缓存: 应用程序访问通读缓存获取数据时,如果通读缓存有应用程序需要的数据,就直接返回;如果没有,那么通读缓存就自己负责访问数据源,从数据源获取数据返回给应用程序,并将这个数据保存在自己的缓存中。

互联网应用中使用通读缓存的是 CDN 和反向代理缓存。

旁路缓存

旁路缓存: 用于程序访问旁路缓存获取数据的时候,如果旁路缓存中有应用程序需要的数据,就直接返回,如果没有,就返回空 (null),应用程序需要自己从数据源读取数据,然后将这个数据写入到旁路缓存中。

应用程序在代码中主要使用的是对象缓存,对象缓存是一种旁路缓存。

对象缓存可以分为两种,一种是本地缓存 ,缓存和应用程序在同一个进程中启动,使用程序的堆空间存放缓存数据,本地缓存的响应速度快,但是缓存可以使用到的内存空间比较小,如要要缓存大量的数据,就要使用远程的分布式缓存

分布式缓存是指将一组服务器构成一个缓存集群,共同对外提供缓存服务。

缓存注意事项

使用缓存主要可以带来三方面好处:

  1. 缓存的数据通常存储在内存中,距离使用数据的应用也更近一点,因此相比从硬盘上获取,或者从网络上获取,它获取数据的速度就更快一点,响应时间更快,性能表现更好。
  2. 缓存的数据通常是计算结果数据,比如对象缓存中,通常存放经过计算加工的结果对象,如果缓存不命中,就需要从数据库中获取原始数据,然后进行计算加工才能得到结果对象,因此使用缓存可以减少 CPU 的计算消耗,节省计算资源,同样也加快了处理的速度。
  3. 通过对象缓存获取数据,可以降低数据库的负载压力。通过 CDN、反向代理等通读缓存获取数据,可以降低服务器的负载压力。这些释放出来的计算资源可以提供给更有需要的计算场景,比如写数据的场景,间接提高整个系统的处理能力。

使用缓存也会带来一些问题:

数据脏读的问题:缓存的数据来自数据源,如果数据源的数据更改了,那么缓存中的数据就变成了脏数据。

解决方法有两个:

异步架构

上一节中,缓存改善的是系统的读操作性能,但是对于写操作,缓存是无能为力的。

提升系统写操作性能的主要手段是使用消息队列的异步架构,有时候也被称为事件驱动架构。这种架构不仅可以提升系统的写性能,而且可以实现系统间的解耦。

消息队列异步架构主要角色包括消息生产者、消息队列、消息消费者。消息生产者通常是主应用程序,生产者将调用请求封装成消息发送给消息队列。此外还需要开发一个专门的消息消费者程序,用来从消息队列中获取、消费消息,由消息消费者完成业务逻辑处理。

根据消息消费方式,又分为 点对点模式发布订阅模式

使用异步架构的好处

负载均衡架构

负载均衡可以将高并发的用户请求分发到多台应用服务器组成的集群上,利用更多的服务器资源处理高并发下的计算压力。

负载均衡的实现主要分为两步:

负载均衡

数据存储架构

在互联网系统架构中,承受着最大处理压力,最难以被伸缩的就是数据存储部分。原因主要有两方面:一方面,数据存储需要硬盘,而硬盘的处理速度要比其他几种计算资源,比如 CPU、内存、网卡要慢一些;另一方面,数据是公司最重要的资产,公司需要保证数据的高可用以及一致性,非功能性的约束更多一些。

目前主要用来改善数据存储能力的主要手段包括:数据库主从复制、数据库分片和 NoSQL 数据库。

数据库主从复制

MySQL 的主从复制,顾名思义,就是将 MySQL 主数据库中的数据复制到从数据库中去,主要原理是:当应用程序客户端发送一条更新命令到主数据库时,数据库会把这条更新命令同步记录到 binlog 中,然后由另外一个线程从 binlog 中读取日志,通过远程通讯的方式将它复制到从服务器上去,从服务器获得这条更新日志后,将其加入到自己的 Relay log 中,然后由另外一个 SQL 执行线程从 Relay log 中读取这条新的日志,并把它在本地数据库这种重新执行一遍。

image-20200808190141402

以上MySQL 主从复制主要涉及三个线程:binlog 线程、I/O 线程和 SQL 线程。

通过数据库主从复制的方式,我们可以实现数据库的读写分离:写操作访问主数据库,读操作访问从数据库,使数据具有更强大的访问负载能力。实践中,通常采用一主多从的数据复制方案。

为了防止主数据库宕机导致的系统不可用,也会采用主主复制的方案:两台数据库互相备份,任何一台服务器都会将自己的 binlog 复制到另一台机器的 Relay log 中,以保持两台服务器的数据一致。

需要注意的是,不管是主从复制还是主主复制,都无法提升数据库的存储能力,如果数据量太大,数据库无法存在存下这么多数据,通过数据复制无法解决问题。

数据库分片

数据库分片主要解决数据库存储问题,主要的方式有两种:分库和分表。

分表 就是将一张表的数据分成若干片,每一片都包含了数据表中的一部分行记录,然后每一片都存储在不同的服务器上,这样就解决了数据库的存储不足的问题。分片的逻辑可以使用中间件完成,比如 MyCat。

分库 就是将不同的业务划分为不同的 database,或者不同的服务器,相关联的数据库表部署在同一个服务器上。而每一类数据库还可以继续选择使用主从复制或者主主复制。

NoSQL 数据库

NoSQL 数据库与传统的关系型数据库不同,它主要的访问方式不是使用 SQL 访问,而是使用 Key、Value 的方式进行数据访问。NoSQL 数据库主要用来解决大规模分布式数据的存储问题。常用的 NoSQL 数据有 Apache Hbase、Apache Casandra、MongoDB、Redis 等。

分布式存储有一个著名的 CAP 原理:一个提供数据服务的分布式系统无法同时满足数据一致性、可用性、分区耐受性这三个条件。

CAP 原理是说,当网络分区失效发生时,我们要么取消操作,保证数据是一致的,但是系统却不可用;要么继续写入数据,但是数据一致性就得不到保证了。

分布式存储系统通常要保证分区耐受性和可用性,而需要在数据一致性上做一些妥协。

搜索引擎架构

搜索引擎倒排索引

要对海量文档进行快速内容检索,主要使用的是倒排索引技术。

举个例子:

有 2 篇文章:

文章 1:tom, live, guangzhou, i, live, guangzhou

文章2: he, live, shanghai

正常的索引是同过文章号和位置定位单词,如:1 -> 3 -> guangzhou;2 -> 1 -> he

索引经过倒排之后变成如下:

单词 文章号
guangzhou 1
he 2
i 1
live 1,2
shanghai 2
tom 1

这样可以通过搜索关键字快速定位文章。

如果要确定关键词在文章的具体位置,需要对倒排索引改造一下:

单词 文章号[出现频率] 出现位置
guangzhou 1[2] 3,6
he 2[1] 1
i 1[1] 4
live 1[2],2[1] 2,5,2
shanghai 2[1] 3
tom 1[1] 1

这样查找关键字时,就能根据单词快速定位到哪篇文章,以及具体的位置。

虽然搜索引擎利用倒排索引已经可以很快得到搜索结果,但是实践中,搜索引擎应用还会使用缓存对搜索结果进行加速,将整个搜索结果直接放入缓存中,以减少倒排索引的访问压力,以及不必要的集合计算。

搜索引擎结果排序

搜索引擎要将用户想要的搜索结果排在前面,就需要将搜索结果进行排序。

对网页的搜索结果可以使用 PageRank 算法排序。

对站内搜索可以使用文章点赞数排序或者根据词频 TF 进行排序。词频的计算公式为: TF = 某个词在该文档中出现的次数 / 该文档总词数

微服务架构

微服务是从单体架构演化而来。单体架构,就是所有的模块全部打包在一个大的应用程序中,部署在一个集群上。

而微服务架构则是从这个大的应用中拆分出一些模块,这些模块独立部署在一些相对较小的服务器集群上,而应用通过远程调用的方式依赖这些独立部署的模块,完成业务处理。这些独立的模块被称为微服务。

独立部署的微服务使模块之间的依赖关系更加清晰,也更加隔离,使系统易于开发、维护,也代表了正确的技术方向。

单体架构的困难和挑战

微服务框架原理

微服务框架从 SOA 架构方案演化而来,框架中包含服务提供者,服务调用者,服务注册中心。服务提供者向注册中心注册自己的服务,而服务调用者去注册中心发现服务,然后根据注册中心提供的访问接口和路径对服务发起请求,由服务提供者完成请求,返回结果给调用者。

服务提供者在微服务容器中启动,通过服务管理容器向服务中心注册时,声明服务提供者提供的接口参数和规范,并且注册自己的服务器 IP 和端口。

服务消费者如果想要调用某个服务,只需要依赖服务提供者接口进行编程。请求接口时,会根据客户端或服务端某种负载均衡策略选择一个服务提供者服务器,通过远程通信协议发送具体的服务请求。

高性能架构

性能指标

性能测试

通过多线程模拟用户请求对系统施加高并发的访问压力,得到以上性能指标。整个测试过程又细分为性能测试、负载测试、压力测试。

性能优化

性能优化的一般步骤是:首先进行性能测试,根据测试结果进行性能分析,寻找性能瓶颈,然后针对瓶颈优化,优化完成后继续进行性能测试,观察性能是否有所改善。然后重复此过程。

高可用架构

高可用的度量

业界通常用多少个 9 来说明互联网应用的可用性。比如淘宝的可用性是 4 个 9,表示淘宝的服务 99.99% 可用。也就是在所有的运行时间里只有 0.01% 不可用,一年大概有 53 分钟不可用。

可用性 = (1 - 年度不可用时间 / 年度总时间) * 100%

高可用架构

高可用架构就是要在各种故障情况下,保证系统依然可以提供服务,具体包含以下几种方案:

安全性架构

数据加解密

通过对用户密码,身份证号,银行卡号等敏感数据信息加密,保护数据安全。

软件开发过程中,主要使用的加密方法有三种:单向散列加密、对称加密、非对称加密。

对称加密计算消耗少,加密性能好,但是不安全,一旦被截取了加密密钥,就可以对密文进行解密。非对称加密需要消耗的计算资源比较多,效率也比较差,但是使用相对比较安全。

HTTPS 使用的是对称加密和非对称加密结合的方式。HTTPS 并不是每次请求响应都用非对称加密,而是先利用非对称加密,在客户端和服务器之间交换一个对称密钥,然后每次请求响应都用对称加密。

使用非对称加密还可以实现数字签名。用数字签名的时候是反过来的,自己用私钥进行加密,得到一个密文,但是其他人可以使用公钥将密文解开,因为私钥只有自己才拥有的,所以等同于签名。一段经过自己私钥加密后的文本,文本内容就等于是自己签名认证过的。

HTTP攻击与防护

HTTP 攻击中最常见的是 SQL 注入和 XSS 攻击。

SQL 注入是利用拼接字符串的方法,向服务器提交恶意 SQL。预防 SQL 注入最有效的方法是 SQL 预编译。

XSS 攻击即跨站点脚本攻击,攻击者构造恶意的浏览器脚本文件,使其在其他用户的浏览器运行,进而达到攻击的目的。XSS 攻击防御的手段是消毒,检查用户提交的请求是否含有可执行的脚本,在请求入口对含有 HTML 的符号进行转义。

web 应用防火墙,是在服务器的请求入口处设置一个请求过滤器,统一将危险的请求进行拦截、隔离。

大数据架构

大数据技术其实是分布式技术在数据处理领域的创新性应用,本质和分布式技术思路一脉相承:用更多的计算机组成一个集群,提供更多的计算资源,满足更大的计算压力要求。大数据技术解决的核心问题是大规模数据的计算和存储问题。

分布式文件存储系统 HDFS 架构

HDFS 可以将千台服务器组成一个统一的文件存储系统,其中 NameNode 服务器充当文件控制块的角色,进行文件元数据管理,即记录文件名,访问权限,数据存储地址等信息,而真正的文件数据则存储在 DataNode 服务器上。

DataNode 以块为单位存储数据,所有的块信息,如ID、块所在的服务器IP地址等,都记录在 NameNode 上。一个大文件可以分成多个数据块,上传到多个 DataNode 服务器节点上,因此理论上,分布式文件存储系统可以存储无限大的数据。

此外,HDFS 为了保证数据不会因硬盘损坏导致数据丢失,会将每个 DataNode 进行复制,存储在多台服务器上。

大数据计算 MapReduce 架构

数据存储在 HDFS 上最终是为了计算,进行数据分析或者机器学习。但是像传统的应用程序那样,把 HDFS 当做普通文件读取数据,进行计算,那么对于 PB 级别的数据,计算将无法进行。

MapReduce 的核心思想是对数据进行分片计算。因为数据是以块为单位存储在多台机器上,那么可以在这些服务器上对每个数据块同时进行分布式计算。MapReduce 分为两个部分,一个是 map 过程,每个服务器上会启动多个 map 进程,map 优先对本地数据进行计算,计算后输出一个 key、value 集合。另一个是 reduce 过程,MapReduce 在每个服务器上启动多个 reduce 过程,然后对所有 map 输出的 key、value 集合进行 shuffle 操作,针对相同 key 发送到同一个 reduce 进程,在 reduce 完成整合操作。

大数据仓库 Hive 架构

数据分析传统上主要使用 SQL 进行分析,如果能根据 SQL 自动生成 MapReduce,那么可以极大降低大数据技术在数据分析领域的应用门槛。Hive 就是将 SQL 转换成 MapReduce 的工具。

快速大数据计算 Spark 架构

MapReduce 主要使用硬盘存储计算过程中的数据,这样其实性能比较差,而且,MapReduce 只能使用 map 和 reduce 函数进行编程,虽然能够完成各种大数据计算,但是编程比较复杂。

Spark 在 MapReduce 上进行改进,主要使用了内存进行中间计算数据存储,加快了计算执行时间,在某些情况下,性能可以提升上百倍。Spark 的主要编程模型是RDD,弹性数据集。在 RDD 上定义了许多常见的大数据计算函数,利用这些函数,可以用极少的代码完成较为复杂的大数据计算。

大数据流计算架构

Spark 虽然比 MapReduce 快很多,但是大多数场景下,计算耗时依然是分钟级别的,这种计算一般被称为大数据批处理计算,实际应用中,有些计算需要接近实时计算结果,比如实时对摄像头采集的数据进行监控分析,这就是所谓的大数据流计算。

比较著名的早期流式大数据计算引擎是 Storm,后来 Spark Streaming 也逐渐流行起来。Spark Streaming 架构原理是将实时流入的数据切分成小的一批一批的数据交给 Spark 执行。由于数据量比较小,Spark Steaming 又常驻系统,不需要重新启动,因此可以毫秒级完成计算。

最近几年比较流行的大数据引擎 Flink,其架构原理和 Spark Steaming 类似。

AI 与互联网架构

智能推荐算法

大数据平台提供了数据的获取、存储、计算、应用的技术方案,而真正挖掘出这些数据之间的关系,让数据发挥价值的是各种机器学习算法。而最常见、应用最广的大概就是智能推荐算法了。

智能推荐大概有以下几类:

智能推荐算法需要不断优化,不断收集用户反馈,不断迭代算法和升级数据,才能得到比较好的推荐效果。

区块链技术架构

比特币与区块链原理

2008 年 11 月,由中本聪设计、开发的比特币正式上线。比特币是一种加密数字货币。而成为货币首先要解决的问题就是交易记账,比特币构建的是一个 无中心、去信任的分布式记账系统

交易

在比特币的交易系统中,所有的交易的参与者都有一个 钱包地址,这个钱包地址正是 非对称加密算法公钥。进行交易的时候,交易的发起者需要将交易的数字货币(一个哈希值)和交易的接受方用自己的钱包私钥进行签名。记账者可以使用发起者公钥对签名进行验证,保证交易是真正发起者提交的,而不是其他人伪造的交易。

区块链

交易签名只能保证交易不是他人伪造的,却不能阻止交易的发起人自己进行多重交易,即将一个比特币同时转账给两个人。

比特币的解决方案是,记账者在收到若干交易后,会将这些交易打包在一起,形成一个区块。区块必须按照严格的顺序产生,因此最新的一个区块的记账者可以根据区块顺序得到此前所有的区块,这样就可以检查所有的区块中的交易数据。

如果保证区块的严格顺序?比特币的做法是,在每个区块的头部记录他的前一个区块,即前驱区块的 hash 值,这样所有的区块就构成了一个链,形成一个单向链表,这样一来就保证了严格的顺序。

通过 hash 值连起来的区块就是 区块链

工作量证明

如果有记账者试图修改历史交易的某笔记录,必然需要改变这个交易所在区块的 hash 值,这样会导致下一个区块的头部记录的前驱区块的 hash 值与它不匹配,因此篡改交易的记账者必须修改下一个区块的 hash 值,直到修改完整个链条的 hash 值。

为了防止有人去重算整个区块链的 hash 值,比特币的解决方案是工作量证明。即比特币要求算出的 hash 值必须有一定难度,需要消耗巨大的算力和电力。在这样巨大的资源消耗要求下,重算所有的 hash 值几乎是不可能的,从而使得比特币的历史交易记录几乎难以被篡改。

挖矿

虽然比特币记账需要消耗巨大的计算资源,但是比特币系统会为每个计算出区块 hash 的记账者赠送一定数量的比特币,这实际上就是比特币的发行机制。由于计算出 hash 值就可以得到比特币,计算 hash 值的过程也被形象地称作“挖矿”。

联盟链和区块链的企业级应用

联盟链是由多个组织共同发起,只有组织成员才能访问的区块链,因此有时候也被称为 许可型区块链。联盟链可以应用于跨国间银行转账,去中心化的互联网分销模式等等。

区块链的出现,使得低成本、去信任的跨组织合作成为可能,将重构组织间的关系,包括企业间的关系,包括政府与企业之间的关系,还有政府部门之间的关系。是一种生产关系革命。

 


关注微信公众账号「曹当家的」,订阅最新文章推送

Table of Contents