Java架构之路
2021-09-25 18:09:21 0 举报
AI智能生成
Java架构之路,循序渐近
作者其他创作
大纲/内容
分布式锁
配置管理
集群管理
功能
属性的目录服务
数据模型
./zkCli.sh -server ip:port
1.连接Zookeeper服务端
quit
2.断开连接
set /节点path value
3.设置节点值
查看帮助命令
4.help
delete /节点path
5.删除单个节点
ls 目录
6.显示指定目标下节点
deleteall /节点path
7.删除带有子节点的节点
create /节点path value
8.创建节点
get /节点path
9.获取节点值
基础命令
create -e /temp1 value
1.创建临时节点(会话关闭删除)
create -s /app1 value
2.创建顺序节点
create -es /temp_order1 value
3.创建临时的顺序系节点
ls2 /节点path
ls -s /节点path
4.列出子节点和附加信息
高级命令
客户端命令
启动服务:./zkServer.sh start
查看服务状态:./zkServer.sh status
停止服务:./zkServer.sh stop
重启服务:./zkServer.sh restart
服务端命令
命令
Apache Zookeeper 的客户端
原生Api
ZkClient
其他Api
Curator
Leader
Follower
1. 基于编号大小投票
2.基于启动时间的大小
3.基于事务id,最新的代表能力越强
投票
选举
集群
利用建立瞬时顺序节点
发布订阅节点状态,比较自己的顺序是不是所有节点中最小的,最小的获取锁成功
Zookeeper
String
List
Hash
Set
Zset
BitMap
Geo
HeperLoglog
发布与订阅的持久化,类似消息中间件
Stream
基本数据类型
单机锁在分布式情况下,也会导致数据冲突问题
1.保证加锁互斥,由于天然单线程,使用setNx不会出现两个线程同时获取到锁
2. 防止死锁,需要带上健壮性,但防止宕机导致锁不能释放,需设置过期时间
3.设置过期时间可能不够业务执行,则需要进行过期时间异步守护线程续期
4.同时需要保证释放锁操作不能释放到别人的锁,所以需要增加本线程唯一标识来判断是否自身锁释放
5.为了保证续命守护线程被挂起不能续命,则需要防止其它线程进来,所以需要保证删除操作的原子性
6.保证原子性可以使用事务保证,也可以使用lua脚本保证
7.防止在集群模式下主从节点的不一致性,导致加锁失效,则需要保证一半以上的节点都加上锁,所以采用Redisson
8.Redisson释放锁的时候也需要进行是否为自身持有锁和锁定状态
分布式锁实现原理
可能导致CPU空转
定时清除
极端情况下可能导致空间浪费
惰性清除
结合上面两种进行随机部分扫描清除
也可能导致一些数据不能清除
定期清除
Redis的过期策略
1.不排挤
2.新添加数据是内存不够用,则在设置了过期的key中LRU淘汰
3.新添加数据是内存不够用,则在所有的key中LRU淘汰
4.新添加数据是内存不够用,则在设置了过期的key中LFU淘汰
5.新添加数据是内存不够用,则在所有的key中LRU淘汰
6.新添加数据是内存不够用,则过期的key中淘汰即将过期的key
7.新添加数据是内存不够用,则在设置了过期的key中随机淘汰
8.新添加数据是内存不够用,则在所有的key中随机淘汰
内存淘汰策略
乐观锁:使用 Watch key监控字段变更配合事务完成
Multi开启事务、Exec提交事务
事务
缓存击穿/穿透
缓存雪崩
经典问题
不能达到数据强一致性
节点宕机需要手动选举
浪费空间,不利于扩容
读写分离,降低压力
利于容灾恢复
主从复制:异步线程复制
自身集群化保证高可用
监控主从节点,选举主节点
哨兵模式
利于扩容
依然需要哨兵坚守
每个节点存储不同的数据。利于扩容
采用hash插槽
无中心化,超过半数ping超时认为某个节点宕机
集群模式
punlish
subscribe
发布与订阅
采用定时持久化到磁盘
可能存在丢失数据
RDB
采用执行命令追加模式
实时性比较高,丢失数据缩小在1秒范围
AOF
持久化
分布式Session
Redis
快速响应处理请求
快(高性能)
处理准确无误
准(一致性)
服务高可用
稳(高可用)
追求目标
并发读
并发写
核心要点
页面缓存
URL缓存
对象缓存
静态资源化
页面优化
Redis缓存
内存标记减少redis访问
中间件削峰
异步任务
数据库性能优化
服务优化
秒杀之前隐藏地址
前端MD5加密再后端加密
双层MD5加密
安全优化
用户登录
共享session
分布式会话
商品列表
商品详情
秒杀
订单详情
功能开发
Jemeter
自定义变量
正式压测
系统压测
优化
高并发秒杀系统
Kafka
RabbitMQ
解耦
异步
削峰
作用
用户进行注册操作
注册信息存储之后需要发送邮件和短信通知
将邮件和短信通知改为异步消息队列,发送到对应微服务
场景
NameServer
接收消息
存储
投递
Broker
组件
1.创建生产者,指定生产者所属的组名
2.指定NameServer的地址
3.启动生产者
4.创建消息对象,指定主体,标签和消息体
5.发送消息
6.关闭生产者
步骤
同步保证
异步保证
单向非保证
类型
hash
顺序消息
投递消息到Broker
发送给生产者半事务消息成功,
生产者执行本地事务发送给Broker进行成功投递还是回滚
如果Broker没有收到二次确认会保留三天然后删除
事务消息
发送消息
1.创建消费者对象,指定消费者所属的组名
2.执行NameServer地址
3.指定消费者订阅的主体和标签
4.设置回调函数,编写处理消息的犯法
5. 启动消费者
消费者消费
1.多Master
2.多Master-Slave,异步复制
3.多Master-Slave,同步双写
4.多Master-Slave(2)
RocketMQ
ZeroMQ
ActiveMQ
Topic
写入的消息中key为null
轮询分配
指定key hash分区
不推荐使用
随机分配
分配分区策略
Partition
leader
follower
同步双写
机制
选举:会维护一个ISR(In Sync Replicas),选取ISR中最好的(同步信息最靠前的)
OSR(Out of sync Replica):未同步的副本
AR: 所有的副本
Replica
OffSet
每个生产者有个pid和每个分区存在一个增序的number
避免多次生产
幂等性
概念
集群管理Zookeeper
管理Partition的选举
Flollwer
下发通知到其它flollwer由各自到去Zookpeer建立临时节点
Producer
Consumer
一个消费者组中可以包含多个消费者,共同来消费Topic的数据
一个topic中如果只有一个分区,那么这个分区只能被某个组的消费者消费
有多少个分区,那么就被同一个组的多少个消费者消费
消费者规则
最好的高吞吐量,一个分区对应一个消费者
当消费者组消费者数量发生变化,会触发再平衡
再均衡(Rebalance)
分区数量/消费者数量 = 每个消费者获取的分区数量
多余的分区依次分配给前面的消费者
公式
Range范围分配策略
轮询依次分配给每个消费者
减少:尽量再分配余下的消费者依次分配原来减少的消费负责的分区
增加:重新调整RangRound分配
粘性分配
消费分区分配策略
Cousumer Group
根据不同写入分区分配策略可能导致消息分配到不同的分区,导致了消息没有先后顺序
解决办法:使用keyhash分区策略,使得相同类型的消息分配到同一个分区,使得由同一个消费者进行消费
消息乱序问题
问题
Kafka-Eagle
集群可视化管理工具
每个topic有多个分区存储
每个分区下有多个Segment
每个Segment下有log、index、timeindex
数据存储
分区副本保证
Broker丢失
1. 所有副本都完成存储
2.leader存储成功
3.不保证,只发信息
ACK
生产者消息不丢失
消息丢失
最多一次
重复消费
最少一次
利用自己维护offset与数据库事务保证
仅有一次
消费者消息不丢失
数据丢失
如果是故障导致积压需解决故障,可以增加临时扩展
业务积压,临时增加消费者
数据积压
基于时间的保留策略
基于日志的大小保留策略
基于偏移量的保留策略
日志删除
相同key的不同值合并为最新的
日志压缩
数据清理
中间件
所有的业务模块融合在一个应用系统中
系统耦合度较高,单点故障,不利于扩展(造成冗余)
1.单体应用架构
在单体架构基础上大体拆分,前台服务,后台服务
2.垂直应用架构
服务按照模块拆分,比如用户模块、订单模块、商品模块、新闻模块
暴露服务依然是前台服务、后台服务
3.分布式架构
在分布式架构的基础上解决依赖错综复杂,加入了服务治理中心
4.SOA架构
将业务原子化拆分(垂直拆分)
所有微服务直接对外暴露
增加网关 APi GateWay
1.服务治理
2.服务之间调用,RPC、Http Resutful
3.服务容错
4.链路追踪
5.服务网关
问题延伸解决
5.微服务架构
服务架构演变
Spring Cloud
多个微服务之间存在依赖关系,一旦一个服务存在故障,可能导致连锁反应
不合理的容量设计
高并发下某个方法响应变慢
资源耗尽
原因
服务雪崩
线程池隔离
信号量隔离
隔离
超时
限流
熔断
服务容错
Netflix开源服务容错,可用性
Hystrix
轻量、简单
Resilience4j
控制线程数量
流量控制
服务降级
负载保护
DashBoard
控制界面
保护东西:可以是系统,方法,代码片段
定义资源
本类定义异常方法处理
blockHandler设置处理异常(BlockException)逻辑
fallBack:定义发生异常后进入的方法
@SentinelResource
资源
如何是保护资源
直接流控
关联流控:其它资源达到阈值触发
链路: 指定请求来源
流控模式
快速失败
排队等待
突然增大流量转为缓步增长
WarmUp
流控效果
流控规则
响应时间阈值
时间窗口:降级时间
平均响应时间(RT)
单位时间内异常数与通过比值
异常比例
单位时间内(1分钟)的异常数量
异常数
降级规则
更加细粒度的控制
具体参数级别的控制
热点规则
控制请求来源
授权规则
面向整个系统整体的负载控制流量
系统规则
分类
规则
服务熔断
1. 保证自身不被下游拖垮
服务隔离
服务超时
服务限流
2.保证不被上游压垮
集群负载
保证平衡
3.保证自身不被外界影响
核心思想
定义持久化配置文件到客户端本地
规则持久化
在@FeignClient(fallBack=FallBackGHandler.class)
Feign对Sentinel支持
Sentinel
服务限流降级
Eureka
Consul
Spring Cloud Ribbon负载均衡
自定义客户端负载均衡
Feign 基于http rest 服务之间调用,自定负载均衡
Nacos
服务注册与发现
服务发现
服务认证、鉴权
服务跨域
Nginx+Lua
Kong
Zuul
依赖导入(spring-cloud-starter-gateway)
日期
主机
请求方式
请求参数
断言(匹配)
请求之间(Pre)
请求之后(Post)
鉴权
认证
内置过滤器
过滤器(请求处理)
路由维度
自定义Api维度
网关限流
路由规则
Spring Cloud Gateway(推荐)
实现组件
服务网关
微服务调用链路
Cat
ZipKin启动的增加存储方式为Mysql
Mysql
ZipKin启动的增加存储方式为ES,及相关信息
Kibana
ElasticSearch
数据持久化
收集、存储,分析,展示
Zipkin
采集
进行记录Trace、Span
Sleuth(推荐)
Pinpoint
Skywalking
一次完整的请求链路路径
Trace
CS:客户端发出请求,开始一个请求的生命
SR:服务端接收到请求开始处理,SR-CS=网路延迟(服务调用时间)
SS:服务端处理完毕准备发送到客户端,SS-SR=服务端上的请求处理时间
CR:客户端接收到服务端的响应,请求结束,CR-SR=请求的总时间
Span
链路追踪
携程开源
Apollo
Disconf
SpringCloud Config
Nacos Config
分布式配置管理
微服务下的多个事务控制问题
提供一个第三者,全局事务管理器,各个事务进行预先提交,如果判断预提交可以成功,上报给全局事务管理器,如果全部事务都成功了,全局事务就下达真正提交事务,依然可能存在出错
全局事务
RocktMq事务
基于可靠消息事务
最大努力通知
Try Confim Cancel
补偿型分布式事务
1.尝试执行业务
2.确认执行业务
3.取消待执行业务
三个步骤
TCC
解决方案思路
事务管理器
全局事务协调器
资源管理器
Seata
分布式事务
分布式任务调度
消息驱动
主要功能
把流量作为切入点、从流量控制、熔断降级、系统负载等多个维度保护服务的稳定性
1.Sentinel
一个更加易于构建云原生应用的动态服务发现,配置管理和服务管理平台
2.Nacos
一个分布式的开源消息系统
3.RocketMQ
一款高性能的RPC框架
4.Dubbo
阿里巴巴开源,一个易于使用的高性能微服务分布式事务解决方案
5.Seata
一款在分布式价架构环境中对应用配置集中管理和推送的应用配置中心产品
6.Alibaba Cloud ACM
阿里巴巴中间件团队开发的一款分布式任务调度产品、提供秒级、精准、高可靠、高可用的定时任务调度服务
7.Alibaba Cloud SchedulerX
覆盖全球的短信服务、友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道
8.Alibaba Cloud SMS
对象存储服务
9.Alibaba Cloud OSS
Spring Cloud Alibaba
Apache Service Comb
分布式服务
1.算法函数中的常数可以忽略
2.算法函数中最高次幂的常数因子可以忽略
3.算法函数最高次幂越小,算法效率越高
算法公式结论
T(n) = O(f(n))
一次循环
O(n)
1.线性阶
二次循环
O(n2)
2.平方阶
三次循环
O(n3)
3.立方阶
O(logn)
4.对数阶
O(1)
5. 常数阶
常见的大O阶
大O表示
当查询的数据不确定就需要考虑最坏的打算
最坏的时间复杂度为该算法的时间复杂度
最坏情况
时间复杂度分析
对象头16个字节
引用8个字节
实例数据根据数据类型相加
8位的倍数
对齐填充
除了对象头身大小和实例数据大小
还需要4个字节保存长度
数组
对象空间大小
空间复杂度分析
算法分析
进行两次循环,双指针,一个指针定位参与比较的元素,另一个定位比较位置
总是在余下的元素中比较寻找最大或者最小的元素放置最后位置
冒泡排序
顺序遍历,在余下的元素中找到最小元素的索引与第一个元素交换
选择排序
顺序遍历获取余下的第一个元素,然后与前面已排序的集合倒序遍历比较并交换,直到找到比自己小的元素停止比较
插入排序
插入排序的优化,先对元素进行分治插入排序,直到为分治进行常规插入排序,这时插入排序的比较交换过程就少了
希尔排序
将集合进行分组,直到最小分组(一个组一个元素),从最小的每两组进行双指针比较添加到新的数组,然后写回
归并算法
取第一个作为临界值将集合一份为二,左边小于临界值,右边大于临界值,接着继续对分组后的每组进行再一分为二
快速排序
利用堆有序,将元素转换为堆,然后删除和下层获取的元素就是一个从大到小的顺序,或者将最大值放置最有一个位置,然后进行堆下层,相当于也找到剩余堆元素的最大值
初始化堆:从索引一半的位置进行倒序下层交换
堆排序
排序算法
算法分类
算法
线性表
单向链表
双向链表
根据判定快指针是否结束,结束时慢指针即为中间值
查找中间值
利用快慢指针是否相遇判定
查找是否有环
利用快慢指针,先找到环,此时准备一个临时指针,指向链表的首节点,之后继续遍历直到慢指针与临时指针相遇,即为入口节点
查找环入口
快慢指针
循环报数,数到三就自杀,然后又从1开始报数,数到三就自杀,依次自杀,总共41个人,16、31会最后自杀
约瑟夫问题
有序符号
符号表
链表
头插法
解决括号匹配问题
后缀表达式
逆波兰表达式
栈
队列
节点的度
度为零的节点
叶子节点
度不为零的节点
分子节点
从根节点开始,根节点的层次为1,根的直接后继层为2,依次类推
节点层次
将树中的节点,按照从上层到下层,同层从左到右的次序排成一个线性序列,把他们编成连续的自然数
节点层次的编号
树中所有的节点的度最大值
树的度
树中节点的最大层次
深度
森林
相关术语
每一层都达到最大值:
满二叉数
完全二叉树
递归向左走
查找最大的键
递归向右走
查找最小的键
先父节点,然后左节点,最后右节点
前序遍历
先左节点,然后父节点,最后右节点
中序遍历
先左节点,然后右节点,最后父节点
后续遍历
基础遍历: 广度优先
利用队列入队,然后每个节点的子节点入队,最后整体key队列遍历
利用递归判断左右子树得到大的数,进行累加
层序遍历:深度优先
最大深度
折纸问题
遍历
二叉树
二树:两个子节点
三树:三个子节点
二三查找树
平衡树
目标达到完全二叉查找树
利用平衡树原理,二三查找树
1. 利用红节点将本节点与父节点进行绑定为一个三树,达到一个元素层级提升
2.规定不允许连续的左红节点
3.不允许右红节点
4.根节点永远是黑节点
5.任何一个空节点到根节点的黑节点数量相等(红节点与绑定的父节点一起是为一个黑节点)
采用红黑节点实现二三查找树
红黑树
扩展二三查找树,变成四、五或者更多阶的查找树
B树
二三查找树,向上增长,叶子节点存储数据,非叶子节点存储索引,并且节点拆分的时候要保留索引和索引数据
mysql的索引
B+树
元素值看作数组索引,索引值为元素的组标识
组标识不同,视为不同的组
默认情况下一个元素视为独立的一个组
不同分组可以进行合并,只需更改当前元素的所属分组标识即可
基本概念
网络中一台台的电脑为独立的元素,要想不同电脑之间能够通信,则需要把他们加入同一个组中(组网)
场景应用
起因:由于N个独立组元素,需要N-1次组合并才能达到所有的元素在同一个组
将索引值改为存储父节点,相同根节点视为同一个组
合并时,只需要将其中一个根节点所在的索引值改为另外一个组的根节点的值,即将两个组的根节点的父节点改为同一个
并查集优化1
进一步优化,合并时,将较小深度的根节点的父节点改为较大的组的根节点
目的是为了将树的层级缩小,减少元素查找根节点的次数
需要另外申请一个数组存放指定根节点所在树的元素个数
并查集优化2
城市之间的路连通,已经连通多少条,剩余还需要多少条,完成所有城市连通
畅通工程
并查集
树
数组方式存储,层序从左到右按序存储
每一个节点都要比它的两个子节点要大于或者等于
两个子节点左右不区分谁大谁小
存储结构
先插入到数组最后一个位置,然后采用上浮算法进行交换调整位置,直到堆中合适的有序位置
上浮算法:依次与父节点比较,然后大于父节点就交换,然后交换完成后继续与父节点进行交换,直到小于父节点结束
插入元素
交换第一个元素(最大元素)和最后一个元素,然后采用下浮算法进行交换调整堆顺序
下浮算法:当前节点与它的子节点找出较大节点比较大于就交换,直到小于截至
删除最大元素
利用堆特性,直接删除最大元素,就为优先级别
最大优先队列
将大顶堆进行反向
优先队列
原始数组存储依次
在进行转换为堆结构数据,不直接调整原始数组,而是新加一个数组存储原始数组的索引位置,根据原始数组对应的大小进行跳转索引数组的顺序
第三个数组为存放第二个数组的索引反序,序号和原始数据序号一致,值就是第二个数组的序号
采用三个数组进行存储元素
索引优先队列
堆
V*2的存储结构,存在空间过多
邻接矩阵
数组加链表(队列)
数组的索引表示顶点,值表示连接相邻顶点的边,多个边用队列进行一次存储
存在,相反指向,但空间复杂度要少于邻接矩阵
邻接表(采用)
相邻顶点
度
子图
路径
环
如果图中任意一个顶点都存在一条路径到达另外一个顶点
连通图
一个非连通图由若干部分组成,每一个连通的部分都可以成为该图的连通子图
连通子图
基本术语
目标搜索指定元素元素
当搜索到指定顶点的相邻顶点后发现该相邻顶点还有子相邻顶点,则优先递归搜索子相邻顶点
需要另外一个数组标志存储是否已经搜索过
采用递归方式
深度优先搜索
非递归,需借助队列
广度优先搜索
利用深度或者广度优先搜索算法查找从起点到终点,查找的过程记录下当前节点的上一个节点
利用记录下来节点的上一个节点记录,遍历依次存入栈中,然后再进行弹出栈就得到从起点到终点的路径节点
路径查找
包含边的两个顶点
权重
给边增加权重,将邻接表中存储为一个Node表示边
加权无向图
将所有顶点连通的最少的边组成的图就是一个树
1. 用一条边连接树中任意两个顶点都会产生一个新的环
2.从树中删除任意一条边,将会得到两颗独立的树
树的性质
1.切分:将树进行任意的切分为两个非空的集合
2.横切边:表示经过一次切分之后,连接两个集合的边叫做横切边
3.在所有横切边中最小权重的边必然属于最小生成树的一条边
4.最小权重的横切边并不是横切边中唯一的最小生成树的边
树的切分定理
经过N-1次切分定理找到所有的最小生成树的边
贪心算法
同样是利用贪心算法寻找最小生成树的边
原理
Prim算法
也是贪心算法的一种优化
原理:利用索引最小优先队列保存图中所有的边,然后依次遍历虽小的边,判断该边是否已经存在最小生成树中,如果存在则不处理,依次寻找所有最小权重的边,并且加入到已存在的最小生成树中。
kruskal算法
最小生成树
无向图
定义
由某个顶点指出的边的个数称为该顶点的出度
出度
指向某个顶点的边的个数
入度
由一系列顶点组成,对于其中的每个顶点都存在一条有向边,从它指向序列中的下一个顶点
有向路径
一条至少含有一条边,且起点和终点相同的有向路径
有向环
不相连
存在一条边指向它,v-->w
存在一条边指向它,w-->v
两个顶点
在众多依赖关系中找出依赖顺序,例如学习技术顺序
原理:利用深度优先搜索,将已经搜索过的顶点进行标记,当下次搜索到已经标记的顶点表示存在环
需要先排除图中存在环的问题
基于深度优先的顶点排序
拓扑排序
在有向图的基础上增加边的权重
加权有向图
最小路径定义和性质
1、根据判断起点s到达目标顶点w的总权重是否小于从起点s到达另外一个顶点v的权重加上v到w边的权重之和
2、如果小于则不需要改变,如果大于,则将起点s到顶点v的权重加上顶点v到终点w的权重设置为目前起点s到到w的总权重,并且把从起点s到达终点w的最小路径中上一条边修改为顶点v到w这条边
边松弛
将顶点的所有出度的边进行依次松弛得到最小边
顶点松弛
松弛技术
1、需要借助索引最小优先队列,存放树中顶点与非树中顶点之间的有效横切边
2、初始化让所有的顶点到目标顶点的权重为无限大
3、让起点直接进入最小路径树中(把该顶点放入队列中),依次去判断获取最小边,然后将该边对应的另外一个顶点放入最小路径树中,接着再去寻找该顶点的所有出度的最小边,依次类推直到找到目标顶点
Dijkstra算法
最短路径
有向图
图
数据结构
数据结构与算法
1.继承Thread类
2.实现Runnable接口
3.线程池工具类
4.线程池原始类
多线程、高并发
JUC
ArrayList
LinkedList
Stack
Vector
LinkedHashSet
HashSet
TreeSet
SortedSet
Deque
AbstractQueue
数组实现的阻塞队列
ArrayBlockingQueue
多元素链表实现阻塞队列
LinkedBlockingQueue
LinkedTransferQueue
单元素阻塞队列
SynchronousQueue
BlockingQueue
Queue
Collection
LinkedHashMap
HashMap
HashTable
TreeMap
Map
集合框架
基于流的阻塞io,一次请求一次处理,需要开启新的线程去同时处理多个客户端请求
BIO
基于Selector多路复用器,将管理多个Channel,监听他们的状态变化,进而根据状态处理数据
NIO
在NIO多路复用器的基础上将写入或者写出异步化
AIO
IO、NIO、AIO
IO多路复用
Java基础
JVM内存结构
性能监控与调优
JVM性能与调优
JVM虚拟机
查看创建表语句:Show Create Table 表名
查看创建数据库语句:Show Create Database 库名
查看表结构:Descible 表名
清空表数据:TRUNCATE 表名,会清空自增列计数器
常用SQL语句
经常作为条件查询的字段
小数据量不要加索引
经常变动的数据不要加索引
重复率高的数据不要加索引
注意事项
索引命中查看关键字:Explain
保证主键不可以重复,只能是一个列
1.主键索引
避免重复的列
可以多个列作为索引(组合索引)
2.唯一索引
默认
3.常规索引
快速定位数据
4.全文索引
查看索引:show index from 表名
1.索引
1.减少 IO 次数
2.代码优化
3.降低 CPU 计算
SQL和索引优化
字段设计最小化
引擎选择
将字段比较多的表拆分为主从表,提高主表的查询效率
将数据量比较大的表动态拆分(hash、日期、业务规则)多表存储
垂直拆分
读写分离分库
水平拆分
分库分表
数据库结构优化
网络
磁盘
内存
系统硬件升级
1.MyISAM不支持事务
2.MyISAM仅支持表级锁、InnoDB支持表级和行级
3.MyISAM支持全文索引,InnoDB不支持
4.MyISAM不支持外键约束、InnoDB支持外键
5.MyISAM存储了行数,InnoDB需要实时扫描查询
6.MyISAM存储空间较小,InnoDB较大
7.MyISAM清空表是重新建表,InnoDB是一条条删除
MyISAM和InnoDB区别
1.保证每个字段的原子性不可拆分
3.同一张表不要存在传递性依赖会存在冗余数据
三范式原则
事务的执行要么都成功,要么都失败
原子性(Automicity)
最终一致性,最后的结果不会操作已有的最大值
一致性(Consistency)
主要是针对或者删除,两次读取数据量不一致
幻读
一个事务读取到了另外一个事务还未提交的数据
脏读
一个事务两次读取某一条数据不一样
不可重复读
读未提交
读已提交
可重复读
串行化
隔离级别
隔离性(isolation)
一旦提交就持久化到数据库,不可逆
持久性(Durability)
mysqldump -hlocalhost -uroot -p12345 库名 > 备份文件路径.sql
source 备份文件路径.sql
备份
针对一条记录进行加锁
如果范围查询将升级为表锁
SELECT * from t_sys_user lock in share mode
SELECT * from t_sys_user for update
查询时加锁
行锁
锁定整张表
默认情况,InnoDB如果判断需要加表锁,自行加锁
lock table tablename read
共享
locck table tablename write
独占
unlock tables
解锁
显示加锁
表锁
锁机制
在线安装
安装
拉取镜像
删除镜像
镜像加载原理
Commit提交镜像
镜像
运行创建容器:docker run -d -P ...
查看容器:docker ps -a
删除容器:docker rm -f <ContainerId/Name>
启动或停止容器:docker start/stop <ContainerId/Name>
查看日志:docker logs -f -t --tail [行数] <容器id>
查看容器元数据:docker inspectr <ContainerId/Name>
进入容器:docker exec -it <ContainerId/Name> /bin/bash
容器
查看容器卷:docekr volume ls
查看卷信息:docekr volume inspect <VolumeId/Name>
数据卷容器:--volumes-from <ContainerId/Name>
容器卷
构建命令:docker build -f /home/dockerfile/Dockfile -t lyscms/volume:1.0 .
Docker基本指令
查看镜像构建历史:docker history <镜像id>
登录:docker login -ulyscms
发布镜像
Dockerfille
--link 连通各个容器
docker network 网络信息命令
查看网卡列表:docker network ls
查看网卡信息:docker network inspect <netId>
自定义网络
配置连接到指定网络
多个网络之间连接
Docker网络
授权
Docker Compose 使用
使用
Docker Compose
准备4台物理机(Linux)
各个物理机节点之间通信
初始化一个swarm
加入工作节点
创建一个管理节点令牌:docker swarm join-token manager
移除节点:docker swarm leave
查看集群节点:docker node ls
部署集群
Raft协议
创建服务
查看服务
访问服务
修改副本数
扩缩容
更新服务
删除服务:docker service rm nginx01
Service
Docker Swarm
Docker Stack
Docker Config
1.编写Springboot并打包
2.编写Dockerfile
3.构建镜像
4.运行容器
部署SpringBoot
Docker
K8s
容器化
用于描述如何去创建对象
将对象的创建与使用分离
具体实现:单例、 原型、工厂方法、抽象工厂、建造者
创建型模式
用于描述如何将类或者对象按照某种布局组成更大的结构
具体实现:代理、适配器、桥接、装饰、外观、享元、组合
结构型模式
用于描述类或者对象之间怎么样相互协作共同完成单个独享无法完成的任务
具体实现:模板方法、策略、命令、责任链、状态、观察者、中介者、迭代器、访问者、备忘录、解释器
行为型模式
模式分类
类名称、属性、方法
+:公有访问权限
-:表示私有访问权限
#:表示保护访问权限
访问权限
访问权限 属性名称:属性类型
属性
访问权限 方法名称(参数列表)[:返回值类型]
方法
类表示方式
单项关联
双向关联
自关联
关联关系
一对多
菱形指向整体(一)
聚合关系
更加强烈的关系
组合双方缺一不可
实心菱形表示,指向整体一方
组合关系
方法内部的局部变量或者形参
引用外部类,需要外部类支持
使用虚线箭头表示
依赖关系
父类与子类之间的关系
空心箭头实线表示,指向父类
继承关系
实现接口
使用带空心三角箭头虚线表示
实现关系
类与类之间关系
类表示法
UML
扩展开放,修改关闭
开闭原则
子类只能扩展功能不能修改父类的的原有功能
所用引用基类的地方可以替换为子类
里氏代换原则
两个类直接关联,尽可能的将关联部分进行抽象,共同继承抽象类
依赖倒转原则
对接口的依赖,不要依赖不需要的接口
采用接口方法拆分
接口隔离原则
最少知识法则
尽量减少与陌生人对话,具体实现:代理模式
迪米特法则
尽量先考虑聚合或者组合关系进行依赖,然后再考虑继承
合成复用原则
软件设计原则
静态变量
静态代码块
饿汉式
1、静态方法判断为null进行构建,否则直接返回
2、判断过程可能发生多线程都通过,则也会创建多个实例,于是需要对静态方法增加类锁
3、由于类锁时比较重量级锁,所以会影响性能,于是需要将锁细化,进行双重检查锁
4、双重检查锁在外层判断对象是否为空的时候,有可能有一个线程已经在创建对象了,但是可能发生创建对象的指令发生指令重排序,导致外层可能存在线程判断对象不为null,但是该对象还未实例化,所以需要对静态变量对象增加volatile,防止指令重排序
5、利用静态内部类的懒加载特性,在静态内部类增加一个静态终态对象属性,在外部增加一个静态方法,在调用该方法的时候,静态内部类才会被加载,并且被final修饰防止指令重排序
懒汉式
利用ObjectOutprintStream写出,然后读回,会得到另个不同的实例
解决:在单例类中定义一个readResolve()方法
序列化
利用反射获取类的构造方法,并且将私有构造权限通过,即可创建新的对象
反射
破坏单例模式
单例模式
工厂封装创建产品方法,根据具体类型创建不同产品,但返回一样的接口
具体使用方再去根据客户的类型去调用工厂类创建产品
工厂类的创建产品的方法改为静态,使用方直接调用即可
简单工厂
相对于抽象工厂来说,只能生产同一级别的产品
工厂方法模式
生成一个产品族的产品,也就是抽象工厂定义生产不同种类商品的接口,不同的具体工厂按照接口定义实现不同种类产品(属于一个产品族)
抽象工厂模式
简单工厂+配置文件达到工厂类与具体产品进行解构
模式扩展
将使用者与创建者解耦,使得使用者不用关系产品创建的细节
是对多个不同产品级的产品族的创建
利于新的产品族的创建
使用场景
工厂模式
用一个已经创建的实例对象作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象
在使用clone方法克隆的时候,新创建的对象本身是深克隆,但是其引用类型的属性还是浅克隆(依然指向原来的同一个对象)
浅克隆
新对象的引用类型的属性也会复制一份(不是指向的同一个对象)
实现:采用序列化,然后反序列化回来就是一个深克隆
深克隆
原型模式
创建复杂对象
将组装和部件构建分离
扩展:lombok.builder
建造者模式
创建型模式(5)
静态代理
需要实现接口
JDK代理
引入三方包
创建Enhancer
CGlib代理
动态代理
代理模式
类适配器(违背合成复用):适配器类实现正常业务接口,并且继承被适配对象
对象适配器:将继承改为集合,通过构造器传入被适配者对象,在接口方法调用成员属性的方法达到接口适配的目的
适配器模式
在原有的对象增加一点修饰或者说是扩展
需要定义一个抽象装饰着类,需要继承原对象的抽象类
在抽象装饰者类聚合原有对象,并且实现抽象类方法
实现
装饰者模式
用于在两个维度独立变化的场景
播放器需要支持在不同操作系统下播放,同时需要支持不同的视频格式文件播放
1.将两个不同变化的维度户进行独立抽象化
2.在抽象层在一个抽象类聚合另外一个抽象类
3.不同的变化通过实现抽象类体现
4.使用时传入具体的实现类
桥接模式
也叫门面模式
将多个子系统类用一个门面类进行一对多的组合关系依赖,到达在门面类统一管理
外观模式
将公有的方法或者属性进行抽象化,各个节点对外统一接口,部分类型接口部分实现,达到对外统一化,并且节点之间通过聚合关系进行组合
应用场景:树结构数据,公共的属性或者方法进行抽象,各个节点之间进行组合
组合模式
单例共享一个享元对象,共有使用
共有
内部状态
形参传递动态
外部状态
实例:Integer.valueOf()
享元模式
结构型模式(7)
将能复用的方法进行抽象
不能复用的方法进行具体类的实现
模板方法模式
多种算法:多态完成选择具体算法
使用多分支判断替换
策略模式
将命令发起者与命令执行者解耦
实现:利用命令类集成命令发起的信息与执行者聚合
命令模式
链式处理
filterChain
责任链模式
状态的变化与具体的动作具有影响作用
默认实现采用if判断或者switch
将分支判断进行对象化,将动作封装,每个状态类具有每个动作,自己判定当前状态的动作可执行
状态模式
监听器
JDK java.util.Observable
观察者模式
多个之间依赖交错复杂
利用一个中介者来维护关联关系
中介者模式
集合迭代器
迭代器用于遍历集合信息
迭代器模式
将元素方法执行交由给访问者来执行
访问者模式
快照模式
对一个类的内部状态进行快照存储,方便在需要的是时候进行恢复
备忘录模式
解释器模式
行为型模式(11)
具体实现
设计模式
建立一个服务端模拟一个数据库引擎
由MyCat服务端去与真实的mysql服务接口,用户只需要与MyCat进行交互
实体数据库和表还是需要在对应的物理数据库中进行创建
System标签
user标签
firewall标签
1.sever.xml
不同的表结构分布到不同的物理数据库中
相同的表结构,数据按照不同的分片规则分布到不同的物理数据库中
table
2.schema.xml
范围分片
取模分片
范围取模分片
枚举分片
hash分片
3.rule.xml
自定义id生成器
4.sequence.xml
配置文件
mysql的主从复制:主数据库开启bin log日志将事务提交生成一个事件保存到日志
从数据库定期(单独线程)拉取日志数据,生成relay日志(中继日志),又开启一个读取日志写入到从数据库
双主备
双主项目进行复制
双主双从
mycat开始balance,进行负载双主或者单主替换
读写分离
MyCat
Java架构之路
0 条评论
下一页