0%

开发原理|后端架构基础知识

Image

抓住9月的尾巴,终于整理完毕🥳。

互联网架构演化进程

img

分布式

参考资料:https://blog.csdn.net/wangshihuidev/article/details/98896812

1.需求

但访问系统的用户越来越多,系统资源就需要更多的CPU内存去处理请求,需要更大的网络带宽去处理数据的传输,需要更多磁盘空间存储数据,有以下两种方法:垂直伸缩 水平伸缩

2.垂直伸缩

(1)垂直伸缩简介

垂直伸缩的核心思想是:提升单台服务器计算处理的性能(个人主义)

但是单台服务器的计算处理能力是有限的,而且也会严重受到计算机硬件水平的制约,即便用更快频率的CPU,更快的网卡,塞更多的磁盘也总会有天花板

(2)垂直伸缩系统优化

增加CPU后,要进行以下调整以保证计算能力有效增长:

  • 开启多线程
  • 调大并发量
  • 防止锁竞争

增加内存后后,要进行以下调整以保证服务能力有效增长:

  • 调大堆参数
  • 调大本地缓存

除此之外对数据库的优化如分表等操作也是一种垂直伸缩

在这里插入图片描述

3.水平伸缩

(1)水平伸缩简介

水平伸缩的核心思想是:用多台服务器合并进行计算处理(集体主义)

通过多台服务器构成分布式集群从而提升系统的整体处理能力

(2)水平伸缩系统优化

在这里插入图片描述

4.方案比较

在这里插入图片描述

5.分布式架构

将单体服务进行以下改造,可获得一个简单的高性能系统:

  • 数据库与应用分离:系统程序,文件服务,数据库服务部署在不同服务器
  • 加一个缓存:将应用程序需要的热点数据存在缓冲中,而不是每一次都要去连接数据库
  • 多台服务器构成单一服务的集群:如数据库集群,应用程序集群,缓存服务集群

img

缓存架构

1.计算机中的缓存

  • CPU和主内存之间有缓存
  • 内存和硬盘之间也有磁盘缓存
  • 在硬盘与网络之间也有某种意义上的缓存

缓存的关键指标是缓存命中率,其有以下影响要素:

  • 缓存键集合大小(键数越少,缓存效率越高)
  • 缓存可使用内存空间(缓存对象越多,缓存命中率越高)
  • 缓存对象生存时间(缓存时间越长,缓存对象被重用的可能性越高)

缓存分为两种:一种是通读缓存,一种是旁路缓存

2.通读缓存

(1)通读缓存简介

img

通读缓存:客户端请求通读缓存服务器,若缓存命中则直接返回数据,否则由通读缓存服务器代理请求到原始服务器获得数据

客户端连接的是通读缓存,而不是生成相应的原始服务器,客户端只能通过通读缓存进行代理去访问原始服务器

比较常见的通读缓存有:Nginx反向代理缓存,fastly缓存

(2)Nginx反向代理缓存

Nginx不仅能作为Web Server,还具有反向代理、负载均衡和缓存的功能

img

(3)fastly缓存
什麼是fastly

fastly即内容分发网络,它们是一组分布在不同地理位置的服务器。其利用遍布全球各地数据中心的缓存,使用户可以通过最近地点的fastly服务器获得网络内容

可以将fastly理解为遍布大街小巷的ATM机,人们不用去银行排长队而是去离自己最近的ATM去取现金

3.旁路缓存

(1)旁路缓存简介

img

旁路缓存:客户端向访问旁路缓存是否有命中的数据,若没有就自己去访问原始服务器获得数据

旁路缓存通常是一个独立的键值对存储(key-value)

比较常见的旁路缓存:Redis

(2)Redis缓存

参考资料:https://zhuanlan.zhihu.com/p/315103766

img

  • 缓存命中:Redis中有相应数据,直接返回数据
  • 缓存缺失:Redis中没有保存相应数据,需要请求数据库服务器,而且要将缺失数据写入Redis(缓存更新)

4.缓存优缺点

(1)缓存的好处
  • 缓存数据存储在内存中,相比硬盘和网络获取效率更高,响应时间更快,性能更好
  • 降低服务器的负载能力
  • 缓存通常会记录计算结果,缓存也减少CPU的计算消耗加快处理速度
(2)缓存的缺点
  • 数据库中的源数据被修改,缓存中的数据变成脏数据
  • 每次写入缓存数据都要标记失效时间

5.缓存的合理使用

(1)缓存关注要点
  • 关注频繁修改的数据,如果一个数据经常被修改,那么使用缓存的价值不大
  • 缓存要有热点,存储空间有限,要选取热门的被访问数据放在缓存
  • 注意缓存雪崩,缓存击穿与缓存穿透
  • 关注缓存的数据一致性
(2)缓存异常与解决方案

参考资料:https://www.sohu.com/a/473442725_115128

img

(3)缓存雪崩

img

缓存雪崩:由于大量缓存数据过期或redis故障,大量用户请求无法在redis中处理而是全部打向了数据库,数据库被乱棒打死后(宕机),会引发一系列连锁反应,造成系统崩溃,故称为雪崩

大量缓存数据过期应对方法

  • 均匀设置过期时间:避免将大量数据设为同一个过期时间,可以给过期时间加上一个随机数
  • 互斥锁:如果发现访问的数据不在 Redis 里,就加个互斥锁,保证同一时间内只有一个请求来更新缓存(互斥锁最好设置超时时间,不然如果拿到锁的请求发生阻塞,一直不释放锁,其他请求也拿不到锁,整个系统就无响应了)
  • 双 key 策略:我们对缓存数据可以使用两个 key,一个是 主 key,会设置过期时间,一个是 备 key,不会设置过期,相当于给缓存数据做了个副本(副本的副本)
  • 后台更新缓存:让缓存“永久有效”,并将更新缓存的工作交由后台线程定时更新(某些缓存会在系统内存紧张的时候被淘汰,所以不存在真正的永久有效,当业务线程发现缓存数据失效了,过消息队列发送一条消息通知后台线程更新缓存)
  • 通过后台更新缓存进行缓存预热,即提取把数据缓存起来而不是等待用户访问才来触发缓存构建

Redis 故障宕机应对方法

  • 服务熔断:服务熔断机制, 暂停业务应用对缓存服务的访问,直接返回错误
  • 请求限流机制:启用 请求限流机制, 只将少部分请求发送到数据库进行处理,再多的请求就在入口直接拒绝服务
  • 构建 Redis 缓存高可靠集群:通过 主从节点的方式构建 Redis 缓存高可靠集群,如果 Redis 缓存的主节点故障宕机,从节点可以切换成为主节点,继续提供缓存服务
(4)缓存击穿
img

缓存击穿:如果缓存中的 某个热点数据过期了,此时大量的请求访问了该热点数据,就无法从缓存中读取,直接访问数据库,数据库很容易就被高并发的请求冲垮,这就是 缓存击穿的问题

缓存击穿应对方法(也是前面提到的两种方法)

  • 互斥锁:保证同一时间只有一个业务线程更新缓存,未能获取互斥锁的请求,要么等待锁释放后重新读取缓存,要么就返回空值或者默认值
  • 后台更新缓存:不给热点数据设置过期时间,由后台异步更新缓存,或者在热点数据准备要过期前,提前通知后台线程更新缓存以及重新设置过期时间
(5)缓存穿透
img

缓存穿透:用户访问的数据即不在缓存中,也不在数据库中,有以下两种诱因:

  • 业务误操作,缓存中的数据和数据库中的数据都被误删除了
  • 黑客恶意攻击,故意大量访问某些读取不存在数据的业务

缓存传递应对方法

  • 非法请求的限制:在API网关处筛选请求,如果判断出是恶意请求就直接返回错误,避免进一步访问缓存和数据库
  • 缓存空值或者默认值:针对查询的数据,在缓存中设置一个空值或者默认值,这样后续请求就可以从缓存中读取到空值或者默认值,返回给应用,而不会继续查询数据库
  • 布隆过滤器:在写入数据数据时使用布隆过滤器做个标记,通过查询布隆过滤器可以快速判断数据是否存在,避免通过查询数据库来判断数据是否存在(Redis本身也是支持布隆过滤器的)
(6)缓存数据一致性

参考资料:https://blog.51cto.com/u_14983647/2548012

缓存与数据库存在一致性问题的根本原因是:多个线程同时操作相同数据

的情况下表现为两个同时查询缓存的线程同时不命中,在写的情况下表现为多个线程并发回写缓存的值不同,发生缓存和数据库不一致

有以下几种不同的写入策略

  • 先更新数据库,再更新缓存(普通低并发)

    8 张图带你分析 Redis 与 MySQL 数据一致性问题_mysql_05

    更新mysql成功,更新redis缓存失败会造成数据不一致

  • 先删除缓存,再写入数据库(低并发优化)

    8 张图带你分析 Redis 与 MySQL 数据一致性问题_redis_06

    先将缓存删除,下个进程再请求更新后的数据库来更新缓存,这种方案只适合低并发中使用,在高并发中一旦下一个进程在前一个进程更新数据库前就去更新缓存,那缓存中放入的依旧是旧数据

    8 张图带你分析 Redis 与 MySQL 数据一致性问题_数据一致性_07

  • 延时双删策略

8 张图带你分析 Redis 与 MySQL 数据一致性问题_数据一致性_08

先将缓存删除,在更新数据库后再次删除缓存,可以很快解决不一致的问题,但是仍然有第二次删除错误,多写多读高并发情况下对 MySQL访问的压力(这时候其实可以加入消息队列异步解决,后面会讲到异步架构

  • 直接操作缓存,定期写入sql(适合高并发)
8 张图带你分析 Redis 与 MySQL 数据一致性问题_redis_09

在高并发的情况下,最佳的方法是直接更新缓存,将缓存定期更新到数据库

异步架构

1.异步架构简介

(1)需求

缓存实际上更多解决了的问题,因为缓存很难保证数据的持久性和一致性,所以我们通常不会将数据直接写入缓存中,而是写入 RDBMAS 等数据中,这时候我们使用消息队列异步架构提升系统的的性能

(2)同步架构与异步架构

同步架构:应用程序调用服务时,阻塞进程等待服务完成,直到返回服务结果才会继续执行

img

这样的阻塞会带来以下问题:

  • 不能释放占用的系统资源,导致系统资源不足,影响系统性能
  • 无法快速给用户响应结果

异步架构:应用程序将调用信息发给消息队列就直接返回,应用程序收到返回后继续执行,快速响应用户释放资源。有专门的消费队列程序从中消息队列取出消息发送给邮箱服务器最后将返回结果通知消息队列

img

2.消息队列

(1)消息队列模型

img

消息队列模型有三个角色:

  • 生产者:产生数据封装发给消息队列
  • 消息队列:存储接收到的消息
  • 消费者:从消息队列中取出数据,消费数据
(2)消费模式

参考资料:https://segmentfault.com/a/1190000019411260

  • 点对点模式:不可重复消费,Queue支持存在多个消费者,但是对一个消息而言,只会有一个消费者可以消费

    img
  • 订阅模式:可以重复消费,发布到topic的消息会被所有订阅者消费

    img
(3)消息队列的优点
  • 实现异步处理,提升处理性能:不再阻塞客户端程序,提高客户端程序的处理性能
  • 可以让系统获得更好的伸缩性:耗时的任务可以通过分布式消息队列,向多台消费者服务器并行发送消息,然后在很多台消费者服务器上并行处理消息,也就是说可以在多台物理服务器上运行消费者
  • 可以平衡流量峰值,削峰填谷:通过消息队列的缓冲,将访问的高峰消掉,而将访问的低谷填平,使系统处在一个最佳的处理状态之下,不会对系统的负载产生太大的冲击
  • 失败隔离和自我修复:生产者不直接依赖消费者,所以分布式消息队列可以将消费者系统产生的错误异常与生产者系统隔离开来,生产者不受消费者失败的影响
  • 生产者和消费者的代码实现解耦合:多个生产者发布消息,多个消费者处理消息,共同完成完整的业务处理逻辑,但是它们的不需要直接的交互调用,没有代码的依赖耦合

3.异步架构总结

img

负载均衡

负载均衡是一种将请求分发到不同服务器以分散高并发计算压力的策略

1.负载均衡方案

参考资料:https://segmentfault.com/a/1190000022328323

(1)HTTP重定向负载均衡

img

用户请求到HTTP重定向负载均衡服务器,用一套负载均衡算法计算到后端服务器的地址,然后将新的地址给用户浏览器,浏览器收到重定向响应后发送请求到新的应用服务器从而实现负载均衡

缺点:

  • 加大请求的工作量,用户端要进行两次请求
  • 集群IP地址需要暴露在公网,安全性低
(2)DNS负载均衡

img

用户通过浏览器发起HTTP请求的时候,DNS 通过对域名进行解析得到 IP 地址,用户委托协议栈的 IP 地址建立HTTP 连接访问真正的服务器,不同的用户进行域名解析将会获取不同的IP地址从而实现负载均衡

  • 通过 DNS 解析获取负载均衡集群某台服务器的地址
  • 不用每次都请求负载的ip,可以缓存起来,重复使用,提高性能
  • DNS不用暴露实际计算的服务器IP(不是采用重定向的方式暴露在浏览器,而且做了二次负载均衡,内网的IP不会暴露出来)
(3)反向代理负载均衡

img

客户端请求反向代理服务器,服务器根据算法得到负载的IP,由反向代理服务器代理客户端请求内网的应用服务器集群,最后将结果返回给客户端

常用的反向代理有:nignx,apache

基于http层做的负载均衡,是一个比较重的协议,效率略低,一般适用于比较小的集群,10+规模

(4)IP负载均衡

img

客户端请求负载均衡服务器,服务器修改目标IP为内网机器的IP,最后返回响应数据并修改响应地址为公网ip

对网络层的IP地址进行替换,不需要在http层工作,直接在操作系统内核的IP数据包中替换地址。效率比基于HTTP层的反向代理高

请求和响应度需要经过负载均衡服务器进行ip层替换,响应数据会成为后期的瓶颈

(5)数据链路负载均衡

img

客户端请求负载均衡服务器,负载均衡服务器替换mac地址应用服务器,ip为负载均衡服务器ip,计算服务器直接响应数据到客户端;

解决响应数据体量过大效率低的问题,通过修改数据链路层的mac地址,ip使用的是虚拟IP,来实现负载均衡

该负载均衡方式吞吐量高,适合大型互联网公司使用

2.负载均衡算法

参考资料:

负载均衡算法介绍

负载均衡算法实现

(1)轮询访问

将请求按照顺序轮流的分配到服务器上,均衡的对待每一台后端的服务器,不关心服务器的的连接数和负载情况,可能导致性能高的服务器无法完全发挥实力,性能低的服务器无法承载过大的负载

如下图:来自客户端的6个请求被均匀分发给两台应用服务器

img

(2)随机访问

根据服务器列表的大小来随机获取其中的一台来访问,随着调用量的增大,实际效果越来越近似于平均分配到没一台服务器,和轮询的效果类似,比较适合服务器性能差不多的场景

img

(3)加权轮询

加权轮询是在轮询的基础上,根据服务器的性能差异,为服务器赋予一定的权值,性能高的服务器分配更高的权值

如下图:来自客户端的请求按5:1的权重分发给两台应用服务器

img

(4)最少连接

由于每个请求的连接时间不一样,使用轮询或者加权轮询算法的话,可能会让一台服务器当前连接数过大,而另一台服务器的连接过小,造成负载不均衡,这时我们可以采用最少连接算法:将请求发送给当前最少连接数的服务器上

如下图:当前服务器1当前连接数最小,那么最新的请求将会发给服务器1

img

在最少连接的基础上,也有加权最少连接算法:根据服务器的性能为每台服务器分配权重以计算出每台服务器能处理的连接数

(5)源地址哈希法

源地址哈希通过对客户端 IP 计算哈希值之后,再对服务器数量取模得到目标服务器的序号。可以保证同一 IP 的客户端的请求会转发到同一台服务器上,用来实现会话粘滞(让用户在一次会话周期内的所有请求始终转发到一台特定的后端服务器上,这种机制也称为粘滞会话)img

数据存储

参考资料:https://www.cnblogs.com/linuxk/p/9366838.html

1.数据库主从复制

(1)一主多重

为了降低数据库的压力,数据库服务器常常使用一主多重结构,对于容灾、可扩展性和高可用性,都是有好处,一主多重结构主要依赖于主从复制读写分离

image-20210929145219480
(2)主从复制
img

主从复制即要让主库和从库的数据一致,其实现步骤为:

  • 从库IO线程通过主库创建的授权用户连接上master
  • 应用程序发送SQL更新命令到主库,主库将该命令同步记录到Binlog中
  • 主库IO线程对从库IO线程的请求进行验证后,将命令和下一个指定更新的位置(position)发送到从库
  • 从库接收更新日志后加入到自己的RelayLog文件末端,并将读取到的主库Binlog文件名和position记录到master.info文件
  • 从库SQL线程检测到RelayLog中的内容有更新,会立刻解析内容并执行解析后的SQL语句
(3)读写分离

主从复制需要时间,向主库写入数据后,如果直接从从库读取,很可能读不到最新值,所以读写分离主要用于对实时性要求不高的业务场景

  • 数据库主机负责读写操作,从机只负责读操作
  • 数据库主机通过复制将数据同步到从机,每台数据库服务器都存储了所有的业务数据
  • 应用服务器将写操作发给数据库主机,将读操作发给数据库从机

2.数据库分片

参考资料https://segmentfault.com/a/1190000015627336

(1)分片简介

分片是解决数据库存储容量限制的直接途径。分片包括垂直分片水平分片两种方式

(2)垂直分片

垂直分片又叫纵向分割,把原有数据库切分成按业务多个数据库。垂直拆分后业务清晰,拆分规则明确,系统之间容易整合与扩展

图片描述

(3)水平分片

水平分片又叫横向分割,即以表中的数据行记录为单位,把原有逻辑数据库切分成多个物理数据库分片,表数据记录分布存储在各个分片上

图片描述

常用水平分片的规则:哈希取模算法H(Key(OrderId)) = Hash(Key(OrderId))%N,将键值相同的行放在一个数据库中

搜索引擎

参考资料:https://leetcode-cn.com/circle/article/7qT9CA/

1.搜索引擎架构

img

2.搜索引擎工作原理分析

(1)搜集

网络爬虫的起点是一组优质的种子网页的链接(新浪主页,腾讯主页等),通过广度优先遍历不断遍历这些网页,爬取网页内容,提取其中的链接,并又将这些链接加入待爬队列中,重复上面操作(递归了属于是)

待爬url队列:

待爬取的url放入Redis中,保证高性能。Redis开启持久化功能,支持断点续爬,即便Redis寄了,也可以从上一个待爬url重新开始爬

url判重:

为了避免网页被重复爬取,我们使用布隆过滤器(上面应对缓存穿透也提到过,可以快速判断数据是否存在数据库中)进行去重操作

布隆过滤器由「初始值都为 0 的位图数组」和「 N 个哈希函数」两部分组成,将数据(url)经过多个哈希函数处理用位图数组表示,查询url是否被爬过时,只要查到位图数组对应的值是否全为1,只要有一个0,就认为该url未被爬过

img

布隆过滤器由于是基于哈希函数实现查找的,高效查找的同时存在哈希冲突的可能性,查询布隆过滤器说数据存在,并不一定证明该数据被处理过,但是查询到数据不存在,这个数据一定是没有处理过的,针对这种情况我们可以通过调整布隆过滤器的哈希函数或其底层的位图大小来尽可能地降低误判的概率,至于发生误判的少量url,let it go!(就是这么粗暴)

网页存储文件:

网页信息存储文件

img

网页id-url对应文件

img

(2)预处理

参考资料:字符串匹配算法

爬取完一个网页的html代码后,需要将<script>,<style>,<option>这些无用的标签及标签包含的内容给去掉,然后把其他标签也去掉但是保留里面的内容,最后得到纯文本(内容包含用户要搜索的关键词),所以我们需要使用字符串匹配算法对html内容进行预处理,对于字符串匹配算法这里列个清单自己去查罢 :(

单模式串匹配算法:

  • BF算法
  • RK算法
  • BM算法
  • KMP算法

上面的查询算法查询单个字符串效率确实不错,但是我们要一次性查出<script>,<style>,<option>这些字段串,多模式串匹配算法更加高效

多模式串匹配算法:

  • AC自动机
(3)分词并创建倒排索引

分词:

预处理获得纯文本后,要对文本内容进行分词即把一段文本切分为一个个词。英语的分词比较简单,每一个单词基本都是用空格隔开的,中文的分词比较难分割,一般是根据现成的词库进行匹配,有兴趣可以研究一下github上有名的jieba分词开源库

组织:

分词后,将单词与网页信息存储文件(文档)对应起来组成以下矩阵

img

倒排索引:

再按照单词-文档组织起来就叫做倒排索引

img

这样我们只要搜索单词,就能找到单词对应的文档id,从而定位url(上面分词+倒排索引的处理流程,就是 ElasticSearch 搜索引擎干的事,也是 ES 能达到毫秒级响应的关键)

排序:

根据词语我们获得了一组网页的id,那哪些网页应该排在前面呢?

Google使用了一种叫做”PageRank“的算法,通过计算每个网页的权重,并按照权重排序。它以网页之间的超链接个数和质量作为主要因素粗略地分析网页重要性以便对其进行打分。

在PageRank中,如果网页A包含网页B说明A认可了B,即为页面B投了一票

img

如上图:ABCD 初始值都为1,然后根据关系计算权重。比如此时B包含了AD两个网页,那么权重1被分为两个1/2分别给A和D,此时A包含BCD,那么此时A页面新的权重为1/2 + 1/3 + 1 = 11/6

此外还有通过词频TF进行排序

img

(4)查询过程
  • 用户输入搜索内容,首先经过分词器处理
  • 按获得的词语去倒排索引里查询相应文档
  • 得到网页id后,去网页存储文件中提取出网页的链接和内容,再按权重从大到小排序即可
(5)寻找热门搜索字符串

现在的搜索引擎还有一项功能:搜索提示词,其主要利用Trie树来实现(字典树,前缀树,单词查询树),如下图

img

这颗多叉树表示了关键字集合 ["to","tea","ted","ten","a","i","in", "inn"]

一般搜索引擎会维护一个词库,假设这个词库由所有搜索次数大于某个阈值(如 1000)的字符串组成,我们就可以用这个词库构建一颗 Trie 树,这样当用户输入字母的时候,就可以以这个字母作为前缀去 Trie 树中查找

哪如何获得热门的搜索提示词放在最前面呢?

通常在实现Trie树的时候,会在节点结构中设置一个标志,用来标记该结点处是否构成一个单词,该标记也可以设置为搜索次数

依次遍历 Trie 树的节点,将节点(字符串+次数)传给一个小顶堆,根据搜索次数不断调整小顶堆,这样遍历完 Trie 树的节点后,小顶堆里的 10 个节点即是最热门的搜索字符

微服务

1.软件架构

参考资料:四种软件架构

(1)单体架构

image-20210912153357714

典型的三级架构,前端(Web/手机端)+中间业务逻辑层+数据库层

单体架构出现的问题:

  • 代码分支管理困难
  • 新增功能麻烦
  • 容易耗尽数据库连接
(2)分布式架构

img

将一个大的系统划分为多个业务模块,业务模块分别部署在不同的服务器上,各个业务模块之间通过接口进行数据交互。数据库也大量采用分布式数据库,通过LVS/Nginx代理应用,将用户请求均衡的负载到不同的服务器上

(3)微服务架构

img

将系统拆分成很多小应用(微服务),微服务可以部署在不同的服务器上,也可以部署在相同的服务器不同的容器上。当应用的故障不会影响到其他应用,单应用的负载也不会影响到其他应用

微服务的特点:

  • 大应用拆分为小模块
  • 小模块不属于集群中
  • 通过远程调用的方式依赖各个独立的模块完成业务的处理

这些小模块就是一个微服务了

2.微服务技术选型

参考资料:2020微服务架构技术选型

img

微服务的内容有点庞大😰,各种技术选型方案也很多,可以查看我的前一篇博文(SpringCloud + Netflix OSS)做一个了解:Java|SpringCloud + Netflix OSS Demo

高可用

1.高可用简介

系统高可用意味着在一台服务器挂掉的情况下,系统仍然无中断地执行其功能的能力

2.高可用策略

(1)冗余备份

冗余备份是指复制关键部件或者系统的主要功能,当意外发生时,可以快速安全地恢复原有的系统,在一定的范围内保障业务的正常运行

(2)负载均衡

负载均衡也可以保证高可用,使用多台服务器分担一台服务器的压力,负载均衡服务器一旦发现集群中某台服务器出现问题,立刻停止对其的请求分发

img

(3)限流降级

限流是对部分请求进行丢弃处理,保证大部分的用户可以正常的请求完成任务

降级即可以屏蔽部分当前看来不是很有用的任务

(5)异地多活

参考资料:饿了么异地多活技术实现

大型的系统多会在各个地方部署数据中心,采用异地多活的多机房策略

异地多活下,各个地域独立隔离,业务流量可以不均等的分配到各个地域和可用区里面

img

  • gzs是一个全局的(所有机房都可以访问的)服务,保存和推送sharding信息。
  • API router复制路由外网流量
  • SOAProxy实现跨机房调用
  • 强一致数据库 / 数据库层的拦截 由DAL实现(图上没展示)
  • DRC实现Mqsql的双向复制

安全性

1.数据加密

参考资料:对称加密、单向加密和非对称加密

(1)单向散列加密
img

单向加密有以下特征:

  • 输入一样,输出必然相同
  • 雪崩效应,输入的微小改变,将会引起结果的巨大变化
  • 定长输出,无论原始数据多大,结果大小都是相同的
  • 不可逆,无法根据特征码还原原来的数据

常用的单向加密算法有:MD5,SHA,CRC

单向加密通常应用在用户密码加密中,经过加密后的密码存储在数据库中,即便被脱库了也无法解密出密码(鉴于有些用户会用一些弱密码,容易被彩虹表暴杀,索引单向加密常常也要加一点盐)

(2)对称加密

img

采用单钥密码的加密方法,同一个密钥可以同时用来加密和解密

对称加密有以下特点:

  • 加密方和解密方使用同一个密钥
  • 加密解密的速度比较快,适合数据比较长时的使用
  • 密钥传输的过程不安全,且容易被破解,密钥管理也比较麻烦

常用的对称加密算法有:DES,3DES,AES,Blowfish

(3)非对称加密

非对称密钥加密也称为公钥加密,由一对公钥和私钥组成。公钥是从私钥提取出来的

可以用公钥加密,再用私钥解密,这种情形一般用于公钥加密;也可以用私钥加密,用公钥解密,常用于数字签名

非对称加密的主要功能就是加密和数字签名

常用的非对称加密:RSA,DSA,ECC

2.HTTP攻击与防护

(1)SQL注入

SQL注入是攻击者在提交请求参数的时候,包含了恶意的SQL脚本

一阶sql注入:

image-20210930172727417

二阶sql注入:

image-20210930172812394

SQL注入防御方法(来源于wiki):

  • 在设计应用程序时,完全使用参数化查询(Parameterized Query)来设计资料访问功能(最有效的方式)
  • 在组合SQL字符串时,先针对所传入的参数加入其他字符(将单引号字符前加上转义字符)。
  • 如果使用PHP开发网页程序的话,需加入转义字符之功能(自动将所有的网页传入参数,将单引号字符前加上转义字符)。
  • 使用php开发,可写入html特殊函数,可正确阻挡XSS攻击。
  • 其他,使用其他更安全的方式连接SQL数据库。例如已修正过SQL注入问题的数据库连接组件,例如ASP.NET的SqlDataSource对象或是 LINQ to SQL。
  • 增强WAF的防御力
(2)XSS攻击

跨站点脚本攻击,攻击者通过构造恶意的浏览器脚本文件注入到网页上,使其在其他用户的浏览器运行进而进行攻击

xss.gif

XSS攻击防御方法:

  • 过滤特殊字符
  • 使用HTTP头指定类型即,可强行指定输出内容为文本或JavaScript脚本(顺便指定了内容编码),而非可以引发攻击的HTML

大数据

参考资料:https://www.hadoopdoc.com/hdfs/hdfs-tutorial

(本文只做简单介绍,大数据的内容也挺多的,有兴趣的可以点入上面链接深入学习)

1.文件存储HDFS架构

(1)HDFS简介

HDFS是一种分布式文件系统,设计用于在商用硬件上商用,管理数以千计的服务器,数以万计的磁盘,将大规模的服务器资源当做一个单一的出承诺函系统进行管理,操作大批量数据就像使用普通文件系统一样

(2)HDFS节点

HDFS架构图

  • Namenode会规范客户端对文件的访问,它维护和管理Slave节点,并把读写任务分配给Slave节点(部署在高可靠的硬件上面)
  • Datanode负责数据存储,它是真正干活的节点,比如响应客户端的数据读写请求,根据Namenode的指令创建和删除block(可以部署在价格低廉的商用机器上)
(3)HDFS进程

HDFS有2个守护进程:

  • Namenode:该进程运行在master节点上,Namenode节点存储元数据,比如文件名,块数量,块副本数量,块的存储位置,以及块ID等
  • Datanode:该进程运行在Slave节点,这些节点是真正对数据进行处理和存储的节点
(4)HDFS数据存储

image-20210930225658950

把文件写入到HDFS的时候,HDFS会把文件分割成很多分片,也就是块(block),文件分割成块之后,HDFS会把他们以分布式方式存储在集群的不多节点上

(5)HDFS机架感知

为了数据容错,NameNode把块的副本放在多个机架上,NameNode尽量会在每个机架都存储至少一个块副本,这样如果其中一个机架发生故障,系统还是可用的

机架感知策略的目的是提升数据可用性、可靠性和网络带宽利用率

(6)HDFS架构

HDFS 1.0 架构图

  • Namenode负责存储元数据而Datanode负责存储实际的数据。执行任何任务,客户端都得和Namenode进行交互,因为Namenode是整个集群的中心

  • Datanode是把数据存储在本地磁盘的,它会定期给Namenode发送心跳信息,以此来表明自己处在工作状态,Datanode还会根据副本因子负责把block拷贝到其他Datanode

2.大数据处理框架

(1)Mapreduce

MapReduce 是 Hadoop 生态下面的计算层,它把任务分割成小任务并分发到集群的机器上并行执行,其分为Map和Reduce两个阶段

img

map和reduce进程在分布式集群中启动过程如下:

img

(2)Hive

Hive 是一个架构在 Hadoop 之上的数据仓库基础工具,它可以处理结构化和半结构化数据,它使得查询和分析存储在 Hadoop 上的数据变得非常方便

有了 Hive,你只要开发简单的 SQL 查询就可以达到 MapReduce 作业同样的查询功能

Hive架构组件

(3)Spark

Spark 是一种高效且多用途的集群计算平台,它提供了一整套开发 API,包括流计算、机器学习或者SQL并支持支持批处理和流处理

Spark已经逐步替代MapReduce、Hive、Storm 等传统的大数据计算框架

spark运行架构及流程

Spark应用程序涉及了driver,master,worker三个节点:

  • Driver:运行Application的main函数并创建SparkContext(运行环境),Driver同时负责将SparkContext关闭
  • Worker:集群中任何一个可以运行spark应用代码的节点
  • Executor:一个应用程序运行的监控和执行容器

参考资料:Apache Flink

Apache Flink 是一个框架和分布式处理引擎,用于在无边界和有边界数据流上进行有状态的计算。Flink 能在所有常见集群环境中运行,并能以内存速度和任意规模进行计算

作为流式数据流执行引擎,针对数据流的分布式计算提供数据分布,数据通信以及容错机制等功能。同时Flink也提供了机器学习库,图计算库等

image-20210930233007590

ontents.com/Autovy/Image/master/img/202109302330786.png)