老齐架构(01 - 10)

老齐架构(01 - 10)

一:MySQL集群模式及其场景

1:单库模式

一个mysql数据库承载所有相关数据。

单库模式的优点和缺点如下:

  • 简单粗暴
  • 适合数量级别千万以下的小型应用
  • 企业网站,创业公司首选
  • 不具备可用性和并发性

2:读写分离的集群模式

在原有的基础上增加中间层,与后端数据集构成读写分离的集群。

整体基础结构:原有的主库派生出字库1,字库2,

利用mysql原有的主从同步机制(即为:binlog日志同步),将主库的数据变化在从库中复现,保证数据同步。

主库一般用于写入处理,从库负责读取。

细节:

  • 如果直接面对主库进行操作无法完成读写分离,需要在前端分配分片中间件,该中间件通过curd请求,来决定由哪个库处理。
  • MHA中间件实现高可用(即:主服务器坏了,MHA中间件可以将某个从表提升为主服务器)。所有节点数据均保持同步。

适用于读多写少,单表不过千万的互联网应用。

在这里插入图片描述
读写分离集群的优缺点如下:

  • 架构复杂度提升,成本提高
  • 所有的节点数据保持同步
  • 适用于读多写少,单表不过千万的互联网应用
  • 配合MHA中间件方案实现高可用

3:分库分表的集群模式

一个mysql数据库撑不住的情况下。将数据库的数据分到不同的节点数据库(即:节点数据库的数据合起来为完整的数据体)。

需要用到中间件进行路由。(对sql进行解析,将请求发到对应的数据库,分发请求的过程叫路由)。

不具备高可用性。

分片算法:

范围法,对分片键依据范围进行划分

  • 范围法结构简单,扩展容易
  • 适合范围索引
  • 数据分布不均匀,局部负载的压力比较大
  • 适用于流水账应用

在这里插入图片描述

Hash法:对分片键取模

  • Hash法分成取模hash和一致性hash
  • 数据分配均衡
  • 节点扩展复杂,数据迁移的难度比较大
  • 建议提前部署足够的节点
  • 适用于预算充足的大型的互联网应用

在这里插入图片描述

分库分表集群模式的优缺点如下:

  • 架构复杂度提升,成本提高
  • 每一个节点的数据都是所有的数据的子集【不具备高可用】
  • 适用于十亿级别数据总量的大型应用【再大的话就需要上大数据了Hbase等】

4:互联网主流的MySQL集群架构

主流架构是读写分离 + 分片法的组合应用

在这里插入图片描述

二:为什么大厂要做数据垂直分表

一张表的字段太多需要做垂直分表。

1:水平分表和垂直分表

水平分表:以行为单位对数据进行拆分(范围法,hash法)。特点:所有的表结构完全相同。用于解决数据量大的存储问题

在这里插入图片描述
垂直分表:将表按列拆分成2张以上的小表,通过主外键关联获取数据。

在这里插入图片描述

# 调整之前
select * from 商品表 where 商品标题="ad钙奶"

# 调整之后
select * from 商品基本信息表 as a, 商品详情信息表 as b 
where a.商品id=b.商品id and a.商品标题='AD钙奶'

2:为什么需要垂直分表

一张表能做的事情,为什么要拆成两张表??

需要了解mysql的InnoDB处理引擎。

  • 行数据称为:row
  • 管理数据基本单位称为页:page;每一页的默认大小:16k
  • 保存页的单位称为区:Extent。
  • 关系:区由连续页组成,页由连续行组成。1024/16=64(即:一个1M的区有64个页)

在这里插入图片描述
InnoDB1.0后新特性,压缩页。

压缩页:对数据底层进行压缩,使实际大小小于逻辑大小。

在跨页检索数据的过程中,压缩和解压缩的效率低。在表设计时,尽可能在页内多存储行数据,减少跨页检索,增加页内检索。

假设1行数据为1K,1页16K,即1页16条数据,1亿的数据需要625万页

垂直分页后,1行数据为64字节(1K=1024字节),即1页256条数据,1亿的数据需要39万页。分页后的数据根据id等关系进行快速提取。

通过将重要字段单独剥离成小表,让每页容纳更多行数据,页减少后,缩小数据扫描范围,达到提高执行效率的目的。

3:总结使用场景

垂直分表条件:

  1. 单表数据达到千万
  2. 字段超20个,且包含vachar,CLOB,BLOB等字段

字段放大小表的依据:

  1. 小表:数据查询、排序时需要的字段;高频访问的小字段

  2. 大表:低频访问字段;大字段

三:多级缓存架构

1:什么是多级缓存架构

在这里插入图片描述

2:客户端缓存

主要对浏览器的静态资源进行缓存

通过在浏览器设置Expires,时间段内以文件形式把图片保存在本地,减少多次请求静态资源带来的带宽损耗(解决并发手段)

下面以百度为例,可以查看到缓存了一些js和图片等信息

在这里插入图片描述

响应头Expires和Cache-control的区别:

  1. 均为通知浏览器进行文件缓存

  2. Expires指在这个时间点缓存就到期

  3. Cache-control指缓存时间有多长

即:你明天还钱给我Expires,时间是一天Cache-control

3:应用级缓存

浏览器只负责读取Expires,Expires在CDN内容分发网络和Nginx进行设置

3.1:CDN内容分发网络

CDN内容分发网络是静态资源分发的主要技术手段,有效解决带宽集中占用以及数据分发问

CDN技术,全称Content Delivery Network,即内容分发网络,是一种构建在数据网络上的分布式的内容分发网。该技术的主要目的是通过在现有的Internet中增加一层新的网络架构,将网站的内容发布到最接近用户的网络“边缘”,从而解决因网络带宽小、用户访问量大、网点分布不均而产生的用户访问网站响应速度慢的问题。以下是对CDN技术的详细介绍:

技术原理:

  • CDN采用流媒体服务器集群技术,克服了单机系统输出带宽及并发能力不足的缺点,极大提升了系统支持的并发流数目,减少了单点失效带来的不良影响。
  • CDN利用全局负载均衡技术将用户的访问指向离用户最近且工作正常的流媒体服务器上,由流媒体服务器直接响应用户的请求。
  • 如果服务器中没有用户要访问的内容,CDN会根据配置自动从原服务器抓取相应的内容并提供给用户。

组成部分:

  • 源站:发布内容的原始站点,所有添加、删除和更改网站的文件操作都在源站上进行。
  • 缓存服务器:直接提供给用户访问的站点资源,由一台或数台服务器组成。当用户发起访问时,智能DNS会将访问请求定位到离用户较近的缓存服务器。
  • 智能DNS:CDN技术的核心,根据用户的来源,将其访问请求指向离用户较近的缓存服务器。
  • 客户端:发起访问的普通用户,一般的访问方式是浏览器。

主要优势:

  • 加速网站加载速度:通过将静态内容缓存在全球各地的服务器上,使用户可以从就近的服务器获取内容,加速网站加载,提升用户体验。
  • 减轻源服务器负担:CDN减少了源服务器的负载压力,将部分请求分发给CDN节点处理,减少了源服务器的响应时间,提升了网站的稳定性和性能。
  • 提高网站的可用性和稳定性:CDN具有负载均衡和故障转移功能,当源服务器发生故障时,CDN可以自动将流量转移到其他可用的节点,保证网站的持续可用性。
  • 改善安全性:CDN提供DDoS攻击防护、SSL加密等安全功能,保护网站免受恶意攻击,提高网站的安全性。
  • 降低网络成本:CDN减少了网络流量的消耗,节约了带宽成本,提高了网络效率和性价比。

适用场景:

  • 高并发访问:CDN可以将内容分发到全球各地的边缘节点,减轻源服务器的负载,提高用户访问速度和网站的可用性。
  • 跨地区访问:CDN可以将内容缓存到离用户最近的边缘节点,减少跨地区访问的延迟,提供更快的响应时间。
  • 视频和音频流媒体:CDN提供高带宽和低延迟的流媒体服务,使用户可以流畅地观看视频和听取音频。
  • 软件和游戏下载:CDN可以加快软件和游戏的下载速度,提供更好的用户体验。
  • 静态内容分发:CDN可以缓存静态内容,使其能够快速加载,减少带宽消耗和源服务器的压力。
  • 动态内容加速:CDN可以与源服务器的缓存服务器进行通信,将动态生成的内容缓存到边缘节点,提高动态内容的传输速度。

综上所述,CDN技术通过其独特的分布式架构和全球部署的节点,为网站和应用提供了高效、稳定、安全的内容分发服务,成为现代互联网架构中不可或缺的一部分。

在这里插入图片描述
在这里插入图片描述

3.2:Nginx缓存管理

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4:服务层缓存

在这里插入图片描述

4.1:进程内缓存

即数据运行时载入程序开辟的缓存中JAVA框架的运用(hibernate,mybatis一二级缓存,springmvc页面缓存)

开源实现:ehcache,Caffeine

这部分的缓存一致性问题一般来说框架已经实现好了,不用管

4.2:进程外缓存

最常见的就是redis数据库这种noSQL对整体架构中的数据进行缓存

在这里插入图片描述

5:总结

  1. 缓存不仅仅是只追加redis就可以了,缓存的引入一定是遵循:先近到远,由快到慢的顺序来进行逐级访问
  2. 缓存一致性问题,缓存问题
  3. 进程内缓存和redis同时使用,是比较好的方案,先查EhCache,再查redis【双写手段】

在这里插入图片描述
4:什么时候要引入多级缓存??

  • 缓存的数据是稳定的
  • 瞬时高并发场景
  • 一定程度上允许数据的不一致性

四:大表严禁使用自增主键

1:大表为什么不能使用自增主键

自增主键在分布式环境下不适用。

由于自增主键必须连续,所以按范围法进行分片,ID的数量已固定。无法进行动态扩展。会产生“尾部热点”效应。

尾部热点:即按范围法进行分片后,前面的分片已储存数据,最后一个分片的压力很大。

Hash分片的效率更高【而自增主键因为连续问题,无法使用Hash分片】

2:UUID是好的替代方案吗

不是好的替代方案

因为UUID是唯一无序的。无序导致索引重排。主键有序的情况下,B+树只需要在原有的数据后面追加即可。

而使用UUID可能会导致整棵B+树都重新调整,大大浪费时间

3:雪花算法介绍

雪花算法(Snowflake)是twitter推特公司分布式项目采用的ID生成算法

在这里插入图片描述

  • 第一部分是1位的符号位 -> 没有实际的用途,主要为了兼容长整型的格式
  • 第二部分是41位的时间戳来记录本地的毫秒时间
  • 第三部分是机器的ID,最大规模是2^10(1024)个节点
  • 第四部分是12位序列,序列的长度决定了一个节点1ms能够产生的ID的数量,2^12(4096)个

实现雪花算法时候要注意时间回拨带来的影响,有可能出现ID重复

五:布隆过滤器在大数据的应用

1:缓存穿透问题

在这里插入图片描述

指恶意用户在短时间内大量查询不存在的数据,导致大量请求在被送达数据库进行查询,当请求数量超过数据库负载上限时,使系统响应出现高延迟甚至瘫痪的行为。

【注意缓存击穿和缓存穿透的区别 -> 缓存击穿是指redis没有,数据库服务器有,而缓存穿透是指redis和数据库都没有】

2:布隆过滤器

由一个很长的二进制向量和一系列随机映射函数组成,可以用于检索一个元素是否在一个集合中。

在这里插入图片描述
初始化的时候,对指定的内容进行若干次哈希,将对应的下标内容修改成为1

在这里插入图片描述
在使用的时候就可以判断当前的内容在不在过滤器中了:

存在的情况 -> 所有的hash结果对应的位都是1 -> 可能误判存在

在这里插入图片描述

不存在的情况 -> 存在某一个hash结果对应的位数不是1 -> 一定不存在

在这里插入图片描述

减少误判的措施

  • 增加二进制数组的位数
  • 增加hash的次数

布隆过滤器的特点

  • 一定的误识别率(即某一元素存在于某集合中,但是实际上该元素并不在集合中)
  • 没有识别错误的情形(即如果某个元素确实没有在该集合中,那么Bloom Filter 是不会报告该元素存在于集合中的,所以不会漏报)
  • “我说你不在你就一定不在,我说在,可能不在”

3:Java运用布隆过滤器

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-all</artifactId>
    <version>3.16.0</version>
</dependency>
public class BloomTest {
    public static void main(String[] args) {
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        // 构造redisson
        RedissonClient redisson = Redisson.create(config);
        // 拿到布隆过滤器
        RBloomFilter<String> test = redisson.getBloomFilter("test");
        // 初始化布隆过滤器,预计元素为1000000L, 误判率1%
        test.tryInit(1000000L, 0.01);
        // 添加元素
        test.add("1");
        test.add("2");
        // 判断指定的编号是不是在布隆过滤器中
        System.out.println(test.contains("1"));
        System.out.println(test.contains("2"));
        System.out.println(test.contains("3"));
    }
}

在这里插入图片描述

加入商品被删除了怎么办??

  • 布隆过滤器因为某一位二进制可能被多个Hash引用,因此布隆过滤器没有办法直接处理删除数据的情况
  • 一般有两种及诶觉方案:定时异步的重建布隆过滤器 或者 采用 计数布隆

六:禁用IP直连

1:IP直连的问题

强耦合问题

jdbc:mysql://202.99.183.21.3306/db
http://192.168.31.205/webapp

这种配置方式在开发过程中没有任何为题,但是如果部署到线上就会有很大的问题产生 - 强耦合问题

原代码连接数据库地址是192.168.3.21,现在业务需要连接到另一台数据库192.168.3.31,则可能存在代码修改,编译,部署,走流程等

在这里插入图片描述
所以线上建议用域名代替ip地址,因为在架构设计中需要考虑解耦问题

2:怎么解决IP直连的问题

方式一:引入内部DNS,即建立一个域名解析服务器。

在这里插入图片描述

  • 优点:IP地址迁移变得灵活,后续直接修改域名解析服务器域名对应的IP地址即可。
  • 缺点:
    • 没有故障发现和转移
    • 一个域名绑定多个ip,负载均衡只有轮询规则。

加入注册中心(Nacos/Eureka/Consul)

弥补没有故障发现和转移。

多个数据库IP,在注册中心进行配置,注册中心通过多种负载均衡,选取某个IP进行返回(跟内部DNS类似)

如果发现故障和故障转移。

数据库注册到注册中心,两者之间通过注册保持连续,注册相当于一个心跳包,服务器节点定时向注册中心发送信息,告知服务器正常。

若某节点异常,异常服务器会被注册中心移除。

在这里插入图片描述

  • 优点:支持故障发现和转移。具有多种负载均衡策略。
  • 缺点:架构复杂度增加。【注册中心需要维护节点的状态,并且定时监听心跳包。一般会部署成集群,比内部DNS复杂,还需考虑高可用】

七:负载均衡器

1:什么是负载均衡器

在这里插入图片描述
优点:高可用、设备压力平均分配,支持故障发现和转移

分类:

  • 软硬件层面 -> 硬件负载均衡器【f5, 贵】,软件负载均衡器
  • 网络层面 -> 四层代理,典型代表是LVS(作用在TCP层),七层代理,典型代表是Nginx(作用在HTTP蹭)

在这里插入图片描述
在这里插入图片描述

2:Nginx负载均衡器

nginx是一款轻量级的Web反向代理服务器,是目前使用最多的软件负载均衡器

Nginx:内置负载均衡策略有哪些 --> 轮询策略(默认)、权重策略、IP_HASH、URL_HASH(第三方模块)、FAIR(第三方模块)

  • 轮询策略:4个任务,你负责1,我负责2,你负责3,我负责4,类似。适用于性能相当的服务器。
  • 权重策略:4个任务,你能力强,你做3个,我能力差,我做1个。适用于性能不一致的服务器。
  • IP_HASH:有多个用户访问Nginx,通过用户的IP对N取模(N台服务器),该IP一直由对应的服务器负责。不建议使用,无法保证服务器的均衡。
  • URL_HASH:类似IP_HASH,比IP_HASH更精确,但仍无法保证服务器的均衡。
  • FAIR:谁有空谁干活。使用心跳包判断哪台服务器闲置,然后把请求送达闲置服务器。现实使用较少。了解即可

八:数据库设计禁用外键约束

在这里插入图片描述

1:插入数据需要检查外键在引用的表是否存在

2:并发读取会将要更改的page pin起来

外键会被频繁检查,导致一直被锁定,pinned page在全部schedule操作执行完毕前不会应用到数据库,过多并发排队会导致崩溃

从而导致实际写入的表也就是订单明细表的所有写操作未提交到DB而且崩溃

3:由于外键约束的级连删除

会导致在其他表引用该值的地方被一并删除,导致删除操作的结果不可控

4:数据一致性校验的问题

如果依赖外键关联来实现数据的一致性校验,会导致一旦需要迁移数据或升级DB软件时

需要改写应用来使应用对数据进行校验,还不如一开始就把数据校验交给应用完成

举一个场景:订单表跟订单明细表。这时订单id主外键关联

  • 性能问题,额外的数据一致性校验查询。往订单明细表添加一条数据,会强制查询对应订单表中的订单id是否存在。
  • 并发问题:外键约束会启用行级锁,主表写入会进入阻塞。并发环境下,往订单明细表添加一条数据,会强制查询对应订单表中的订单id是否存在,所以订单表开启共享锁(共享锁【S锁】,又称为读锁,可以查看但无法修改和删除的一种数据锁)。某种情况下对订单id进行更新操作,这时该数据开启排它锁(排他锁【X锁】,又称写锁)。若写锁不被释放,订单明细表处于被锁定的状态。会造成线层积压,系统崩溃。
  • 级联删除问题:多层级联删除会让数据变得不可控,触发器严禁使用。
  • 数据耦合:数据库层面数据关系产生耦合,数据迁移维护困难。例如如果订单明细表数据增长,数据量10亿后,需要迁移到Hbase。
  • 这时数据不在同一个库,没有了主外键约束,代码上无校验,就会产生属于一致性问题。

九:前后端分离架构

1:纯后端的页面渲染架构

典型代表 = jsp || freemaker

在这里插入图片描述

纯后端渲染主要有如下的问题:

  • 前端团队无法进行单独的调试
  • 前后端职责不清,分工不明确
  • 不具备多端应用的能力

2:半分离架构模式

在这里插入图片描述

半分离式的架构主要有如下的特点

  • 前后端前后结构
  • 后端API和数据重用
  • 应用渲染更加的灵活
  • 约定好接口和规范进行mock开发

3:前后端分离式架构

在这里插入图片描述
前端NodeJS这里有一个本地缓存的概念,在第一次请求之后,会将后端拿到的数据存储到本地缓存,第二次发起同样请求的时候,只需要从本地获取返回就可以了,这样可以减少网络访问和增加效率。

应用网关的诞生就是为了请求路由,应用网关中存在一个设备标识的标签,当客户端带着请求通过应用网关的时候,应用网关就会解析这个设备标识,从而知道访问的设备类型,然后前后端就可以根据不同的设备类型,进行不同的数据返回,这就是多端访问。同时应用网关还可以进行黑白名单的处理,鉴权认证的工作等等。

十:Canal实现MySQL异构数据同步

1:何为异构数据

在这里插入图片描述
mysql存储的数据的结构和ES存储的数据的结构完全是不一样的,这样的数据叫做异构数据。

如果现在商户在团队A中插入了一个Mysql数据,如何同步给团队B的ES数据呢?

一般的做法就是在Java代码中新增MySQL数据库时候向调用团队B同步接口新建ES商品数据。—> 高耦合现象

此时就会出现团队A & 团队B在代码层面上的高耦合,团队A必须了解团队B提供的接口才可以实现,但是这个本身不属于团队A的工作范畴

同时上述解决方案还涉及到了扩展困难的问题:假设现在有一个团队C在维护MongoDB的数据库也要同步MySQL数据库,难道团队A又要改代码?

所以需要一种方法:保证数据做到准实时同步,同时还要进行团队之间的数据结构,团队A不再进行背锅

2:canal

Canal是阿里的一个开源项目,纯粹使用java开发,基于数据库增量日志解析,提供增量数据订阅 & 消费,目前主要支持了MySQL

先来复习一下主从同步

在这里插入图片描述
而Canal就是伪装成从库的,通过监听relayLog自动的获取到用户在MySQL上的增量修改,以此可以完成MySQL更改数据的任意处理推送工作

在这里插入图片描述
通过单单的引入Canal解决了数据监听的问题,但是还没有解决解耦的问题,这时候就要引入消息队列完成应用之间的解耦

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值